mirror of
https://github.com/ZaidElkurdi/AssistantPlus.git
synced 2025-01-22 11:28:31 +00:00
- Capture Group Commands
- Run commands with NSTask
This commit is contained in:
parent
611764adf4
commit
6ada354e53
@ -1 +1 @@
|
||||
2
|
||||
58
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:assistantplus_root_helper.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>EC9F4657-A65C-4A72-975C-EE3D32554A76</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>assistantplus_root_helper</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>1DDFB15FDAC578A4447EF06D6A0EB8914E453AB8</key>
|
||||
<string>https://bitbucket.org/ZaidElkurdi/assistantplus.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>assistant+/assistantplus_root_helper/assistantplus_root_helper.xcodeproj</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>1DDFB15FDAC578A4447EF06D6A0EB8914E453AB8</key>
|
||||
<string>../../../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>https://bitbucket.org/ZaidElkurdi/assistantplus.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>111</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>1DDFB15FDAC578A4447EF06D6A0EB8914E453AB8</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>1DDFB15FDAC578A4447EF06D6A0EB8914E453AB8</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>Assistant2</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
Binary file not shown.
22
assistant+/assistantplusapp/APCaptureGroupCommand.h
Normal file
22
assistant+/assistantplusapp/APCaptureGroupCommand.h
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// APCaptureGroupCommand.h
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface APCaptureGroupCommand : NSObject
|
||||
@property (nonatomic, strong) NSString *name;
|
||||
@property (nonatomic, strong) NSArray *variables;
|
||||
@property (nonatomic, strong) NSArray *conditionals;
|
||||
@property (nonatomic, strong) NSString *trigger;
|
||||
@property (nonatomic, strong) NSString *command;
|
||||
@property (nonatomic, strong) NSString *uuid;
|
||||
|
||||
-(id)initWithDictionary:(NSDictionary*)dict;
|
||||
- (NSDictionary*)dictionaryRepresentation;
|
||||
|
||||
@end
|
41
assistant+/assistantplusapp/APCaptureGroupCommand.m
Normal file
41
assistant+/assistantplusapp/APCaptureGroupCommand.m
Normal file
@ -0,0 +1,41 @@
|
||||
//
|
||||
// APCaptureGroupCommand.m
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "APCaptureGroupCommand.h"
|
||||
|
||||
@implementation APCaptureGroupCommand
|
||||
|
||||
-(id)initWithDictionary:(NSDictionary*)dict {
|
||||
if (self = [super init]) {
|
||||
NSString *name = dict[@"name"];
|
||||
NSArray *variables = dict[@"variables"];
|
||||
NSArray *conditionals = dict[@"conditionals"];
|
||||
NSString *command = dict[@"command"];
|
||||
NSString *trigger = dict[@"trigger"];
|
||||
NSString *uuid = dict[@"uuid"];
|
||||
|
||||
self.name = name;
|
||||
self.variables = variables ? variables : [NSArray array];
|
||||
self.conditionals = conditionals ? conditionals : [NSArray array];
|
||||
self.command = command ? command : @"";
|
||||
self.trigger = trigger ? trigger : @"";
|
||||
self.uuid = uuid ? uuid : [NSString stringWithFormat:@"%@", [NSUUID UUID]];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSDictionary*)dictionaryRepresentation {
|
||||
return @{@"name" : self.name ? self.name : @"Untitled",
|
||||
@"variables" : self.variables ? self.variables : [NSArray array],
|
||||
@"conditionals" : self.conditionals ? self.conditionals : [NSArray array],
|
||||
@"command" : self.command ? self.command : @"",
|
||||
@"trigger" : self.trigger ? self.trigger : @"",
|
||||
@"uuid" : self.uuid ? self.uuid : [NSString stringWithFormat:@"%@", [NSUUID UUID]]};
|
||||
}
|
||||
|
||||
@end
|
@ -3,7 +3,7 @@
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 3/22/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserve.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
@ -20,6 +20,12 @@
|
||||
B86E67181ACE7AC0007C6014 /* APCustomReply.m in Sources */ = {isa = PBXBuildFile; fileRef = B88C0AE51AC32CEF00D4D107 /* APCustomReply.m */; };
|
||||
B86E67191ACE7AC0007C6014 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B88C0A871ABF7D6200D4D107 /* main.m */; };
|
||||
B86E671B1ACE7C66007C6014 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B86E671A1ACE7C66007C6014 /* Default-568h@2x.png */; };
|
||||
B8B2D2411ADD875900FEE8C3 /* CaptureGroupCommandsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8B2D2401ADD875900FEE8C3 /* CaptureGroupCommandsViewController.m */; };
|
||||
B8B2D2471ADD879500FEE8C3 /* APCaptureGroupCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = B8B2D2461ADD879500FEE8C3 /* APCaptureGroupCommand.m */; };
|
||||
B8B2D24A1ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8B2D2491ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.m */; };
|
||||
B8B2D24B1ADD8EE900FEE8C3 /* CaptureGroupCommandsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8B2D2401ADD875900FEE8C3 /* CaptureGroupCommandsViewController.m */; };
|
||||
B8B2D24C1ADD8EED00FEE8C3 /* CaptureGroupCommandDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B8B2D2491ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.m */; };
|
||||
B8B2D24D1ADD8EF100FEE8C3 /* APCaptureGroupCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = B8B2D2461ADD879500FEE8C3 /* APCaptureGroupCommand.m */; };
|
||||
B8EC46D41AC6422100ED3836 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B88C0A7C1ABF79AA00D4D107 /* AppDelegate.m */; };
|
||||
B8EC46D51AC6422100ED3836 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B88C0A7F1ABF79AA00D4D107 /* MainViewController.m */; };
|
||||
B8EC46D61AC6422100ED3836 /* ActivatorListenersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B88C0ACD1ABF8F7C00D4D107 /* ActivatorListenersViewController.m */; };
|
||||
@ -82,6 +88,12 @@
|
||||
B88C0AE21AC32C2A00D4D107 /* CustomReplyDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomReplyDetailViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
B88C0AE41AC32CEF00D4D107 /* APCustomReply.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APCustomReply.h; sourceTree = SOURCE_ROOT; };
|
||||
B88C0AE51AC32CEF00D4D107 /* APCustomReply.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APCustomReply.m; sourceTree = SOURCE_ROOT; };
|
||||
B8B2D23F1ADD875900FEE8C3 /* CaptureGroupCommandsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CaptureGroupCommandsViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
B8B2D2401ADD875900FEE8C3 /* CaptureGroupCommandsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CaptureGroupCommandsViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
B8B2D2451ADD879500FEE8C3 /* APCaptureGroupCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APCaptureGroupCommand.h; sourceTree = SOURCE_ROOT; };
|
||||
B8B2D2461ADD879500FEE8C3 /* APCaptureGroupCommand.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = APCaptureGroupCommand.m; sourceTree = SOURCE_ROOT; };
|
||||
B8B2D2481ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CaptureGroupCommandDetailViewController.h; sourceTree = SOURCE_ROOT; };
|
||||
B8B2D2491ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CaptureGroupCommandDetailViewController.m; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -174,6 +186,10 @@
|
||||
B88C0A7E1ABF79AA00D4D107 /* MainViewController.h */,
|
||||
B88C0A7F1ABF79AA00D4D107 /* MainViewController.m */,
|
||||
B834EFF31AC5EF2C00CF009E /* LaunchScreen2.xib */,
|
||||
B8B2D23F1ADD875900FEE8C3 /* CaptureGroupCommandsViewController.h */,
|
||||
B8B2D2401ADD875900FEE8C3 /* CaptureGroupCommandsViewController.m */,
|
||||
B8B2D2481ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.h */,
|
||||
B8B2D2491ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.m */,
|
||||
B86E66D81ACD1991007C6014 /* PluginsViewController.h */,
|
||||
B86E66D91ACD1991007C6014 /* PluginsViewController.m */,
|
||||
B88C0ADE1AC32C2000D4D107 /* CustomRepliesViewController.h */,
|
||||
@ -188,6 +204,8 @@
|
||||
B88C0AD21ABF968B00D4D107 /* APActivatorListener.m */,
|
||||
B88C0AE41AC32CEF00D4D107 /* APCustomReply.h */,
|
||||
B88C0AE51AC32CEF00D4D107 /* APCustomReply.m */,
|
||||
B8B2D2451ADD879500FEE8C3 /* APCaptureGroupCommand.h */,
|
||||
B8B2D2461ADD879500FEE8C3 /* APCaptureGroupCommand.m */,
|
||||
B88C0A871ABF7D6200D4D107 /* main.m */,
|
||||
B88C0AB61ABF838500D4D107 /* Info.plist */,
|
||||
B88C0AC11ABF864D00D4D107 /* LaunchScreen.xib */,
|
||||
@ -353,12 +371,15 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B8EC46D41AC6422100ED3836 /* AppDelegate.m in Sources */,
|
||||
B8B2D2411ADD875900FEE8C3 /* CaptureGroupCommandsViewController.m in Sources */,
|
||||
B8EC46D51AC6422100ED3836 /* MainViewController.m in Sources */,
|
||||
B8EC46D61AC6422100ED3836 /* ActivatorListenersViewController.m in Sources */,
|
||||
B8EC46D71AC6422100ED3836 /* CustomRepliesViewController.m in Sources */,
|
||||
B8B2D24A1ADD87AB00FEE8C3 /* CaptureGroupCommandDetailViewController.m in Sources */,
|
||||
B8EC46D81AC6422100ED3836 /* CustomReplyDetailViewController.m in Sources */,
|
||||
B86E66DA1ACD1991007C6014 /* PluginsViewController.m in Sources */,
|
||||
B8EC46D91AC6422100ED3836 /* ListenerDetailViewController.m in Sources */,
|
||||
B8B2D2471ADD879500FEE8C3 /* APCaptureGroupCommand.m in Sources */,
|
||||
B8EC46DA1AC6422100ED3836 /* APActivatorListener.m in Sources */,
|
||||
B8EC46DB1AC6422100ED3836 /* APCustomReply.m in Sources */,
|
||||
B8EC46DC1AC6422100ED3836 /* main.m in Sources */,
|
||||
@ -378,12 +399,15 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
B86E67101ACE7AC0007C6014 /* AppDelegate.m in Sources */,
|
||||
B8B2D24B1ADD8EE900FEE8C3 /* CaptureGroupCommandsViewController.m in Sources */,
|
||||
B86E67111ACE7AC0007C6014 /* MainViewController.m in Sources */,
|
||||
B86E67121ACE7AC0007C6014 /* PluginsViewController.m in Sources */,
|
||||
B86E67131ACE7AC0007C6014 /* CustomRepliesViewController.m in Sources */,
|
||||
B86E67141ACE7AC0007C6014 /* CustomReplyDetailViewController.m in Sources */,
|
||||
B8B2D24C1ADD8EED00FEE8C3 /* CaptureGroupCommandDetailViewController.m in Sources */,
|
||||
B86E67151ACE7AC0007C6014 /* ActivatorListenersViewController.m in Sources */,
|
||||
B86E67161ACE7AC0007C6014 /* ListenerDetailViewController.m in Sources */,
|
||||
B8B2D24D1ADD8EF100FEE8C3 /* APCaptureGroupCommand.m in Sources */,
|
||||
B86E67171ACE7AC0007C6014 /* APActivatorListener.m in Sources */,
|
||||
B86E67181ACE7AC0007C6014 /* APCustomReply.m in Sources */,
|
||||
B86E67191ACE7AC0007C6014 /* main.m in Sources */,
|
||||
|
Binary file not shown.
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges</key>
|
||||
<true/>
|
||||
<key>SnapshotAutomaticallyBeforeSignificantChanges</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// CaptureGroupCommandDetailViewController.h
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "APCaptureGroupCommand.h"
|
||||
|
||||
@protocol CommandDetailDelegate <NSObject>
|
||||
- (void)commandDidChange:(APCaptureGroupCommand*)command;
|
||||
@end
|
||||
|
||||
@interface CaptureGroupCommandDetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UIActionSheetDelegate, UITextFieldDelegate>
|
||||
@property (assign) id<CommandDetailDelegate> delegate;
|
||||
- (id)initWithCommand:(APCaptureGroupCommand*)command;
|
||||
@end
|
@ -0,0 +1,487 @@
|
||||
//
|
||||
// CaptureGroupCommandDetailViewController.m
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CaptureGroupCommandDetailViewController.h"
|
||||
|
||||
typedef enum {
|
||||
APNameCell = 1,
|
||||
APTriggerCell = 2,
|
||||
APCommandCell = 3
|
||||
} APTextCellType;
|
||||
|
||||
typedef enum {
|
||||
APWhenValue = 1,
|
||||
APSetValue = 2,
|
||||
} APConditionalEditingType;
|
||||
|
||||
@interface CaptureGroupCommandDetailViewController ()
|
||||
@property (strong, nonatomic) APCaptureGroupCommand *currCommand;
|
||||
@property (strong, nonatomic) UITextField *nameField;
|
||||
@property (strong, nonatomic) UITextField *triggerField;
|
||||
@property (strong, nonatomic) UITextField *commandField;
|
||||
@property (strong, nonatomic) UITableView *tableView;
|
||||
|
||||
@property (strong, nonatomic) NSMutableArray *mutableVariables;
|
||||
@property (strong, nonatomic) NSMutableArray *mutableConditionals;
|
||||
@property (nonatomic) BOOL didChange;
|
||||
@property (nonatomic) NSInteger conditionalToEdit;
|
||||
@property (nonatomic) APConditionalEditingType editingType;
|
||||
@end
|
||||
|
||||
@implementation CaptureGroupCommandDetailViewController
|
||||
|
||||
- (id)initWithCommand:(APCaptureGroupCommand*)command {
|
||||
if (self = [super init]) {
|
||||
self.currCommand = command;
|
||||
self.mutableVariables = command.variables ? [command.variables mutableCopy] : [NSMutableArray array];
|
||||
|
||||
if (command.conditionals && command.conditionals.count > 0) {
|
||||
self.mutableConditionals = [[NSMutableArray alloc] init];
|
||||
for (NSArray *currConditional in command.conditionals) {
|
||||
[self.mutableConditionals addObject:[currConditional mutableCopy]];
|
||||
}
|
||||
} else {
|
||||
self.mutableConditionals = [NSMutableArray array];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
UIColor *backgroundColor = [UIColor colorWithWhite:.9f alpha:1.0];
|
||||
self.view.backgroundColor = backgroundColor;
|
||||
|
||||
self.tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
|
||||
self.tableView.dataSource = self;
|
||||
self.tableView.delegate = self;
|
||||
|
||||
CGFloat expectedHeight = [[self getHelpMessage] boundingRectWithSize:CGSizeMake(self.view.frame.size.width-20, CGFLOAT_MAX)
|
||||
options:NSStringDrawingUsesLineFragmentOrigin
|
||||
attributes:@{NSFontAttributeName : [UIFont fontWithName:@"Helvetica" size:14]}
|
||||
context:nil].size.height;
|
||||
|
||||
UIView *msgView = [[UIView alloc] initWithFrame:CGRectMake(0, 10, self.view.frame.size.width, expectedHeight+30)];
|
||||
UILabel *msgLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 20, self.view.frame.size.width-20, expectedHeight)];
|
||||
msgLabel.lineBreakMode = NSLineBreakByWordWrapping;
|
||||
msgLabel.numberOfLines = 0;
|
||||
msgLabel.text = [self getHelpMessage];
|
||||
msgLabel.textAlignment = NSTextAlignmentLeft;
|
||||
msgLabel.font = [UIFont fontWithName:@"Helvetica" size:14];
|
||||
msgLabel.textColor = [UIColor darkGrayColor];
|
||||
[msgView addSubview:msgLabel];
|
||||
|
||||
self.tableView.tableFooterView = msgView;
|
||||
[self.view addSubview:self.tableView];
|
||||
|
||||
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPressed:)];
|
||||
[self.navigationItem setRightBarButtonItem:addButton];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(saveChangesIfNecessary)
|
||||
name:UIApplicationWillResignActiveNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
[self saveChangesIfNecessary];
|
||||
}
|
||||
|
||||
- (void)saveChangesIfNecessary {
|
||||
if (self.didChange) {
|
||||
self.currCommand.conditionals = self.mutableConditionals;
|
||||
self.currCommand.trigger = self.triggerField.text;
|
||||
self.currCommand.variables = self.mutableVariables;
|
||||
self.currCommand.name = self.nameField.text;
|
||||
self.currCommand.command = self.commandField.text;
|
||||
[self.delegate commandDidChange:self.currCommand];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 5;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
if (section == 0) {
|
||||
return 1;
|
||||
} else if (section == 1) {
|
||||
return 1;
|
||||
} else if (section == 2) {
|
||||
return self.mutableVariables.count;
|
||||
} else if (section == 3) {
|
||||
return self.mutableConditionals.count;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.section == 0) {
|
||||
return [self createTextCell:APNameCell];
|
||||
} else if (indexPath.section == 1) {
|
||||
return [self createTextCell:APTriggerCell];
|
||||
} else if (indexPath.section == 2) {
|
||||
return [self createVariableCellForIndex:indexPath.row];
|
||||
} else if (indexPath.section == 3) {
|
||||
return [self createConditionalCellForIndex:indexPath.row];
|
||||
} else if (indexPath.section == 4) {
|
||||
return [self createTextCell:APCommandCell];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.section == 3) {
|
||||
return 200;
|
||||
}
|
||||
|
||||
return 50;
|
||||
}
|
||||
|
||||
- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
||||
switch (section) {
|
||||
case 0:
|
||||
return @"";
|
||||
break;
|
||||
case 1:
|
||||
return @"";
|
||||
case 2:
|
||||
return @"Variables";
|
||||
case 3:
|
||||
return @"Conditionals";
|
||||
case 4:
|
||||
return @"Command";
|
||||
default:
|
||||
return @"";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Cell Helpers
|
||||
|
||||
- (UITableViewCell*)createTextCell:(APTextCellType)cellType {
|
||||
UITableViewCell *cell = [[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 60, 50)];
|
||||
|
||||
UITextField *nameField = [[UITextField alloc] initWithFrame:CGRectMake(80, 2, self.view.frame.size.width-60, 50)];
|
||||
nameField.delegate = self;
|
||||
nameField.tag = -1;
|
||||
nameField.returnKeyType = UIReturnKeyDone;
|
||||
|
||||
if (cellType == APNameCell) {
|
||||
nameLabel.text = @"Name:";
|
||||
nameField.text = self.currCommand.name;
|
||||
self.nameField = nameField;
|
||||
|
||||
CGRect oldFrame = self.nameField.frame;
|
||||
oldFrame.origin.x = 70;
|
||||
oldFrame.size.width = self.view.frame.size.width - 70;
|
||||
nameField.frame = oldFrame;
|
||||
self.nameField.frame = oldFrame;
|
||||
} else if (cellType == APTriggerCell) {
|
||||
nameLabel.text = @"Trigger:";
|
||||
nameField.text = self.currCommand.trigger;
|
||||
self.triggerField = nameField;
|
||||
} else if (cellType == APCommandCell) {
|
||||
nameLabel.hidden = YES;
|
||||
nameField.text = self.currCommand.command;
|
||||
self.commandField = nameField;
|
||||
|
||||
CGRect oldFrame = self.commandField.frame;
|
||||
oldFrame.origin.x = 5;
|
||||
oldFrame.size.width = self.view.frame.size.width - 5;
|
||||
self.commandField.frame = oldFrame;
|
||||
}
|
||||
|
||||
[cell.contentView addSubview:nameLabel];
|
||||
[cell.contentView addSubview:nameField];
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (UITableViewCell*)createVariableCellForIndex:(NSInteger)index {
|
||||
UITableViewCell *cell = [[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
UITextField *nameField = [[UITextField alloc] initWithFrame:CGRectMake(10, 2, self.view.frame.size.width-10, 50)];
|
||||
nameField.delegate = self;
|
||||
nameField.tag = 100+index;
|
||||
nameField.returnKeyType = UIReturnKeyDone;
|
||||
nameField.placeholder = @"Unnamed Variable";
|
||||
|
||||
NSString *variableName = [self.mutableVariables objectAtIndex:index];
|
||||
if (variableName.length > 0) {
|
||||
nameField.text = variableName;
|
||||
} else {
|
||||
nameField.text = @"";
|
||||
}
|
||||
|
||||
[cell.contentView addSubview:nameField];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (UITableViewCell*)createConditionalCellForIndex:(NSInteger)index {
|
||||
UITableViewCell *cell = [[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
UILabel *whenlabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 70, 50)];
|
||||
whenlabel.text = @"When:";
|
||||
|
||||
UILabel *equalsLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 50, 70, 50)];
|
||||
equalsLabel.text = @"Equals:";
|
||||
|
||||
UILabel *setLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 100, 70, 50)];
|
||||
setLabel.text = @"Set:";
|
||||
|
||||
UILabel *toLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 150, 70, 50)];
|
||||
toLabel.text = @"To:";
|
||||
|
||||
UIButton *whenField = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
whenField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
whenField.frame = CGRectMake(70, 2, self.view.frame.size.width-15, 50);
|
||||
whenField.tag = index;
|
||||
[whenField addTarget:self action:@selector(whenButtonPressedForIndex:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
NSString *whenVariableName = self.mutableConditionals[index][0];
|
||||
if (whenVariableName && whenVariableName.length > 0) {
|
||||
[whenField setTitle:whenVariableName forState:UIControlStateNormal];
|
||||
[whenField setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
|
||||
} else {
|
||||
[whenField setTitle:@"Select Variable..." forState:UIControlStateNormal];
|
||||
[whenField setTitleColor:[UIColor colorWithWhite:0.7 alpha:1.0] forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
UITextField *equalsField = [[UITextField alloc] initWithFrame:CGRectMake(80, 57, self.view.frame.size.width-80, 35)];
|
||||
equalsField.returnKeyType = UIReturnKeyDone;
|
||||
equalsField.font = [UIFont systemFontOfSize:17];
|
||||
equalsField.tag = 1000 + index;
|
||||
equalsField.placeholder = @"A Value";
|
||||
|
||||
NSString *equalsValue = self.mutableConditionals[index][1];
|
||||
if (equalsValue.length > 0) {
|
||||
equalsField.text = equalsValue;
|
||||
} else {
|
||||
equalsField.text = @"";
|
||||
}
|
||||
equalsField.delegate = self;
|
||||
|
||||
UIButton *setField = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
setField.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||
setField.frame = CGRectMake(50, 100, self.view.frame.size.width-75, 50);
|
||||
setField.tag = index;
|
||||
[setField addTarget:self action:@selector(setButtonPressedForIndex:) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
NSString *setVariableName = self.mutableConditionals[index][2];
|
||||
if (setVariableName && setVariableName.length > 0) {
|
||||
[setField setTitle:setVariableName forState:UIControlStateNormal];
|
||||
[setField setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
|
||||
} else {
|
||||
[setField setTitle:@"Select Variable..." forState:UIControlStateNormal];
|
||||
[setField setTitleColor:[UIColor colorWithWhite:0.7 alpha:1.0] forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
UITextField *toField = [[UITextField alloc] initWithFrame:CGRectMake(40, 158, self.view.frame.size.width-80, 35)];
|
||||
toField.returnKeyType = UIReturnKeyDone;
|
||||
toField.tag = 2000 + index;
|
||||
toField.font = [UIFont systemFontOfSize:17];
|
||||
toField.placeholder = @"A Value";
|
||||
|
||||
NSString *toValue = self.mutableConditionals[index][3];
|
||||
if (toValue.length > 0) {
|
||||
toField.text = toValue;
|
||||
} else {
|
||||
toField.text = @"";
|
||||
}
|
||||
toField.delegate = self;
|
||||
|
||||
[cell.contentView addSubview:whenlabel];
|
||||
[cell.contentView addSubview:equalsLabel];
|
||||
[cell.contentView addSubview:setLabel];
|
||||
[cell.contentView addSubview:toLabel];
|
||||
|
||||
[cell.contentView addSubview:equalsField];
|
||||
[cell.contentView addSubview:toField];
|
||||
[cell.contentView addSubview:whenField];
|
||||
[cell.contentView addSubview:setField];
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.section == 0 || indexPath.section == 1 || indexPath.section == 4) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return UITableViewCellEditingStyleDelete;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||
|
||||
if (indexPath.section == 2) {
|
||||
[self.mutableVariables removeObjectAtIndex:indexPath.row];
|
||||
} else if (indexPath.section == 3) {
|
||||
[self.mutableConditionals removeObjectAtIndex:indexPath.row];
|
||||
}
|
||||
|
||||
[self.tableView beginUpdates];
|
||||
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.tableView endUpdates];
|
||||
self.didChange = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UI Delegates
|
||||
|
||||
- (void)addPressed:(id)sender {
|
||||
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Add new..." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:nil, nil];
|
||||
[actionSheet addButtonWithTitle:@"Variable"];
|
||||
[actionSheet addButtonWithTitle:@"Conditional"];
|
||||
actionSheet.cancelButtonIndex = 0;
|
||||
actionSheet.tag = 1;
|
||||
[actionSheet showInView:self.view];
|
||||
}
|
||||
|
||||
- (void)whenButtonPressedForIndex:(UIButton*)button {
|
||||
self.conditionalToEdit = button.tag;
|
||||
self.editingType = APWhenValue;
|
||||
[self displayVariableSelection];
|
||||
}
|
||||
|
||||
- (void)setButtonPressedForIndex:(UIButton*)button {
|
||||
self.conditionalToEdit = button.tag;
|
||||
self.editingType = APSetValue;
|
||||
[self displayVariableSelection];
|
||||
}
|
||||
|
||||
- (void)displayVariableSelection {
|
||||
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Select Variable..." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:nil, nil];
|
||||
for (NSString *name in self.mutableVariables) {
|
||||
if (name.length > 0) {
|
||||
[actionSheet addButtonWithTitle:name];
|
||||
}
|
||||
}
|
||||
actionSheet.tag = 2;
|
||||
actionSheet.cancelButtonIndex = 0;
|
||||
[actionSheet showInView:self.view];
|
||||
}
|
||||
|
||||
- (void)addOptionsSheetClickedButtonAtIndex:(NSInteger)buttonIndex {
|
||||
NSInteger section;
|
||||
NSInteger row;
|
||||
if (buttonIndex == 1) {
|
||||
//variable
|
||||
section = 2;
|
||||
[self.mutableVariables addObject:@""];
|
||||
row = self.mutableVariables.count-1;
|
||||
|
||||
} else if (buttonIndex == 2) {
|
||||
//conditional
|
||||
section = 3;
|
||||
[self.mutableConditionals addObject:[NSMutableArray arrayWithObjects:@"", @"", @"", @"", nil]];
|
||||
row = self.mutableConditionals.count-1;
|
||||
} else {
|
||||
//Is cancel button
|
||||
return;
|
||||
}
|
||||
|
||||
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:row inSection:section];
|
||||
|
||||
[self.tableView beginUpdates];
|
||||
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.tableView endUpdates];
|
||||
}
|
||||
|
||||
- (void)variableSelectionSheetClickedButtonAtIndex:(NSInteger)buttonIndex {
|
||||
NSString *variableName = [self.mutableVariables objectAtIndex:buttonIndex-1];
|
||||
if (self.editingType == APSetValue) {
|
||||
[[self.mutableConditionals objectAtIndex:self.conditionalToEdit] setObject:variableName atIndexedSubscript:2];
|
||||
} else if (self.editingType == APWhenValue) {
|
||||
[[self.mutableConditionals objectAtIndex:self.conditionalToEdit] setObject:variableName atIndexedSubscript:0];
|
||||
}
|
||||
|
||||
[self.tableView beginUpdates];
|
||||
[self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForItem:self.conditionalToEdit inSection:3]] withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.tableView endUpdates];
|
||||
}
|
||||
|
||||
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
|
||||
if (buttonIndex == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionSheet.tag == 1) {
|
||||
[self addOptionsSheetClickedButtonAtIndex:buttonIndex];
|
||||
} else if (actionSheet.tag == 2) {
|
||||
[self variableSelectionSheetClickedButtonAtIndex:buttonIndex];
|
||||
}
|
||||
[self.view endEditing:YES];
|
||||
self.didChange = YES;
|
||||
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
[textField resignFirstResponder];
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
|
||||
if (textField == self.commandField) {
|
||||
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:4] atScrollPosition:UITableViewScrollPositionTop animated:YES];
|
||||
} else if (textField == self.nameField) {
|
||||
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
|
||||
} else if (textField == self.triggerField) {
|
||||
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
|
||||
self.didChange = YES;
|
||||
NSString *newText = [textField.text stringByReplacingCharactersInRange:range withString:string];
|
||||
if (textField.tag - 2000 >= 0) {
|
||||
[[self.mutableConditionals objectAtIndex:textField.tag-2000] setObject:newText atIndexedSubscript:3];
|
||||
} else if (textField.tag - 1000 >= 0) {
|
||||
[[self.mutableConditionals objectAtIndex:textField.tag-1000] setObject:newText atIndexedSubscript:1];
|
||||
} else if (textField.tag - 100 >= 0) {
|
||||
[self.mutableVariables setObject:newText atIndexedSubscript:textField.tag-100];
|
||||
} else if (textField == self.nameField) {
|
||||
self.currCommand.name = newText;
|
||||
} else if (textField == self.triggerField) {
|
||||
self.currCommand.trigger = newText;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
}
|
||||
|
||||
#pragma mark - Helpers
|
||||
|
||||
- (NSString*)getHelpMessage {
|
||||
return @"Enabled: For a listener to appear in Activator it must be enabled\n"
|
||||
"\nPassthrough: If enabled, Assistant+ will continue searching for another Activator listener, custom reply, or plugin to handle the command. If it doesn't find anything to handle the command, Siri will go to its default action. You can add a voice confirmation for your Activator listener if you create a custom reply for the same trigger and then enable passthrough for your listener\n"
|
||||
"\nName: A name to describe your listener. This can be anything and is purely for informational purposes\n"
|
||||
"\nTrigger: The command that will trigger the Activator listener, you must have at least one for the listener to appear in Activator. You may use wildcards in the trigger by using (.*). For example, '(.*)turn on the lights' will trigger on \"Turn on the lights\", \"Siri turn on the lights\", \"Hey Siri please turn on the lights\", etc.\n"
|
||||
"\nOnce you create an Activator listener here you must go to Activator and assign it to an event.";
|
||||
}
|
||||
|
||||
@end
|
@ -0,0 +1,14 @@
|
||||
//
|
||||
// CaptureGroupCommandsViewController.h
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "CaptureGroupCommandDetailViewController.h"
|
||||
|
||||
@interface CaptureGroupCommandsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, CommandDetailDelegate>
|
||||
|
||||
@end
|
168
assistant+/assistantplusapp/CaptureGroupCommandsViewController.m
Normal file
168
assistant+/assistantplusapp/CaptureGroupCommandsViewController.m
Normal file
@ -0,0 +1,168 @@
|
||||
//
|
||||
// CaptureGroupCommandsViewController.m
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "CaptureGroupCommandsViewController.h"
|
||||
#import "APCaptureGroupCommand.h"
|
||||
#import "CPDistributedMessagingCenter.h"
|
||||
|
||||
@interface CaptureGroupCommandsViewController ()
|
||||
@property (strong, nonatomic) UITableView *commandsTable;
|
||||
@end
|
||||
|
||||
@implementation CaptureGroupCommandsViewController {
|
||||
NSMutableArray *savedCommands;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.title = @"Commands";
|
||||
|
||||
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addNewCommand:)];
|
||||
[self.navigationItem setRightBarButtonItem:addButton];
|
||||
|
||||
self.commandsTable = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
|
||||
self.commandsTable.delegate = self;
|
||||
self.commandsTable.dataSource = self;
|
||||
self.commandsTable.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
|
||||
UIColor *backgroundColor = [UIColor colorWithWhite:.9f alpha:1.0];
|
||||
self.commandsTable.backgroundColor = backgroundColor;
|
||||
|
||||
[self.view addSubview:self.commandsTable];
|
||||
|
||||
[self loadCommandsFromFile];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
if ([self.commandsTable indexPathForSelectedRow]) {
|
||||
[self.commandsTable deselectRowAtIndexPath:[self.commandsTable indexPathForSelectedRow] animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
}
|
||||
|
||||
- (void)loadCommandsFromFile {
|
||||
savedCommands = [[NSMutableArray alloc] init];
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
if ([defaults objectForKey:@"captureGroupCommands"]) {
|
||||
NSArray *commands = [defaults objectForKey:@"captureGroupCommands"];
|
||||
for (NSDictionary *currCommand in commands) {
|
||||
APCaptureGroupCommand *command = [[APCaptureGroupCommand alloc] initWithDictionary:currCommand];
|
||||
[savedCommands addObject:command];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)saveCommandsToFile {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableArray *toSave = [[NSMutableArray alloc] init];
|
||||
if (savedCommands) {
|
||||
for (APCaptureGroupCommand *currCommand in savedCommands) {
|
||||
[toSave addObject:[currCommand dictionaryRepresentation]];
|
||||
}
|
||||
[defaults setObject:toSave forKey:@"captureGroupCommands"];
|
||||
[defaults synchronize];
|
||||
}
|
||||
|
||||
#if !(TARGET_IPHONE_SIMULATOR)
|
||||
NSLog(@"Sending back to springobard!");
|
||||
CPDistributedMessagingCenter* center = [CPDistributedMessagingCenter centerNamed:@"com.zaid.applus.springboard"];
|
||||
[center sendMessageName:@"UpdateCaptureGroupCommands" userInfo:@{@"captureGroupCommands" : toSave}];
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - Button Handlers
|
||||
|
||||
- (void)addNewCommand:(id)sender {
|
||||
APCaptureGroupCommand *newCommand = [[APCaptureGroupCommand alloc] init];
|
||||
[savedCommands addObject:newCommand];
|
||||
|
||||
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:savedCommands.count-1 inSection:0];
|
||||
|
||||
[CATransaction begin];
|
||||
[self.commandsTable beginUpdates];
|
||||
[CATransaction setCompletionBlock: ^{
|
||||
[self tableView:self.commandsTable didSelectRowAtIndexPath:newIndexPath];
|
||||
}];
|
||||
[self.commandsTable insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.commandsTable endUpdates];
|
||||
[CATransaction commit];
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDataSource
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"commandCell"];
|
||||
if (!cell) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"commandCell"];
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
}
|
||||
|
||||
APCaptureGroupCommand *currCommand = [savedCommands objectAtIndex:indexPath.row];
|
||||
cell.textLabel.text = currCommand.name.length > 0 ? currCommand.name : @"Untitled Command";
|
||||
cell.detailTextLabel.text = currCommand.trigger.length > 0 ? currCommand.trigger : @"No Trigger Yet";
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
#pragma mark - UITableViewDelegate
|
||||
|
||||
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
APCaptureGroupCommand *selectedCommand = [savedCommands objectAtIndex:indexPath.row];
|
||||
CaptureGroupCommandDetailViewController *detailVC = [[CaptureGroupCommandDetailViewController alloc] initWithCommand:selectedCommand];
|
||||
detailVC.delegate = self;
|
||||
[self.navigationController pushViewController:detailVC animated:YES];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return savedCommands.count;
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||
APCaptureGroupCommand *toDelete = [savedCommands objectAtIndex:indexPath.row];
|
||||
[savedCommands removeObject:toDelete];
|
||||
[self saveCommandsToFile];
|
||||
|
||||
[self.commandsTable beginUpdates];
|
||||
[self.commandsTable deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.commandsTable endUpdates];
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return 60;
|
||||
}
|
||||
|
||||
#pragma mark - CommandDelegate
|
||||
|
||||
- (void)commandDidChange:(APCaptureGroupCommand *)command{
|
||||
for (NSInteger currIndex = 0; currIndex < savedCommands.count; currIndex++) {
|
||||
APCaptureGroupCommand *currCommand = [savedCommands objectAtIndex:currIndex];
|
||||
if ([currCommand.uuid isEqualToString:command.uuid]) {
|
||||
NSLog(@"Replacing %@", currCommand);
|
||||
[savedCommands replaceObjectAtIndex:currIndex withObject:currCommand];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[self saveCommandsToFile];
|
||||
[self.commandsTable reloadData];
|
||||
}
|
||||
|
||||
@end
|
@ -3,6 +3,7 @@
|
||||
#import "CustomRepliesViewController.h"
|
||||
#import "CPDistributedMessagingCenter.h"
|
||||
#import "PluginsViewController.h"
|
||||
#import "CaptureGroupCommandsViewController.h"
|
||||
|
||||
@implementation MainViewController
|
||||
|
||||
@ -54,6 +55,9 @@
|
||||
cellTitle = @"Custom Replies";
|
||||
break;
|
||||
case 2:
|
||||
cellTitle = @"Capture Group Commands";
|
||||
break;
|
||||
case 3:
|
||||
cellTitle = @"Installed Plugins";
|
||||
default:
|
||||
break;
|
||||
@ -64,7 +68,7 @@
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section {
|
||||
@ -97,7 +101,10 @@
|
||||
case 1:
|
||||
[self goToNewVC:[[CustomRepliesViewController alloc] init]];
|
||||
break;
|
||||
case 2: {
|
||||
case 2:
|
||||
[self goToNewVC:[[CaptureGroupCommandsViewController alloc] init]];
|
||||
break;
|
||||
case 3: {
|
||||
#if !(TARGET_IPHONE_SIMULATOR)
|
||||
CPDistributedMessagingCenter *center = [CPDistributedMessagingCenter centerNamed:@"com.zaid.applus.springboard"];
|
||||
NSDictionary *installed = [center sendMessageAndReceiveReplyName:@"getInstalledPlugins" userInfo:nil];
|
||||
|
@ -5,7 +5,7 @@ export TARGET = iphone:clang:latest:8.0
|
||||
export SDKVERSION=8.1
|
||||
|
||||
APPLICATION_NAME = AssistantPlusApp
|
||||
AssistantPlusApp_FILES = main.m AppDelegate.m MainViewController.m APActivatorListener.m ActivatorListenersViewController.m ListenerDetailViewController.m CustomReplyDetailViewController.m CustomRepliesViewController.m APCustomReply.m PluginsViewController.m
|
||||
AssistantPlusApp_FILES = main.m AppDelegate.m MainViewController.m APActivatorListener.m ActivatorListenersViewController.m ListenerDetailViewController.m CustomReplyDetailViewController.m CustomRepliesViewController.m APCustomReply.m PluginsViewController.m CaptureGroupCommandDetailViewController.m CaptureGroupCommandsViewController.m APCaptureGroupCommand.m
|
||||
AssistantPlusApp_FRAMEWORKS = UIKit CoreGraphics QuartzCore
|
||||
AssistantPlusApp_PRIVATE_FRAMEWORKS = AppSupport
|
||||
AssistantPlusApp_CFLAGS = -fobjc-arc
|
||||
|
Binary file not shown.
@ -0,0 +1,21 @@
|
||||
//
|
||||
// APCaptureGroupCommand.h
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface APCaptureGroupCommand : NSObject
|
||||
@property (nonatomic, strong) NSString *name;
|
||||
@property (nonatomic, strong) NSArray *variables;
|
||||
@property (nonatomic, strong) NSArray *conditionals;
|
||||
@property (nonatomic, strong) NSRegularExpression *trigger;
|
||||
@property (nonatomic, strong) NSString *command;
|
||||
@property (nonatomic, strong) NSString *uuid;
|
||||
|
||||
-(id)initWithDictionary:(NSDictionary*)dict;
|
||||
-(NSString*)buildCommandWithValues:(NSArray*)values;
|
||||
@end
|
108
assistant+/assistantpluspluginmanager/APCaptureGroupCommand.m
Normal file
108
assistant+/assistantpluspluginmanager/APCaptureGroupCommand.m
Normal file
@ -0,0 +1,108 @@
|
||||
//
|
||||
// APCaptureGroupCommand.m
|
||||
// AssistantPlusApp
|
||||
//
|
||||
// Created by Zaid Elkurdi on 4/14/15.
|
||||
// Copyright (c) 2015 Zaid Elkurdi. All rights reserved.
|
||||
//
|
||||
|
||||
#import "APCaptureGroupCommand.h"
|
||||
|
||||
@implementation APCaptureGroupCommand {
|
||||
NSArray *variableRanges;
|
||||
}
|
||||
|
||||
-(id)initWithDictionary:(NSDictionary*)dict {
|
||||
if (self = [super init]) {
|
||||
NSString *name = dict[@"name"];
|
||||
NSArray *variables = dict[@"variables"];
|
||||
NSArray *conditionals = dict[@"conditionals"];
|
||||
NSString *command = dict[@"command"];
|
||||
NSString *trigger = dict[@"trigger"];
|
||||
NSString *uuid = dict[@"uuid"];
|
||||
|
||||
self.name = name;
|
||||
self.variables = variables ? variables : [NSArray array];
|
||||
self.conditionals = conditionals ? conditionals : [NSArray array];
|
||||
self.command = command ? command : @"";
|
||||
self.trigger = [NSRegularExpression regularExpressionWithPattern:trigger options:NSRegularExpressionCaseInsensitive error:nil];
|
||||
self.uuid = uuid ? uuid : [NSString stringWithFormat:@"%@", [NSUUID UUID]];
|
||||
[self buildRangeDictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)buildRangeDictionary {
|
||||
NSMutableArray *newVariableRanges = [[NSMutableArray alloc] init];
|
||||
for (NSString *currVariable in self.variables) {
|
||||
NSRange currRange = [self.command rangeOfString:[NSString stringWithFormat:@"[%@]", currVariable]];
|
||||
if (currRange.location != NSNotFound) {
|
||||
[newVariableRanges addObject:@[currVariable, [NSValue valueWithRange:currRange]]];
|
||||
}
|
||||
}
|
||||
|
||||
//Sort the variables by location in order to calculate offset easily
|
||||
variableRanges = [newVariableRanges sortedArrayUsingComparator:^NSComparisonResult(NSArray *first, NSArray *second) {
|
||||
NSRange firstRange = [first[1] rangeValue];
|
||||
NSRange secondRange = [second[1] rangeValue];
|
||||
|
||||
return firstRange.location > secondRange.location;
|
||||
}];
|
||||
}
|
||||
|
||||
-(NSString*)buildCommandWithValues:(NSArray*)values {
|
||||
//First, map the captured values to their variable names
|
||||
NSMutableDictionary *variablesToValues = [[NSMutableDictionary alloc] init];
|
||||
NSInteger currIndex = 0;
|
||||
NSLog(@"Values: %@", values);
|
||||
for (NSString *currValue in values) {
|
||||
NSLog(@"On: %@", currValue);
|
||||
if (currIndex < self.variables.count) {
|
||||
NSLog(@"Adding: %@", currValue);
|
||||
NSString *currVariable = self.variables[currIndex];
|
||||
NSLog(@"Assigning to %@", currVariable);
|
||||
variablesToValues[currVariable] = currValue;
|
||||
}
|
||||
currIndex++;
|
||||
}
|
||||
|
||||
//Second, check the conditionals to see
|
||||
for (NSArray *currRule in self.conditionals) {
|
||||
NSString *conditionalVariable = currRule[0];
|
||||
NSString *conditionalValue = currRule[1];
|
||||
NSString *targetVariable = currRule[2];
|
||||
NSString *targetValue = currRule[3];
|
||||
|
||||
if (!conditionalVariable || !targetVariable || !conditionalValue || !targetValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *actualValue = variablesToValues[conditionalVariable];
|
||||
if (actualValue) {
|
||||
if ([actualValue compare:conditionalValue options:NSCaseInsensitiveSearch] == NSOrderedSame) {
|
||||
variablesToValues[targetVariable] = targetValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSLog(@"Var to Val: %@", variablesToValues);
|
||||
NSMutableString *mutableCommand = [self.command mutableCopy];
|
||||
NSInteger offset = 0;
|
||||
for (NSArray *currVariablePair in variableRanges) {
|
||||
NSString *currVariable = currVariablePair[0];
|
||||
NSString *currValue = variablesToValues[currVariable];
|
||||
NSLog(@"Currently on %@ %@", currVariable, currValue);
|
||||
if (!currVariable || !currValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSRange rangeToReplace = [currVariablePair[1] rangeValue];
|
||||
rangeToReplace.location += offset;
|
||||
|
||||
[mutableCommand replaceCharactersInRange:rangeToReplace withString:currValue];
|
||||
offset += currValue.length - rangeToReplace.length;
|
||||
}
|
||||
return mutableCommand;
|
||||
}
|
||||
|
||||
@end
|
@ -13,6 +13,7 @@
|
||||
@interface APPluginSystem : NSObject<APPluginSystem, LAEventDataSource> {
|
||||
NSMutableArray *plugins;
|
||||
NSMutableArray *activatorListenersArray;
|
||||
NSMutableArray *captureGroupCommandsArray;
|
||||
}
|
||||
|
||||
@property (strong, nonatomic) APSession *currSession;
|
||||
@ -26,5 +27,8 @@
|
||||
//1.0.1
|
||||
- (void)siriSay:(NSString*)message;
|
||||
|
||||
//1.0.2
|
||||
- (void)reloadCaptureGroupCommands:(NSDictionary*)commands;
|
||||
|
||||
- (NSDictionary*)getInstalledPlugins;
|
||||
@end
|
||||
|
@ -9,6 +9,8 @@
|
||||
#import "APPluginSystem.h"
|
||||
#import "APPlugin.h"
|
||||
#import "APActivatorListener.h"
|
||||
#import "APCaptureGroupCommand.h"
|
||||
#import "CPDistributedMessagingCenter.h"
|
||||
|
||||
static NSString *PREFERENCE_PATH = @"/var/mobile/Library/Preferences/com.assistantplus.app.plist";
|
||||
static NSString *EVENT_PREFIX = @"APListener";
|
||||
@ -28,6 +30,7 @@ static NSString *EVENT_PREFIX = @"APListener";
|
||||
|
||||
NSDictionary *pref = [NSDictionary dictionaryWithContentsOfFile:PREFERENCE_PATH];
|
||||
[sharedManager reloadActivatorListeners:pref];
|
||||
[sharedManager reloadCaptureGroupCommands:pref];
|
||||
});
|
||||
return sharedManager;
|
||||
}
|
||||
@ -58,9 +61,12 @@ static NSString *EVENT_PREFIX = @"APListener";
|
||||
|
||||
- (BOOL)handleCommand:(NSString*)command withTokens:(NSSet*)tokens withSession:(APSession*)currSession {
|
||||
self.currSession = currSession;
|
||||
//First check activator listeners
|
||||
|
||||
//Clean up the command
|
||||
NSString *userCommand = [command lowercaseString];
|
||||
userCommand = [userCommand stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
|
||||
//First check activator listeners
|
||||
for (APActivatorListener *currListener in activatorListenersArray) {
|
||||
for (NSRegularExpression *currExpression in currListener.triggers) {
|
||||
NSArray *arrayOfAllMatches = [currExpression matchesInString:userCommand options:0 range:NSMakeRange(0, [userCommand length])];
|
||||
@ -77,6 +83,27 @@ static NSString *EVENT_PREFIX = @"APListener";
|
||||
}
|
||||
}
|
||||
|
||||
//Then check Capture Group Commands
|
||||
for (APCaptureGroupCommand *currCommand in captureGroupCommandsArray) {
|
||||
NSRegularExpression *currExpression = currCommand.trigger;
|
||||
NSArray *arrayOfAllMatches = [currExpression matchesInString:userCommand options:0 range:NSMakeRange(0, [userCommand length])];
|
||||
for (NSTextCheckingResult *match in arrayOfAllMatches) {
|
||||
if (match.numberOfRanges > 0) {
|
||||
NSMutableArray *variableMatches = [[NSMutableArray alloc] init];
|
||||
for (NSInteger currIndex = 1; currIndex < match.numberOfRanges; currIndex++) {
|
||||
NSString *variableValue = [[userCommand substringWithRange:[match rangeAtIndex:currIndex]] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
NSLog(@"Match %ld: %@", (long)currIndex, variableValue);
|
||||
[variableMatches addObject:variableValue];
|
||||
}
|
||||
NSString *commandToExecute = [currCommand buildCommandWithValues:variableMatches];
|
||||
CPDistributedMessagingCenter* center = [CPDistributedMessagingCenter centerNamed:@"com.zaid.applus.springboard"];
|
||||
[center sendMessageName:@"runCommand" userInfo:@{@"command" : commandToExecute}];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Go through the plugins
|
||||
NSLog(@"AP: Got Command \"%@\"", userCommand);
|
||||
for (APPlugin *currPlugin in plugins) {
|
||||
if ([currPlugin handleSpeech:userCommand withTokens:tokens withSession:currSession]) {
|
||||
@ -108,6 +135,22 @@ static NSString *EVENT_PREFIX = @"APListener";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reloadCaptureGroupCommands:(NSDictionary*)commands {
|
||||
NSLog(@"Loading capture group commands!");
|
||||
captureGroupCommandsArray = [[NSMutableArray alloc] init];
|
||||
|
||||
if ([commands objectForKey:@"captureGroupCommands"]) {
|
||||
for (NSDictionary *currCommand in [commands objectForKey:@"captureGroupCommands"]) {
|
||||
id triggerValue = currCommand[@"trigger"];
|
||||
id commandValue = currCommand[@"command"];
|
||||
if (triggerValue && commandValue) {
|
||||
APCaptureGroupCommand *command = [[APCaptureGroupCommand alloc] initWithDictionary:currCommand];
|
||||
[captureGroupCommandsArray addObject:command];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)siriSay:(NSString*)message {
|
||||
[self.currSession sendTextSnippet:message temporary:NO scrollToTop:YES dialogPhase:@"Completion"];
|
||||
}
|
||||
|
@ -18,4 +18,5 @@
|
||||
- (void)getCurrentLocationWithCompletion:(void (^)(NSDictionary *info))completion;
|
||||
- (void)loadPlugins;
|
||||
- (void)gotCurrentLocation:(NSString*)msg withInfo:(NSDictionary*)info;
|
||||
- (void)runCommand:(NSString*)msg withInfo:(NSDictionary*)info;
|
||||
@end
|
||||
|
@ -16,6 +16,12 @@
|
||||
- (void)_relaunchSpringBoardNow;
|
||||
@end
|
||||
|
||||
@interface NSTask : NSObject
|
||||
- (void)setLaunchPath:(NSString*)path;
|
||||
- (void)setArguments:(NSArray*)args;
|
||||
- (void)launch;
|
||||
@end
|
||||
|
||||
|
||||
@implementation APSpringboardUtils {
|
||||
APPluginSystem *pluginManager;
|
||||
@ -33,9 +39,11 @@
|
||||
[center registerForMessageName:@"RetrievedLocation" target:sharedObj selector:@selector(gotCurrentLocation:withInfo:)];
|
||||
[center registerForMessageName:@"UpdateActivatorListeners" target:sharedObj selector:@selector(updateActivatorListeners:withListeners:)];
|
||||
[center registerForMessageName:@"UpdateCustomReplies" target:sharedObj selector:@selector(updateCustomReplies:withReplies:)];
|
||||
[center registerForMessageName:@"UpdateCaptureGroupCommands" target:sharedObj selector:@selector(updateCaptureGroupCommands:withCommands:)];
|
||||
[center registerForMessageName:@"respringForListeners" target:sharedObj selector:@selector(respring)];
|
||||
[center registerForMessageName:@"getInstalledPlugins" target:sharedObj selector:@selector(getInstalledPlugins:withInfo:)];
|
||||
[center registerForMessageName:@"siriSay" target:sharedObj selector:@selector(siriSay:withMessage:)];
|
||||
[center registerForMessageName:@"runCommand" target:sharedObj selector:@selector(runCommand:withInfo:)];
|
||||
}
|
||||
}
|
||||
return sharedObj;
|
||||
@ -54,6 +62,10 @@
|
||||
[pluginManager reloadActivatorListeners:listeners];
|
||||
}
|
||||
|
||||
- (void)updateCaptureGroupCommands:(NSString*)msg withCommands:(NSDictionary*)commands {
|
||||
[pluginManager reloadCaptureGroupCommands:commands];
|
||||
}
|
||||
|
||||
- (void)updateCustomReplies:(NSString*)msg withReplies:(NSDictionary*)dict {
|
||||
[pluginManager reloadCustomRepliesPlugin:dict];
|
||||
}
|
||||
@ -92,6 +104,15 @@
|
||||
[self stopLocationDaemon];
|
||||
}
|
||||
|
||||
- (void)runCommand:(NSString*)msg withInfo:(NSDictionary*)info {
|
||||
NSTask *task = [[NSTask alloc] init];
|
||||
[task setLaunchPath: @"/bin/sh"];
|
||||
NSArray *arguments = @[@"-c",
|
||||
info[@"command"]];
|
||||
[task setArguments:arguments];
|
||||
[task launch];
|
||||
}
|
||||
|
||||
- (void)startLocationDaemon {
|
||||
system("/Applications/AssistantPlusApp.app/assistantplus_root_helper start");
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
@protocol APSharedUtils <NSObject>
|
||||
+ (id)sharedAPUtils;
|
||||
- (void)getCurrentLocationWithCompletion:(void (^)(NSDictionary *info))completion;
|
||||
- (void)runCommand:(NSString*)msg withInfo:(NSDictionary*)info;
|
||||
@end
|
||||
|
||||
@protocol APPluginSystem <NSObject>
|
||||
|
@ -5,7 +5,7 @@ export TARGET_IPHONEOS_DEPLOYMENT_VERSION = 8.0
|
||||
|
||||
TWEAK_NAME = AssistantPlusPluginManager
|
||||
AssistantPlusPluginManager_CFLAGS = -fobjc-arc
|
||||
AssistantPlusPluginManager_FILES = Tweak.xm APPluginSystem.m APPlugin.m APSpringboardUtils.m APActivatorListener.m
|
||||
AssistantPlusPluginManager_FILES = Tweak.xm APPluginSystem.m APPlugin.m APSpringboardUtils.m APActivatorListener.m APCaptureGroupCommand.m
|
||||
AssistantPlusPluginManager_PRIVATE_FRAMEWORKS = AssistantServices SAObjects AppSupport
|
||||
AssistantPlusPluginManager_FRAMEWORKS = Foundation UIKit CoreLocation
|
||||
AssistantPlusPluginManager_LIBRARIES = substrate activator
|
||||
|
@ -13,6 +13,12 @@
|
||||
<FileRef
|
||||
location = "container:APPlugin.m">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:APCaptureGroupCommand.h">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:APCaptureGroupCommand.m">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "container:APPluginSystem.h">
|
||||
</FileRef>
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
||||
13
|
||||
27
|
@ -1,6 +1,6 @@
|
||||
include theos/makefiles/common.mk
|
||||
|
||||
export ARCHS = armv7 arm64
|
||||
export ARCHS = armv7 armv7s arm64
|
||||
export TARGET = iphone:clang:latest:8.0
|
||||
export SDKVERSION=8.1
|
||||
|
||||
|
@ -6,5 +6,5 @@ Description: Control Spotify using Siri! Currently spotifySiriControls supports
|
||||
Maintainer: Zaid Elkurdi
|
||||
Author: Zaid Elkurdi
|
||||
Section: Tweaks
|
||||
Version: 1.0.0-13
|
||||
Installed-Size: 616
|
||||
Version: 1.0.0-27
|
||||
Installed-Size: 888
|
||||
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user