Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 74e3f32438 | |||
| 1f3dbbce75 | |||
| c98154e2c3 | |||
| 5ead539397 | |||
| 3f63f8fefc | |||
| dcb134242d | |||
| 6c4577199c | |||
| 643e87c199 | |||
| bc2c91fc94 | |||
| 7586157fe2 | |||
| 4d3c2cad2c | |||
| d845d8cda9 | |||
| 2efd8d1dca | |||
| 7bbaed6227 | |||
| fdc43c1cd3 | |||
| a9e6e5241c | |||
| 67f4a5477b | |||
| a1eeb57ad6 | |||
| 934abde616 | |||
| 00dd421e20 | |||
| e2b2d5b9e1 | |||
| 86d5b1ae49 | |||
| 3ea350cec1 | |||
| aeaad2986f | |||
| b564f5296a | |||
| 439ec69ab8 | |||
| eda4bdb9c9 |
@@ -1,3 +1,10 @@
|
||||
2.2.0 2015/8/18
|
||||
- Basic accessibility support [starkos]
|
||||
- Added an option to hide the shortcut delete button [oreshinya]
|
||||
- Advertised support for Carthage [Tom Brown]
|
||||
- Bugfix for shortcuts not working after set twice [Roman Sokolov]
|
||||
- Ignore a solo Tab key when recording shortcuts [Roman Sokolov]
|
||||
|
||||
2.1.2 2015/1/28
|
||||
- Better key equivalent handling for non-ASCII layouts.
|
||||
[Dmitry Obukhov]
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.1.2</string>
|
||||
<string>2.2.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.1.2</string>
|
||||
<string>2.2.0</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2014–2015 Vadim Shpakovski. All rights reserved.</string>
|
||||
</dict>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
// These glyphs are missed in Carbon.h
|
||||
enum {
|
||||
@@ -20,7 +21,7 @@ enum {
|
||||
kMASShortcutGlyphPadClear = 0x2327,
|
||||
kMASShortcutGlyphNorthwestArrow = 0x2196,
|
||||
kMASShortcutGlyphSoutheastArrow = 0x2198,
|
||||
} MASShortcutGlyph;
|
||||
};
|
||||
|
||||
NS_INLINE NSString* NSStringFromMASKeyCode(unsigned short ch)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
framework module MASShortcut {
|
||||
umbrella header "Shortcut.h"
|
||||
|
||||
export *
|
||||
module * { export * }
|
||||
}
|
||||
@@ -41,9 +41,15 @@
|
||||
|
||||
- (void) bindShortcutWithDefaultsKey: (NSString*) defaultsKeyName toAction: (dispatch_block_t) action
|
||||
{
|
||||
NSAssert([defaultsKeyName rangeOfString:@"."].location == NSNotFound,
|
||||
@"Illegal character in binding name (“.”), please see http://git.io/x5YS.");
|
||||
NSAssert([defaultsKeyName rangeOfString:@" "].location == NSNotFound,
|
||||
@"Illegal character in binding name (“ ”), please see http://git.io/x5YS.");
|
||||
[_actions setObject:[action copy] forKey:defaultsKeyName];
|
||||
[self bind:defaultsKeyName toObject:[NSUserDefaultsController sharedUserDefaultsController]
|
||||
withKeyPath:[@"values." stringByAppendingString:defaultsKeyName] options:_bindingOptions];
|
||||
[self bind:defaultsKeyName
|
||||
toObject:[NSUserDefaultsController sharedUserDefaultsController]
|
||||
withKeyPath:[@"values." stringByAppendingString:defaultsKeyName]
|
||||
options:_bindingOptions];
|
||||
}
|
||||
|
||||
- (void) breakBindingWithDefaultsKey: (NSString*) defaultsKeyName
|
||||
@@ -103,6 +109,7 @@
|
||||
|
||||
// Just deleting the old shortcut
|
||||
if (newShortcut == nil) {
|
||||
[_shortcuts removeObjectForKey:key];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,4 +95,13 @@ static NSString *const SampleDefaultsKey = @"sampleShortcut";
|
||||
@"Bind shortcut using a default value.");
|
||||
}
|
||||
|
||||
// See issue #64 <http://git.io/x5YS> for rationale and discussion.
|
||||
- (void) testIllegalSymbolsInBindingNames
|
||||
{
|
||||
XCTAssertThrows([_binder bindShortcutWithDefaultsKey:@"foo.bar" toAction:^{}],
|
||||
@"Throw for illegal binding symbols: a dot (“.”).");
|
||||
XCTAssertThrows([_binder bindShortcutWithDefaultsKey:@"foo bar" toAction:^{}],
|
||||
@"Throw for illegal binding symbols: a space (“ ”).");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -21,4 +21,6 @@ typedef enum {
|
||||
/// Returns custom class for drawing control.
|
||||
+ (Class)shortcutCellClass;
|
||||
|
||||
- (void)setAcceptsFirstResponder:(BOOL)value;
|
||||
|
||||
@end
|
||||
|
||||
+115
-19
@@ -3,9 +3,8 @@
|
||||
|
||||
NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
|
||||
#define HINT_BUTTON_WIDTH 23.0
|
||||
#define BUTTON_FONT_SIZE 11.0
|
||||
#define SEGMENT_CHROME_WIDTH 6.0
|
||||
static const CGFloat MASHintButtonWidth = 23;
|
||||
static const CGFloat MASButtonFontSize = 11;
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@@ -13,6 +12,7 @@ NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
|
||||
@property (nonatomic, getter = isHinting) BOOL hinting;
|
||||
@property (nonatomic, copy) NSString *shortcutPlaceholder;
|
||||
@property (nonatomic, assign) BOOL showsDeleteButton;
|
||||
|
||||
@end
|
||||
|
||||
@@ -23,6 +23,7 @@ NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
NSInteger _shortcutToolTipTag;
|
||||
NSInteger _hintToolTipTag;
|
||||
NSTrackingArea *_hintArea;
|
||||
BOOL _acceptsFirstResponder;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -54,9 +55,11 @@ NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
{
|
||||
_shortcutCell = [[[self.class shortcutCellClass] alloc] init];
|
||||
_shortcutCell.buttonType = NSPushOnPushOffButton;
|
||||
_shortcutCell.font = [[NSFontManager sharedFontManager] convertFont:_shortcutCell.font toSize:BUTTON_FONT_SIZE];
|
||||
_shortcutCell.font = [[NSFontManager sharedFontManager] convertFont:_shortcutCell.font toSize:MASButtonFontSize];
|
||||
_shortcutValidator = [MASShortcutValidator sharedValidator];
|
||||
_enabled = YES;
|
||||
_showsDeleteButton = YES;
|
||||
_acceptsFirstResponder = NO;
|
||||
[self resetShortcutCellStyle];
|
||||
}
|
||||
|
||||
@@ -122,14 +125,27 @@ NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
|
||||
// Only enabled view supports recording
|
||||
if (flag && !self.enabled) return;
|
||||
|
||||
if (_recording != flag) {
|
||||
_recording = flag;
|
||||
self.shortcutPlaceholder = nil;
|
||||
[self resetToolTips];
|
||||
[self activateEventMonitoring:_recording];
|
||||
[self activateResignObserver:_recording];
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
// Only care about changes in state
|
||||
if (flag == _recording) return;
|
||||
|
||||
_recording = flag;
|
||||
self.shortcutPlaceholder = nil;
|
||||
[self resetToolTips];
|
||||
[self activateEventMonitoring:_recording];
|
||||
[self activateResignObserver:_recording];
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
// Give VoiceOver users feedback on the result. Requires at least 10.9 to run.
|
||||
if (_recording == NO && (&NSAccessibilityPriorityKey != NULL)) {
|
||||
NSString* msg = _shortcutValue ?
|
||||
NSLocalizedString(@"Shortcut set", @"VoiceOver: Shortcut set") :
|
||||
NSLocalizedString(@"Shortcut cleared", @"VoiceOver: Shortcut cleared");
|
||||
NSDictionary *announcementInfo = @{
|
||||
NSAccessibilityAnnouncementKey : msg,
|
||||
NSAccessibilityPriorityKey : @(NSAccessibilityPriorityHigh),
|
||||
};
|
||||
NSAccessibilityPostNotificationWithUserInfo(self, NSAccessibilityAnnouncementRequestedNotification, announcementInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +154,7 @@ NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
_shortcutValue = shortcutValue;
|
||||
[self resetToolTips];
|
||||
[self setNeedsDisplay:YES];
|
||||
[self propagateValue:shortcutValue forBinding:@"shortcutValue"];
|
||||
[self propagateValue:shortcutValue forBinding:MASShortcutBinding];
|
||||
|
||||
if (self.shortcutValueChange) {
|
||||
self.shortcutValueChange(self);
|
||||
@@ -188,9 +204,15 @@ NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
- (void)drawRect:(CGRect)dirtyRect
|
||||
{
|
||||
if (self.shortcutValue) {
|
||||
[self drawInRect:self.bounds withTitle:NSStringFromMASKeyCode(self.recording ? kMASShortcutGlyphEscape : kMASShortcutGlyphClear)
|
||||
alignment:NSRightTextAlignment state:NSOffState];
|
||||
|
||||
NSString *buttonTitle;
|
||||
if (self.recording) {
|
||||
buttonTitle = NSStringFromMASKeyCode(kMASShortcutGlyphEscape);
|
||||
} else if (self.showsDeleteButton) {
|
||||
buttonTitle = NSStringFromMASKeyCode(kMASShortcutGlyphClear);
|
||||
}
|
||||
if (buttonTitle != nil) {
|
||||
[self drawInRect:self.bounds withTitle:buttonTitle alignment:NSRightTextAlignment state:NSOffState];
|
||||
}
|
||||
CGRect shortcutRect;
|
||||
[self getShortcutRect:&shortcutRect hintRect:NULL];
|
||||
NSString *title = (self.recording
|
||||
@@ -229,11 +251,11 @@ NSString *const MASShortcutBinding = @"shortcutValue";
|
||||
- (void)getShortcutRect:(CGRect *)shortcutRectRef hintRect:(CGRect *)hintRectRef
|
||||
{
|
||||
CGRect shortcutRect, hintRect;
|
||||
CGFloat hintButtonWidth = HINT_BUTTON_WIDTH;
|
||||
CGFloat hintButtonWidth = MASHintButtonWidth;
|
||||
switch (self.style) {
|
||||
case MASShortcutViewStyleTexturedRect: hintButtonWidth += 2.0; break;
|
||||
case MASShortcutViewStyleRounded: hintButtonWidth += 3.0; break;
|
||||
case MASShortcutViewStyleFlat: hintButtonWidth -= 8.0 - (_shortcutCell.font.pointSize - BUTTON_FONT_SIZE); break;
|
||||
case MASShortcutViewStyleFlat: hintButtonWidth -= 8.0 - (_shortcutCell.font.pointSize - MASButtonFontSize); break;
|
||||
default: break;
|
||||
}
|
||||
CGRectDivide(self.bounds, &hintRect, &shortcutRect, hintButtonWidth, CGRectMaxXEdge);
|
||||
@@ -376,6 +398,11 @@ void *kUserDataHint = &kUserDataHint;
|
||||
// Create a shortcut from the event
|
||||
MASShortcut *shortcut = [MASShortcut shortcutWithEvent:event];
|
||||
|
||||
// Tab key must pass through.
|
||||
if (shortcut.keyCode == kVK_Tab){
|
||||
return event;
|
||||
}
|
||||
|
||||
// If the shortcut is a plain Delete or Backspace, clear the current shortcut and cancel recording
|
||||
if (!shortcut.modifierFlags && ((shortcut.keyCode == kVK_Delete) || (shortcut.keyCode == kVK_ForwardDelete))) {
|
||||
weakSelf.shortcutValue = nil;
|
||||
@@ -464,7 +491,7 @@ void *kUserDataHint = &kUserDataHint;
|
||||
#pragma mark Bindings
|
||||
|
||||
// http://tomdalling.com/blog/cocoa/implementing-your-own-cocoa-bindings/
|
||||
-(void) propagateValue:(id)value forBinding:(NSString*)binding;
|
||||
-(void) propagateValue:(id)value forBinding:(NSString*)binding
|
||||
{
|
||||
NSParameterAssert(binding != nil);
|
||||
|
||||
@@ -508,4 +535,73 @@ void *kUserDataHint = &kUserDataHint;
|
||||
[boundObject setValue:value forKeyPath:boundKeyPath];
|
||||
}
|
||||
|
||||
#pragma mark - Accessibility
|
||||
|
||||
- (BOOL)accessibilityIsIgnored
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityHelp
|
||||
{
|
||||
return NSLocalizedString(@"To record a new shortcut, click this button, and then type the"
|
||||
@" new shortcut, or press delete to clear an existing shortcut.",
|
||||
@"VoiceOver shortcut help");
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityLabel
|
||||
{
|
||||
NSString* title = _shortcutValue.description ?: @"Empty";
|
||||
title = [title stringByAppendingFormat:@" %@", NSLocalizedString(@"keyboard shortcut", @"VoiceOver title")];
|
||||
return title;
|
||||
}
|
||||
|
||||
- (BOOL)accessibilityPerformPress
|
||||
{
|
||||
if (self.isRecording == NO) {
|
||||
self.recording = YES;
|
||||
return YES;
|
||||
}
|
||||
else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)accessibilityRole
|
||||
{
|
||||
return NSAccessibilityButtonRole;
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return _acceptsFirstResponder;
|
||||
}
|
||||
|
||||
- (void)setAcceptsFirstResponder:(BOOL)value
|
||||
{
|
||||
_acceptsFirstResponder = value;
|
||||
}
|
||||
|
||||
- (BOOL)becomeFirstResponder
|
||||
{
|
||||
[self setNeedsDisplay:YES];
|
||||
return [super becomeFirstResponder];
|
||||
}
|
||||
|
||||
- (BOOL)resignFirstResponder
|
||||
{
|
||||
[self setNeedsDisplay:YES];
|
||||
return [super resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)drawFocusRingMask
|
||||
{
|
||||
[_shortcutCell drawFocusRingMaskWithFrame:[self bounds] inView:self];
|
||||
}
|
||||
|
||||
- (NSRect)focusRingMaskBounds
|
||||
{
|
||||
return [self bounds];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'MASShortcut'
|
||||
s.version = '2.1.2'
|
||||
s.version = '2.2.0'
|
||||
s.summary = 'Modern framework for managing global keyboard shortcuts compatible with Mac App Store'
|
||||
s.homepage = 'https://github.com/shpakovski/MASShortcut'
|
||||
s.license = 'BSD 2-clause'
|
||||
@@ -9,7 +9,7 @@ Pod::Spec.new do |s|
|
||||
|
||||
s.platform = :osx
|
||||
s.osx.deployment_target = "10.6"
|
||||
s.source = { :git => 'https://github.com/shpakovski/MASShortcut.git', :tag => '2.1.2' }
|
||||
s.source = { :git => 'https://github.com/shpakovski/MASShortcut.git', :tag => '2.2.0' }
|
||||
s.source_files = 'Framework/*.{h,m}'
|
||||
s.exclude_files = 'Framework/*Tests.m'
|
||||
s.osx.frameworks = 'Carbon', 'AppKit'
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
0DC2F18F199372B4003A0131 /* MASDictionaryTransformerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MASDictionaryTransformerTests.m; path = Framework/MASDictionaryTransformerTests.m; sourceTree = "<group>"; };
|
||||
0DC2F19619938EFA003A0131 /* MASShortcutView+Bindings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "MASShortcutView+Bindings.h"; path = "Framework/MASShortcutView+Bindings.h"; sourceTree = "<group>"; };
|
||||
0DC2F19719938EFA003A0131 /* MASShortcutView+Bindings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "MASShortcutView+Bindings.m"; path = "Framework/MASShortcutView+Bindings.m"; sourceTree = "<group>"; };
|
||||
EAFFDC811AACFF3300F38834 /* MASShortcut.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = MASShortcut.modulemap; path = Framework/MASShortcut.modulemap; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -177,6 +178,7 @@
|
||||
0DC2F18A19937060003A0131 /* User Defaults Storage */,
|
||||
0D827DA119912A6D0010B8EF /* UI */,
|
||||
0D827D2F1990D5640010B8EF /* Info.plist */,
|
||||
EAFFDC811AACFF3300F38834 /* MASShortcut.modulemap */,
|
||||
0D827D98199110F60010B8EF /* Prefix.pch */,
|
||||
0D827D761990F81E0010B8EF /* Shortcut.h */,
|
||||
);
|
||||
@@ -316,9 +318,9 @@
|
||||
productReference = 0D827D371990D5E70010B8EF /* Demo.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
0D827D8219910AFF0010B8EF /* Tests */ = {
|
||||
0D827D8219910AFF0010B8EF /* MASShortcutTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0D827D9219910AFF0010B8EF /* Build configuration list for PBXNativeTarget "Tests" */;
|
||||
buildConfigurationList = 0D827D9219910AFF0010B8EF /* Build configuration list for PBXNativeTarget "MASShortcutTests" */;
|
||||
buildPhases = (
|
||||
0D827D7F19910AFF0010B8EF /* Sources */,
|
||||
0D827D8019910AFF0010B8EF /* Frameworks */,
|
||||
@@ -329,7 +331,7 @@
|
||||
dependencies = (
|
||||
0D827D8F19910AFF0010B8EF /* PBXTargetDependency */,
|
||||
);
|
||||
name = Tests;
|
||||
name = MASShortcutTests;
|
||||
productName = Tests;
|
||||
productReference = 0D827D8319910AFF0010B8EF /* Tests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
@@ -362,8 +364,8 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
0D827CD21990D4420010B8EF /* MASShortcut */,
|
||||
0D827D8219910AFF0010B8EF /* MASShortcutTests */,
|
||||
0D827D361990D5E70010B8EF /* Demo */,
|
||||
0D827D8219910AFF0010B8EF /* Tests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -517,6 +519,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
FRAMEWORK_VERSION = A;
|
||||
@@ -525,6 +528,7 @@
|
||||
INFOPLIST_FILE = Framework/Info.plist;
|
||||
INSTALL_PATH = "@executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
MODULEMAP_FILE = Framework/MASShortcut.modulemap;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
@@ -535,6 +539,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
FRAMEWORK_VERSION = A;
|
||||
@@ -543,6 +548,7 @@
|
||||
INFOPLIST_FILE = Framework/Info.plist;
|
||||
INSTALL_PATH = "@executable_path/../Frameworks";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
MODULEMAP_FILE = Framework/MASShortcut.modulemap;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
@@ -647,7 +653,7 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
0D827D9219910AFF0010B8EF /* Build configuration list for PBXNativeTarget "Tests" */ = {
|
||||
0D827D9219910AFF0010B8EF /* Build configuration list for PBXNativeTarget "MASShortcutTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
0D827D9019910AFF0010B8EF /* Debug */,
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0D827D8219910AFF0010B8EF"
|
||||
BuildableName = "Tests.xctest"
|
||||
BlueprintName = "Tests"
|
||||
BuildableName = "MASShortcutTests.xctest"
|
||||
BlueprintName = "MASShortcutTests"
|
||||
ReferencedContainer = "container:MASShortcut.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
@@ -47,8 +47,8 @@
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0D827D8219910AFF0010B8EF"
|
||||
BuildableName = "Tests.xctest"
|
||||
BlueprintName = "Tests"
|
||||
BuildableName = "MASShortcutTests.xctest"
|
||||
BlueprintName = "MASShortcutTests"
|
||||
ReferencedContainer = "container:MASShortcut.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[](https://travis-ci.org/shpakovski/MASShortcut)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
|
||||
# Intro
|
||||
|
||||
@@ -18,11 +19,11 @@ Features:
|
||||
* Mac App Store friendly
|
||||
* Works on OS X 10.6 and up
|
||||
* Hacking-friendly codebase covered with tests
|
||||
* Basic accessibility support
|
||||
|
||||
Important features currently missing:
|
||||
|
||||
* Localisation
|
||||
* Accessibility
|
||||
|
||||
Pull requests welcome :)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user