feat: after a crash, suggest to send a crash report (closes #132)

also updated many localications
This commit is contained in:
Louis Pontoise
2020-07-22 21:45:30 +09:00
committed by lwouis
parent 85b5ee7653
commit a8970ddf71
91 changed files with 3610 additions and 782 deletions
+2
View File
@@ -22,6 +22,8 @@
<string>#VERSION#</string>
<key>FeedbackToken</key>
<string>#FEEDBACK_TOKEN#</string>
<key>AppCenterSecret</key>
<string>#APPCENTER_SECRET#</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>LSUIElement</key>
+1
View File
@@ -7,4 +7,5 @@ target 'alt-tab-macos' do
pod 'ShortcutRecorder', :git => 'https://github.com/Kentzo/ShortcutRecorder.git', :commit => 'f718220854575bad86fa89dd2bb3decd0b14b2b0'
pod 'SwiftyMarkdown', '1.1.0'
pod 'Preferences', '1.0.1'
pod 'AppCenter/Crashes', '3.3.1'
end
+7 -1
View File
@@ -1,4 +1,7 @@
PODS:
- AppCenter/Core (3.3.1)
- AppCenter/Crashes (3.3.1):
- AppCenter/Core
- LetsMove (1.24)
- Preferences (1.0.1)
- ShortcutRecorder (3.1)
@@ -6,6 +9,7 @@ PODS:
- SwiftyMarkdown (1.1.0)
DEPENDENCIES:
- AppCenter/Crashes (= 3.3.1)
- LetsMove (from `https://github.com/lwouis/LetsMove.git`, commit `7abf4daed1a25218f2b52f2dfd190aee5a50071c`)
- Preferences (= 1.0.1)
- ShortcutRecorder (from `https://github.com/Kentzo/ShortcutRecorder.git`, commit `f718220854575bad86fa89dd2bb3decd0b14b2b0`)
@@ -14,6 +18,7 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- AppCenter
- Preferences
- SwiftyMarkdown
@@ -36,12 +41,13 @@ CHECKOUT OPTIONS:
:git: https://github.com/Kentzo/ShortcutRecorder.git
SPEC CHECKSUMS:
AppCenter: 76ecf7e959a68e36b0fd314e8dc5897660214423
LetsMove: fefe56bc7bc7fb7d37049e28a14f297961229fc5
Preferences: a5afbe0ae3e6bd886328b1960f4998e65d58f2c4
ShortcutRecorder: fdf620aca34101b0cba3b10fca815e0459254189
Sparkle: ea073ba9c69cee3ebaab8685ba1e732e14d249f7
SwiftyMarkdown: 033abc9dad9a37903f81aec5188cade436f40520
PODFILE CHECKSUM: ccd8822c0e64188b9aaf554188c72ef13a7c81f4
PODFILE CHECKSUM: 356279aa09d4eac74abe0d828422386fe7345766
COCOAPODS: 1.9.1
+25
View File
@@ -0,0 +1,25 @@
Visual Studio App Center SDK for Apple platforms
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1 @@
Versions/Current/AppCenter
@@ -0,0 +1 @@
Versions/Current/Headers
@@ -0,0 +1 @@
Versions/Current/Modules
@@ -0,0 +1 @@
Versions/Current/PrivateHeaders
@@ -0,0 +1 @@
Versions/Current/Resources
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSAbstractLog.h"
#import "MSAppCenter.h"
#import "MSAppCenterErrors.h"
#import "MSChannelGroupProtocol.h"
#import "MSChannelProtocol.h"
#import "MSConstants.h"
#import "MSCustomProperties.h"
#import "MSDevice.h"
#import "MSEnable.h"
#import "MSLog.h"
#import "MSLogWithProperties.h"
#import "MSLogger.h"
#import "MSService.h"
#import "MSServiceAbstract.h"
#import "MSWrapperLogger.h"
#import "MSWrapperSdk.h"
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_ABSTRACT_LOG_H
#define MS_ABSTRACT_LOG_H
#import <Foundation/Foundation.h>
@interface MSAbstractLog : NSObject
@end
#endif
@@ -0,0 +1,223 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSConstants.h"
@class MSWrapperSdk;
#if !TARGET_OS_TV
@class MSCustomProperties;
#endif
@interface MSAppCenter : NSObject
/**
* Returns the singleton instance of MSAppCenter.
*/
+ (instancetype)sharedInstance;
/**
* Configure the SDK with an application secret.
*
* @param appSecret A unique and secret key used to identify the application.
*
* @discussion This may be called only once per application process lifetime.
*/
+ (void)configureWithAppSecret:(NSString *)appSecret;
/**
* Configure the SDK.
*
* @discussion This may be called only once per application process lifetime.
*/
+ (void)configure;
/**
* Configure the SDK with an application secret and an array of services to start.
*
* @param appSecret A unique and secret key used to identify the application.
* @param services Array of services to start.
*
* @discussion This may be called only once per application process lifetime.
*/
+ (void)start:(NSString *)appSecret withServices:(NSArray<Class> *)services;
/**
* Start the SDK with an array of services.
*
* @param services Array of services to start.
*
* @discussion This may be called only once per application process lifetime.
*/
+ (void)startWithServices:(NSArray<Class> *)services;
/**
* Start a service.
*
* @param service A service to start.
*
* @discussion This may be called only once per service per application process lifetime.
*/
+ (void)startService:(Class)service;
/**
* Configure the SDK with an array of services to start from a library. This will not start the service at application level, it will enable
* the service only for the library.
*
* @param services Array of services to start.
*/
+ (void)startFromLibraryWithServices:(NSArray<Class> *)services;
/**
* Check whether the SDK has already been configured or not.
*
* @return YES if configured, NO otherwise.
*/
+ (BOOL)isConfigured;
/**
* Check whether app is running in App Center Test Cloud.
*
* @return true if running in App Center Test Cloud, false otherwise.
*/
+ (BOOL)isRunningInAppCenterTestCloud;
/**
* Change the base URL (schema + authority + port only) used to communicate with the backend.
*
* @param logUrl Base URL to use for backend communication.
*/
+ (void)setLogUrl:(NSString *)logUrl;
/**
* Enable or disable the SDK as a whole. In addition to AppCenter resources, it will also enable or disable all registered services.
* The state is persisted in the device's storage across application launches.
*
* @param isEnabled YES to enable, NO to disable.
*
* @see isEnabled
*/
+ (void)setEnabled:(BOOL)isEnabled;
/**
* Check whether the SDK is enabled or not as a whole.
*
* @return YES if enabled, NO otherwise.
*
* @see setEnabled:
*/
+ (BOOL)isEnabled;
/**
* Get log level.
*
* @return Log level.
*/
+ (MSLogLevel)logLevel;
/**
* Set log level.
*
* @param logLevel The log level.
*/
+ (void)setLogLevel:(MSLogLevel)logLevel;
/**
* Set log level handler.
*
* @param logHandler Handler.
*/
+ (void)setLogHandler:(MSLogHandler)logHandler;
/**
* Set wrapper SDK information to use when building device properties. This is intended in case you are building a SDK that uses the App
* Center SDK under the hood, e.g. our Xamarin SDK or ReactNative SDk.
*
* @param wrapperSdk Wrapper SDK information.
*/
+ (void)setWrapperSdk:(MSWrapperSdk *)wrapperSdk;
#if !TARGET_OS_TV
/**
* Set the custom properties.
*
* @param customProperties Custom properties object.
*/
+ (void)setCustomProperties:(MSCustomProperties *)customProperties;
#endif
/**
* Check whether the application delegate forwarder is enabled or not.
*
* @return YES if enabled, NO otherwise.
*
* @discussion The application delegate forwarder forwards messages that target your application delegate methods via swizzling to the SDK.
* It simplifies the SDK integration but may not be suitable to any situations. For
* instance it should be disabled if you or one of your third party SDK is doing message forwarding on the application delegate. Message
* forwarding usually implies the implementation of @see NSObject#forwardingTargetForSelector: or @see NSObject#forwardInvocation: methods.
* To disable the application delegate forwarder just add the `AppCenterAppDelegateForwarderEnabled` tag to your Info .plist file and set it
* to `0`. Then you will have to forward any application delegate needed by the SDK manually.
*/
+ (BOOL)isAppDelegateForwarderEnabled;
/**
* Get unique installation identifier.
*
* @return Unique installation identifier.
*/
+ (NSUUID *)installId;
/**
* Detect if a debugger is attached to the app process. This is only invoked once on app startup and can not detect
* if the debugger is being attached during runtime!
*
* @return BOOL if the debugger is attached.
*/
+ (BOOL)isDebuggerAttached;
/**
* Get the current version of AppCenter SDK.
*
* @return The current version of AppCenter SDK.
*/
+ (NSString *)sdkVersion;
/**
* Set the maximum size of the internal storage. This method must be called before App Center is started. This method is only intended for
* applications.
*
* @param sizeInBytes Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size
* (default is 4096 bytes). Values below 20,480 bytes (20 KiB) will be ignored.
*
* @param completionHandler Callback that is invoked when the database size has been set. The `BOOL` parameter is `YES` if changing the size
* is successful, and `NO` otherwise. This parameter can be null.
*
* @discussion This only sets the maximum size of the database, but App Center modules might store additional data.
* The value passed to this method is not persisted on disk. The default maximum database size is 10485760 bytes (10 MiB).
*/
+ (void)setMaxStorageSize:(long)sizeInBytes completionHandler:(void (^)(BOOL))completionHandler;
/**
* Set the user identifier.
*
* @param userId User identifier.
*
* @discussion Set the user identifier for logs sent for the default target token when the secret passed in @c
* MSAppCenter:start:withServices: contains "target={targetToken}".
*
* For App Center backend the user identifier maximum length is 256 characters.
*
* AppCenter must be configured or started before this API can be used.
*/
+ (void)setUserId:(NSString *)userId;
/**
* Set country code to use when building device properties.
*
* @param countryCode The two-letter ISO country code. @see https://www.iso.org/obp/ui/#search for more information.
*/
+ (void)setCountryCode:(NSString *)countryCode;
@end
@@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_APP_CENTER_ERRORS_H
#define MS_APP_CENTER_ERRORS_H
#import <Foundation/Foundation.h>
#define MS_APP_CENTER_BASE_DOMAIN @"com.Microsoft.AppCenter."
NS_ASSUME_NONNULL_BEGIN
#pragma mark - Domain
static NSString *const kMSACErrorDomain = MS_APP_CENTER_BASE_DOMAIN @"ErrorDomain";
#pragma mark - General
// Error codes.
NS_ENUM(NSInteger){MSACLogInvalidContainerErrorCode = 1, MSACCanceledErrorCode = 2, MSACDisabledErrorCode = 3};
// Error descriptions.
static NSString const *kMSACLogInvalidContainerErrorDesc = @"Invalid log container.";
static NSString const *kMSACCanceledErrorDesc = @"The operation was canceled.";
static NSString const *kMSACDisabledErrorDesc = @"The service is disabled.";
#pragma mark - Connection
// Error codes.
NS_ENUM(NSInteger){MSACConnectionPausedErrorCode = 100, MSACConnectionHttpErrorCode = 101};
// Error descriptions.
static NSString const *kMSACConnectionHttpErrorDesc = @"An HTTP error occured.";
static NSString const *kMSACConnectionPausedErrorDesc = @"Canceled, connection paused with log deletion.";
// Error user info keys.
static NSString const *kMSACConnectionHttpCodeErrorKey = @"MSACConnectionHttpCode";
NS_ASSUME_NONNULL_END
#endif
@@ -0,0 +1,83 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_CHANNEL_GROUP_PROTOCOL_H
#define MS_CHANNEL_GROUP_PROTOCOL_H
#import <Foundation/Foundation.h>
#import "MSChannelProtocol.h"
NS_ASSUME_NONNULL_BEGIN
@class MSChannelUnitConfiguration;
@protocol MSIngestionProtocol;
@protocol MSChannelUnitProtocol;
/**
* `MSChannelGroupProtocol` represents a kind of channel that contains constituent MSChannelUnit objects. When an operation from the
* `MSChannelProtocol` is performed on the group, that operation should be propagated to its constituent MSChannelUnit objects.
*/
@protocol MSChannelGroupProtocol <MSChannelProtocol>
/**
* Initialize a channel unit with the given configuration.
*
* @param configuration channel configuration.
*
* @return The added `MSChannelUnitProtocol`. Use this object to enqueue logs.
*/
- (id<MSChannelUnitProtocol>)addChannelUnitWithConfiguration:(MSChannelUnitConfiguration *)configuration;
/**
* Initialize a channel unit with the given configuration.
*
* @param configuration channel configuration.
* @param ingestion The alternative ingestion object
*
* @return The added `MSChannelUnitProtocol`. Use this object to enqueue logs.
*/
- (id<MSChannelUnitProtocol>)addChannelUnitWithConfiguration:(MSChannelUnitConfiguration *)configuration
withIngestion:(nullable id<MSIngestionProtocol>)ingestion;
/**
* Change the base URL (schema + authority + port only) used to communicate with the backend.
*
* @param logUrl base URL to use for backend communication.
*/
- (void)setLogUrl:(NSString *)logUrl;
/**
* Set the app secret.
*
* @param appSecret The app secret.
*/
- (void)setAppSecret:(NSString *)appSecret;
/**
* Set the maximum size of the internal storage. This method must be called before App Center is started.
*
* @discussion The default maximum database size is 10485760 bytes (10 MiB).
*
* @param sizeInBytes Maximum size of the internal storage in bytes. This will be rounded up to the nearest multiple of a SQLite page size
* (default is 4096 bytes). Values below 24576 bytes (24 KiB) will be ignored.
* @param completionHandler Callback that is invoked when the database size has been set. The `BOOL` parameter is `YES` if changing the size
* is successful, and `NO` otherwise.
*/
- (void)setMaxStorageSize:(long)sizeInBytes completionHandler:(nullable void (^)(BOOL))completionHandler;
/**
* Return a channel unit instance for the given groupId.
*
* @param groupId The group ID for a channel unit.
*
* @return A channel unit instance or `nil`.
*/
- (nullable id<MSChannelUnitProtocol>)channelUnitForGroupId:(NSString *)groupId;
@end
NS_ASSUME_NONNULL_END
#endif
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_CHANNEL_PROTOCOL_H
#define MS_CHANNEL_PROTOCOL_H
#import <Foundation/Foundation.h>
#import "MSEnable.h"
NS_ASSUME_NONNULL_BEGIN
@protocol MSChannelDelegate;
/**
* `MSChannelProtocol` contains the essential operations of a channel. Channels are broadly responsible for enqueuing logs to be sent to the
* backend and/or stored on disk.
*/
@protocol MSChannelProtocol <NSObject, MSEnable>
/**
* Add delegate.
*
* @param delegate delegate.
*/
- (void)addDelegate:(id<MSChannelDelegate>)delegate;
/**
* Remove delegate.
*
* @param delegate delegate.
*/
- (void)removeDelegate:(id<MSChannelDelegate>)delegate;
/**
* Pause operations, logs will be stored but not sent.
*
* @param identifyingObject Object used to identify the pause request.
*
* @discussion A paused channel doesn't forward logs to the ingestion. The identifying object used to pause the channel can be any unique
* object. The same identifying object must be used to call resume. For simplicity if the caller is the one owning the channel then @c self
* can be used as identifying object.
*
* @see resumeWithIdentifyingObject:
*/
- (void)pauseWithIdentifyingObject:(id<NSObject>)identifyingObject;
/**
* Resume operations, logs can be sent again.
*
* @param identifyingObject Object used to passed to the pause method.
*
* @discussion The channel only resume when all the outstanding identifying objects have been resumed.
*
* @see pauseWithIdentifyingObject:
*/
- (void)resumeWithIdentifyingObject:(id<NSObject>)identifyingObject;
@end
NS_ASSUME_NONNULL_END
#endif
@@ -0,0 +1,170 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
/**
* Log Levels
*/
typedef NS_ENUM(NSUInteger, MSLogLevel) {
/**
* Logging will be very chatty
*/
MSLogLevelVerbose = 2,
/**
* Debug information will be logged
*/
MSLogLevelDebug = 3,
/**
* Information will be logged
*/
MSLogLevelInfo = 4,
/**
* Errors and warnings will be logged
*/
MSLogLevelWarning = 5,
/**
* Errors will be logged
*/
MSLogLevelError = 6,
/**
* Only critical errors will be logged
*/
MSLogLevelAssert = 7,
/**
* Logging is disabled
*/
MSLogLevelNone = 99
};
typedef NSString * (^MSLogMessageProvider)(void);
typedef void (^MSLogHandler)(MSLogMessageProvider messageProvider, MSLogLevel logLevel, NSString *tag, const char *file,
const char *function, uint line);
/**
* Channel priorities, check the kMSPriorityCount if you add a new value.
* The order matters here! Values NEED to range from low priority to high priority.
*/
typedef NS_ENUM(NSInteger, MSPriority) { MSPriorityBackground, MSPriorityDefault, MSPriorityHigh };
static short const kMSPriorityCount = MSPriorityHigh + 1;
/**
* The priority by which the modules are initialized.
* MSPriorityMax is reserved for only 1 module and this needs to be Crashes.
* Crashes needs to be initialized first to catch crashes in our other SDK Modules (which will hopefully never happen) and to avoid losing
* any log at crash time.
*/
typedef NS_ENUM(NSInteger, MSInitializationPriority) {
MSInitializationPriorityDefault = 500,
MSInitializationPriorityHigh = 750,
MSInitializationPriorityMax = 999
};
/**
* Enum with the different HTTP status codes.
*/
typedef NS_ENUM(NSInteger, MSHTTPCodesNo) {
// Invalid
MSHTTPCodesNo0XXInvalidUnknown = 0,
// Informational
MSHTTPCodesNo1XXInformationalUnknown = 1,
MSHTTPCodesNo100Continue = 100,
MSHTTPCodesNo101SwitchingProtocols = 101,
MSHTTPCodesNo102Processing = 102,
// Success
MSHTTPCodesNo2XXSuccessUnknown = 2,
MSHTTPCodesNo200OK = 200,
MSHTTPCodesNo201Created = 201,
MSHTTPCodesNo202Accepted = 202,
MSHTTPCodesNo203NonAuthoritativeInformation = 203,
MSHTTPCodesNo204NoContent = 204,
MSHTTPCodesNo205ResetContent = 205,
MSHTTPCodesNo206PartialContent = 206,
MSHTTPCodesNo207MultiStatus = 207,
MSHTTPCodesNo208AlreadyReported = 208,
MSHTTPCodesNo209IMUsed = 209,
// Redirection
MSHTTPCodesNo3XXSuccessUnknown = 3,
MSHTTPCodesNo300MultipleChoices = 300,
MSHTTPCodesNo301MovedPermanently = 301,
MSHTTPCodesNo302Found = 302,
MSHTTPCodesNo303SeeOther = 303,
MSHTTPCodesNo304NotModified = 304,
MSHTTPCodesNo305UseProxy = 305,
MSHTTPCodesNo306SwitchProxy = 306,
MSHTTPCodesNo307TemporaryRedirect = 307,
MSHTTPCodesNo308PermanentRedirect = 308,
// Client error
MSHTTPCodesNo4XXSuccessUnknown = 4,
MSHTTPCodesNo400BadRequest = 400,
MSHTTPCodesNo401Unauthorised = 401,
MSHTTPCodesNo402PaymentRequired = 402,
MSHTTPCodesNo403Forbidden = 403,
MSHTTPCodesNo404NotFound = 404,
MSHTTPCodesNo405MethodNotAllowed = 405,
MSHTTPCodesNo406NotAcceptable = 406,
MSHTTPCodesNo407ProxyAuthenticationRequired = 407,
MSHTTPCodesNo408RequestTimeout = 408,
MSHTTPCodesNo409Conflict = 409,
MSHTTPCodesNo410Gone = 410,
MSHTTPCodesNo411LengthRequired = 411,
MSHTTPCodesNo412PreconditionFailed = 412,
MSHTTPCodesNo413RequestEntityTooLarge = 413,
MSHTTPCodesNo414RequestURITooLong = 414,
MSHTTPCodesNo415UnsupportedMediaType = 415,
MSHTTPCodesNo416RequestedRangeNotSatisfiable = 416,
MSHTTPCodesNo417ExpectationFailed = 417,
MSHTTPCodesNo418IamATeapot = 418,
MSHTTPCodesNo419AuthenticationTimeout = 419,
MSHTTPCodesNo420MethodFailureSpringFramework = 420,
MSHTTPCodesNo420EnhanceYourCalmTwitter = 4200,
MSHTTPCodesNo422UnprocessableEntity = 422,
MSHTTPCodesNo423Locked = 423,
MSHTTPCodesNo424FailedDependency = 424,
MSHTTPCodesNo424MethodFailureWebDaw = 4240,
MSHTTPCodesNo425UnorderedCollection = 425,
MSHTTPCodesNo426UpgradeRequired = 426,
MSHTTPCodesNo428PreconditionRequired = 428,
MSHTTPCodesNo429TooManyRequests = 429,
MSHTTPCodesNo431RequestHeaderFieldsTooLarge = 431,
MSHTTPCodesNo444NoResponseNginx = 444,
MSHTTPCodesNo449RetryWithMicrosoft = 449,
MSHTTPCodesNo450BlockedByWindowsParentalControls = 450,
MSHTTPCodesNo451RedirectMicrosoft = 451,
MSHTTPCodesNo451UnavailableForLegalReasons = 4510,
MSHTTPCodesNo494RequestHeaderTooLargeNginx = 494,
MSHTTPCodesNo495CertErrorNginx = 495,
MSHTTPCodesNo496NoCertNginx = 496,
MSHTTPCodesNo497HTTPToHTTPSNginx = 497,
MSHTTPCodesNo499ClientClosedRequestNginx = 499,
// Server error
MSHTTPCodesNo5XXSuccessUnknown = 5,
MSHTTPCodesNo500InternalServerError = 500,
MSHTTPCodesNo501NotImplemented = 501,
MSHTTPCodesNo502BadGateway = 502,
MSHTTPCodesNo503ServiceUnavailable = 503,
MSHTTPCodesNo504GatewayTimeout = 504,
MSHTTPCodesNo505HTTPVersionNotSupported = 505,
MSHTTPCodesNo506VariantAlsoNegotiates = 506,
MSHTTPCodesNo507InsufficientStorage = 507,
MSHTTPCodesNo508LoopDetected = 508,
MSHTTPCodesNo509BandwidthLimitExceeded = 509,
MSHTTPCodesNo510NotExtended = 510,
MSHTTPCodesNo511NetworkAuthenticationRequired = 511,
MSHTTPCodesNo522ConnectionTimedOut = 522,
MSHTTPCodesNo598NetworkReadTimeoutErrorUnknown = 598,
MSHTTPCodesNo599NetworkConnectTimeoutErrorUnknown = 599
};
@@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_CUSTOM_PROPERTIES_H
#define MS_CUSTOM_PROPERTIES_H
#import <Foundation/Foundation.h>
/**
* Custom properties builder.
* Collects multiple properties to send in one log.
*/
@interface MSCustomProperties : NSObject
/**
* Set the specified property value with the specified key.
* If the properties previously contained a property for the key, the old value is replaced.
*
* @param key Key with which the specified value is to be set.
* @param value Value to be set with the specified key.
*
* @return This instance.
*/
- (instancetype)setString:(NSString *)value forKey:(NSString *)key;
/**
* Set the specified property value with the specified key.
* If the properties previously contained a property for the key, the old value is replaced.
*
* @param key Key with which the specified value is to be set.
* @param value Value to be set with the specified key.
*
* @return This instance.
*/
- (instancetype)setNumber:(NSNumber *)value forKey:(NSString *)key;
/**
* Set the specified property value with the specified key.
* If the properties previously contained a property for the key, the old value is replaced.
*
* @param key Key with which the specified value is to be set.
* @param value Value to be set with the specified key.
*
* @return This instance.
*/
- (instancetype)setBool:(BOOL)value forKey:(NSString *)key;
/**
* Set the specified property value with the specified key.
* If the properties previously contained a property for the key, the old value is replaced.
*
* @param key Key with which the specified value is to be set.
* @param value Value to be set with the specified key.
*
* @return This instance.
*/
- (instancetype)setDate:(NSDate *)value forKey:(NSString *)key;
/**
* Clear the property for the specified key.
*
* @param key Key whose mapping is to be cleared.
*
* @return This instance.
*/
- (instancetype)clearPropertyForKey:(NSString *)key;
@end
#endif
@@ -0,0 +1,96 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_DEVICE_H
#define MS_DEVICE_H
#import <Foundation/Foundation.h>
#import "MSWrapperSdk.h"
@interface MSDevice : MSWrapperSdk
/*
* Name of the SDK. Consists of the name of the SDK and the platform, e.g. "appcenter.ios", "appcenter.android"
*/
@property(nonatomic, copy, readonly) NSString *sdkName;
/*
* Version of the SDK in semver format, e.g. "1.2.0" or "0.12.3-alpha.1".
*/
@property(nonatomic, copy, readonly) NSString *sdkVersion;
/*
* Device model (example: iPad2,3).
*/
@property(nonatomic, copy, readonly) NSString *model;
/*
* Device manufacturer (example: HTC).
*/
@property(nonatomic, copy, readonly) NSString *oemName;
/*
* OS name (example: iOS).
*/
@property(nonatomic, copy, readonly) NSString *osName;
/*
* OS version (example: 9.3.0).
*/
@property(nonatomic, copy, readonly) NSString *osVersion;
/*
* OS build code (example: LMY47X). [optional]
*/
@property(nonatomic, copy, readonly) NSString *osBuild;
/*
* API level when applicable like in Android (example: 15). [optional]
*/
@property(nonatomic, copy, readonly) NSNumber *osApiLevel;
/*
* Language code (example: en_US).
*/
@property(nonatomic, copy, readonly) NSString *locale;
/*
* The offset in minutes from UTC for the device time zone, including daylight savings time.
*/
@property(nonatomic, readonly, strong) NSNumber *timeZoneOffset;
/*
* Screen size of the device in pixels (example: 640x480).
*/
@property(nonatomic, copy, readonly) NSString *screenSize;
/*
* Application version name, e.g. 1.1.0
*/
@property(nonatomic, copy, readonly) NSString *appVersion;
/*
* Carrier name (for mobile devices). [optional]
*/
@property(nonatomic, copy, readonly) NSString *carrierName;
/*
* Carrier country code (for mobile devices). [optional]
*/
@property(nonatomic, copy, readonly) NSString *carrierCountry;
/*
* The app's build number, e.g. 42.
*/
@property(nonatomic, copy, readonly) NSString *appBuild;
/*
* The bundle identifier, package identifier, or namespace, depending on what the individual plattforms use, .e.g com.microsoft.example.
* [optional]
*/
@property(nonatomic, copy, readonly) NSString *appNamespace;
@end
#endif
@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_ENABLE_H
#define MS_ENABLE_H
#import <Foundation/Foundation.h>
/**
* Protocol to define an instance that can be enabled/disabled.
*/
@protocol MSEnable <NSObject>
@required
/**
* Enable/disable this instance and delete data on disabled state.
*
* @param isEnabled A boolean value set to YES to enable the instance or NO to disable it.
* @param deleteData A boolean value set to YES to delete data or NO to keep it.
*/
- (void)setEnabled:(BOOL)isEnabled andDeleteDataOnDisabled:(BOOL)deleteData;
@end
#endif
@@ -0,0 +1,73 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_LOG_H
#define MS_LOG_H
#import <Foundation/Foundation.h>
@class MSDevice;
@protocol MSLog <NSObject>
/**
* Log type.
*/
@property(nonatomic, copy) NSString *type;
/**
* Log timestamp.
*/
@property(nonatomic, strong) NSDate *timestamp;
/**
* A session identifier is used to correlate logs together. A session is an abstract concept in the API and is not necessarily an analytics
* session, it can be used to only track crashes.
*/
@property(nonatomic, copy) NSString *sid;
/**
* Optional distribution group ID value.
*/
@property(nonatomic, copy) NSString *distributionGroupId;
/**
* Optional user identifier.
*/
@property(nonatomic, copy) NSString *userId;
/**
* Device properties associated to this log.
*/
@property(nonatomic, strong) MSDevice *device;
/**
* Transient object tag. For example, a log can be tagged with a transmission target. We do this currently to prevent properties being
* applied retroactively to previous logs by comparing their tags.
*/
@property(nonatomic, strong) NSObject *tag;
/**
* Checks if the object's values are valid.
*
* @return YES, if the object is valid.
*/
- (BOOL)isValid;
/**
* Adds a transmission target token that this log should be sent to.
*
* @param token The transmission target token.
*/
- (void)addTransmissionTargetToken:(NSString *)token;
/**
* Gets all transmission target tokens that this log should be sent to.
*
* @returns Collection of transmission target tokens that this log should be sent to.
*/
- (NSSet *)transmissionTargetTokens;
@end
#endif
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_LOG_WITH_PROPERTIES_H
#define MS_LOG_WITH_PROPERTIES_H
#import <Foundation/Foundation.h>
#import "MSAbstractLog.h"
@interface MSLogWithProperties : MSAbstractLog
/**
* Additional key/value pair parameters. [optional]
*/
@property(nonatomic, strong) NSDictionary<NSString *, NSString *> *properties;
@end
#endif
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSConstants.h"
#define MSLog(_level, _tag, _message) \
[MSLogger logMessage:_message level:_level tag:_tag file:__FILE__ function:__PRETTY_FUNCTION__ line:__LINE__]
#define MSLogAssert(tag, format, ...) \
MSLog(MSLogLevelAssert, tag, (^{ \
return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \
}))
#define MSLogError(tag, format, ...) \
MSLog(MSLogLevelError, tag, (^{ \
return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \
}))
#define MSLogWarning(tag, format, ...) \
MSLog(MSLogLevelWarning, tag, (^{ \
return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \
}))
#define MSLogInfo(tag, format, ...) \
MSLog(MSLogLevelInfo, tag, (^{ \
return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \
}))
#define MSLogDebug(tag, format, ...) \
MSLog(MSLogLevelDebug, tag, (^{ \
return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \
}))
#define MSLogVerbose(tag, format, ...) \
MSLog(MSLogLevelVerbose, tag, (^{ \
return [NSString stringWithFormat:(format), ##__VA_ARGS__]; \
}))
@interface MSLogger : NSObject
+ (void)logMessage:(MSLogMessageProvider)messageProvider
level:(MSLogLevel)loglevel
tag:(NSString *)tag
file:(const char *)file
function:(const char *)function
line:(uint)line;
@end
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_SERVICE_H
#define MS_SERVICE_H
#import <Foundation/Foundation.h>
/**
* Protocol declaring service logic.
*/
@protocol MSService <NSObject>
/**
* Enable or disable this service.
* The state is persisted in the device's storage across application launches.
*
* @param isEnabled Whether this service is enabled or not.
*
* @see isEnabled
*/
+ (void)setEnabled:(BOOL)isEnabled;
/**
* Indicates whether this service is enabled.
*
* @return `YES` if this service is enabled, `NO` if it is not.
*
* @see setEnabled:
*/
+ (BOOL)isEnabled;
@end
#endif
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_SERVICE_ABSTRACT_H
#define MS_SERVICE_ABSTRACT_H
#import <Foundation/Foundation.h>
#import "MSService.h"
@protocol MSChannelGroupProtocol;
/**
* Abstraction of services common logic.
* This class is intended to be subclassed only not instantiated directly.
*/
@interface MSServiceAbstract : NSObject <MSService>
/**
* The flag indicates whether the service is started from application or not.
*/
@property(nonatomic, assign) BOOL startedFromApplication;
/**
* Start this service with a channel group. Also sets the flag that indicates that a service has been started.
*
* @param channelGroup channel group used to persist and send logs.
* @param appSecret app secret for the SDK.
* @param token default transmission target token for this service.
* @param fromApplication indicates whether the service started from an application or not.
*/
- (void)startWithChannelGroup:(id<MSChannelGroupProtocol>)channelGroup
appSecret:(NSString *)appSecret
transmissionTargetToken:(NSString *)token
fromApplication:(BOOL)fromApplication;
/**
* Update configuration when the service requires to start again. This method should only be called if the service is started from libraries
* and then is being started from an application.
*
* @param appSecret app secret for the SDK.
* @param token default transmission target token for this service.
*/
- (void)updateConfigurationWithAppSecret:(NSString *)appSecret transmissionTargetToken:(NSString *)token;
/**
* Checks if the service needs the application secret.
*
* @return `YES` if the application secret is required, `NO` otherwise.
*/
- (BOOL)isAppSecretRequired;
@end
#endif
@@ -0,0 +1,16 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSConstants.h"
/**
* This is a utility for producing App Center style log messages. It is only intended for use by App Center services and wrapper SDKs of App
* Center.
*/
@interface MSWrapperLogger : NSObject
+ (void)MSWrapperLog:(MSLogMessageProvider)message tag:(NSString *)tag level:(MSLogLevel)level;
@end
@@ -0,0 +1,59 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_WRAPPER_SDK_H
#define MS_WRAPPER_SDK_H
#import <Foundation/Foundation.h>
@interface MSWrapperSdk : NSObject
/*
* Version of the wrapper SDK. When the SDK is embedding another base SDK (for example Xamarin.Android wraps Android), the Xamarin specific
* version is populated into this field while sdkVersion refers to the original Android SDK. [optional]
*/
@property(nonatomic, copy, readonly) NSString *wrapperSdkVersion;
/*
* Name of the wrapper SDK (examples: Xamarin, Cordova). [optional]
*/
@property(nonatomic, copy, readonly) NSString *wrapperSdkName;
/*
* Version of the wrapper technology framework (Xamarin runtime version or ReactNative or Cordova etc...). [optional]
*/
@property(nonatomic, copy, readonly) NSString *wrapperRuntimeVersion;
/*
* Label that is used to identify application code 'version' released via Live Update beacon running on device.
*/
@property(nonatomic, copy, readonly) NSString *liveUpdateReleaseLabel;
/*
* Identifier of environment that current application release belongs to, deployment key then maps to environment like Production, Staging.
*/
@property(nonatomic, copy, readonly) NSString *liveUpdateDeploymentKey;
/*
* Hash of all files (ReactNative or Cordova) deployed to device via LiveUpdate beacon. Helps identify the Release version on device or need
* to download updates in future
*/
@property(nonatomic, copy, readonly) NSString *liveUpdatePackageHash;
- (instancetype)initWithWrapperSdkVersion:(NSString *)wrapperSdkVersion
wrapperSdkName:(NSString *)wrapperSdkName
wrapperRuntimeVersion:(NSString *)wrapperRuntimeVersion
liveUpdateReleaseLabel:(NSString *)liveUpdateReleaseLabel
liveUpdateDeploymentKey:(NSString *)liveUpdateDeploymentKey
liveUpdatePackageHash:(NSString *)liveUpdatePackageHash;
/**
* Checks if the object's values are valid.
*
* @return YES, if the object is valid.
*/
- (BOOL)isValid;
@end
#endif
@@ -0,0 +1,12 @@
framework module AppCenter {
umbrella header "AppCenter.h"
export *
module * { export * }
link framework "Foundation"
link framework "SystemConfiguration"
link framework "AppKit"
link "sqlite3"
link "z"
}
@@ -0,0 +1,110 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSConstants+Flags.h"
@protocol MSChannelUnitProtocol;
@protocol MSChannelGroupProtocol;
@protocol MSChannelProtocol;
@protocol MSLog;
@protocol MSChannelDelegate <NSObject>
@optional
/**
* A callback that is called when a channel unit is added to the channel group.
*
* @param channelGroup The channel group.
* @param channel The newly added channel.
*/
- (void)channelGroup:(id<MSChannelGroupProtocol>)channelGroup didAddChannelUnit:(id<MSChannelUnitProtocol>)channel;
/**
* A callback that is called when a log is just enqueued. Delegates may want to prepare the log a little more before further processing.
*
* @param log The log to prepare.
*/
- (void)channel:(id<MSChannelProtocol>)channel prepareLog:(id<MSLog>)log;
/**
* A callback that is called after a log is definitely prepared.
*
* @param log The log.
* @param internalId An internal Id to keep track of logs.
* @param flags Options for the log.
*/
- (void)channel:(id<MSChannelProtocol>)channel didPrepareLog:(id<MSLog>)log internalId:(NSString *)internalId flags:(MSFlags)flags;
/**
* A callback that is called after a log completed the enqueueing process whether it was successful or not.
*
* @param log The log.
* @param internalId An internal Id to keep track of logs.
*/
- (void)channel:(id<MSChannelProtocol>)channel didCompleteEnqueueingLog:(id<MSLog>)log internalId:(NSString *)internalId;
/**
* Callback method that will be called before each log will be send to the server.
*
* @param channel The channel object.
* @param log The log to be sent.
*/
- (void)channel:(id<MSChannelProtocol>)channel willSendLog:(id<MSLog>)log;
/**
* Callback method that will be called in case the SDK was able to send a log.
*
* @param channel The channel object.
* @param log The log to be sent.
*/
- (void)channel:(id<MSChannelProtocol>)channel didSucceedSendingLog:(id<MSLog>)log;
/**
* Callback method that will be called in case the SDK was unable to send a log.
*
* @param channel The channel object.
* @param log The log to be sent.
* @param error The error that occured.
*/
- (void)channel:(id<MSChannelProtocol>)channel didFailSendingLog:(id<MSLog>)log withError:(NSError *)error;
/**
* A callback that is called when setEnabled has been invoked.
*
* @param channel The channel.
* @param isEnabled The boolean that indicates enabled.
* @param deletedData The boolean that indicates deleting data on disabled.
*/
- (void)channel:(id<MSChannelProtocol>)channel didSetEnabled:(BOOL)isEnabled andDeleteDataOnDisabled:(BOOL)deletedData;
/**
* A callback that is called when pause has been invoked.
*
* @param channel The channel.
* @param identifyingObject The identifying object used to pause the channel.
*/
- (void)channel:(id<MSChannelProtocol>)channel didPauseWithIdentifyingObject:(id<NSObject>)identifyingObject;
/**
* A callback that is called when resume has been invoked.
*
* @param channel The channel.
* @param identifyingObject The identifying object used to resume the channel.
*/
- (void)channel:(id<MSChannelProtocol>)channel didResumeWithIdentifyingObject:(id<NSObject>)identifyingObject;
/**
* Callback method that will determine if a log should be filtered out from the usual processing pipeline. If any delegate returns true, the
* log is filtered.
*
* @param channelUnit The channel unit that is going to send the log.
* @param log The log to be filtered or not.
*
* @return `true` if the log should be filtered out.
*/
- (BOOL)channelUnit:(id<MSChannelUnitProtocol>)channelUnit shouldFilterLog:(id<MSLog>)log;
@end
@@ -0,0 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_CONSTANTS_FLAGS_H
#define MS_CONSTANTS_FLAGS_H
#import <Foundation/Foundation.h>
typedef NS_OPTIONS(NSUInteger, MSFlags) {
MSFlagsNone = (0 << 0), // => 00000000
MSFlagsNormal = (1 << 0), // => 00000001
MSFlagsCritical = (1 << 1), // => 00000010
MSFlagsPersistenceNormal DEPRECATED_MSG_ATTRIBUTE("please use MSFlagsNormal") = MSFlagsNormal,
MSFlagsPersistenceCritical DEPRECATED_MSG_ATTRIBUTE("please use MSFlagsCritical") = MSFlagsCritical,
MSFlagsDefault = MSFlagsNormal
};
#endif
@@ -0,0 +1,44 @@
<?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>BuildMachineOSBuild</key>
<string>19F101</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>AppCenter</string>
<key>CFBundleIdentifier</key>
<string>com.microsoft.appcenter</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>AppCenter</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>11C505</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>19B90</string>
<key>DTSDKName</key>
<string>macosx10.15</string>
<key>DTXcode</key>
<string>1130</string>
<key>DTXcodeBuild</key>
<string>11C505</string>
<key>LSMinimumSystemVersion</key>
<string>10.9</string>
</dict>
</plist>
@@ -0,0 +1 @@
A
@@ -0,0 +1 @@
Versions/Current/AppCenterCrashes
@@ -0,0 +1 @@
Versions/Current/Headers
@@ -0,0 +1 @@
Versions/Current/Modules
@@ -0,0 +1 @@
Versions/Current/Resources
@@ -0,0 +1,11 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSCrashHandlerSetupDelegate.h"
#import "MSCrashes.h"
#import "MSCrashesDelegate.h"
#import "MSErrorAttachmentLog+Utility.h"
#import "MSErrorAttachmentLog.h"
#import "MSWrapperCrashesHelper.h"
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_ABSTRACT_LOG_H
#define MS_ABSTRACT_LOG_H
#import <Foundation/Foundation.h>
@interface MSAbstractLog : NSObject
@end
#endif
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
/**
* This is required for Wrapper SDKs that need to provide custom behavior surrounding the setup of crash handlers.
*/
@protocol MSCrashHandlerSetupDelegate <NSObject>
@optional
/**
* Callback method that will be called immediately before crash handlers are set up.
*/
- (void)willSetUpCrashHandlers;
/**
* Callback method that will be called immediately after crash handlers are set up.
*/
- (void)didSetUpCrashHandlers;
/**
* Callback method that gets a value indicating whether the SDK should enable an uncaught exception handler.
*
* @return YES if SDK should enable uncaught exception handler, otherwise NO.
*
* @discussion Do not register an UncaughtExceptionHandler for Xamarin as we rely on the Xamarin runtime to report NSExceptions. Registering
* our own UncaughtExceptionHandler will cause the Xamarin debugger to not work properly (it will not stop for NSExceptions).
*/
- (BOOL)shouldEnableUncaughtExceptionHandler;
@end
@@ -0,0 +1,171 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import "MSErrorReport.h"
#import "MSServiceAbstract.h"
@class MSCrashesDelegate;
/**
* Custom block that handles the alert that prompts the user whether crash reports need to be processed or not.
*
* @return Returns YES to discard crash reports, otherwise NO.
*/
typedef BOOL (^MSUserConfirmationHandler)(NSArray<MSErrorReport *> *_Nonnull errorReports);
/**
* Error Logging status.
*/
typedef NS_ENUM(NSUInteger, MSErrorLogSetting) {
/**
* Crash reporting is disabled.
*/
MSErrorLogSettingDisabled = 0,
/**
* User is asked each time before sending error logs.
*/
MSErrorLogSettingAlwaysAsk = 1,
/**
* Each error log is send automatically.
*/
MSErrorLogSettingAutoSend = 2
};
/**
* Crash Manager alert user input.
*/
typedef NS_ENUM(NSUInteger, MSUserConfirmation) {
/**
* User chose not to send the crash report.
*/
MSUserConfirmationDontSend = 0,
/**
* User wants the crash report to be sent.
*/
MSUserConfirmationSend = 1,
/**
* User wants to send all error logs.
*/
MSUserConfirmationAlways = 2
};
@protocol MSCrashesDelegate;
@interface MSCrashes : MSServiceAbstract
///-----------------------------------------------------------------------------
/// @name Testing Crashes Feature
///-----------------------------------------------------------------------------
/**
* Lets the app crash for easy testing of the SDK.
*
* The best way to use this is to trigger the crash with a button action.
*
* Make sure not to let the app crash in `applicationDidFinishLaunching` or any other startup method! Since otherwise the app would crash
* before the SDK could process it.
*
* Note that our SDK provides support for handling crashes that happen early on startup. Check the documentation for more information on how
* to use this.
*
* If the SDK detects an App Store environment, it will _NOT_ cause the app to crash!
*/
+ (void)generateTestCrash;
///-----------------------------------------------------------------------------
/// @name Helpers
///-----------------------------------------------------------------------------
/**
* Check if the app has crashed in the last session.
*
* @return Returns YES is the app has crashed in the last session.
*/
+ (BOOL)hasCrashedInLastSession;
/**
* Check if the app received memory warning in the last session.
*
* @return Returns YES is the app received memory warning in the last session.
*/
+ (BOOL)hasReceivedMemoryWarningInLastSession;
/**
* Provides details about the crash that occurred in the last app session
*/
+ (nullable MSErrorReport *)lastSessionCrashReport;
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
/**
* Callback for report exception.
*
* NOTE: This method should be called only if you explicitly disabled swizzling for it.
*
* On OS X runtime, not all uncaught exceptions end in a custom `NSUncaughtExceptionHandler`.
* Forward exception from overrided `[NSApplication reportException:]` to catch additional exceptions.
*/
+ (void)applicationDidReportException:(NSException *_Nonnull)exception;
#endif
///-----------------------------------------------------------------------------
/// @name Configuration
///-----------------------------------------------------------------------------
#if !TARGET_OS_TV
/**
* Disable the Mach exception server.
*
* By default, the SDK uses the Mach exception handler to catch fatal signals, e.g. stack overflows, via a Mach exception server. If you
* want to disable the Mach exception handler, you should call this method _BEFORE_ starting the SDK. Your typical setup code would look
* like this:
*
* `[MSCrashes disableMachExceptionHandler]`;
* `[MSAppCenter start:@"YOUR_APP_ID" withServices:@[[MSCrashes class]]];`
*
* or if you are using Swift:
*
* `MSCrashes.disableMachExceptionHandler()`
* `MSAppCenter.start("YOUR_APP_ID", withServices: [MSAnalytics.self, MSCrashes.self])`
*
* tvOS does not support the Mach exception handler, thus crashes that are caused by stack overflows cannot be detected. As a result,
* disabling the Mach exception server is not available in the tvOS SDK.
*
* @discussion It can be useful to disable the Mach exception handler when you are debugging the Crashes service while developing,
* especially when you attach the debugger to your application after launch.
*/
+ (void)disableMachExceptionHandler;
#endif
/**
* Set the delegate
* Defines the class that implements the optional protocol `MSCrashesDelegate`.
*
* @see MSCrashesDelegate
*/
+ (void)setDelegate:(_Nullable id<MSCrashesDelegate>)delegate;
/**
* Set a user confirmation handler that is invoked right before processing crash reports to determine whether sending crash reports or not.
*
* @param userConfirmationHandler A handler for user confirmation.
*
* @see MSUserConfirmationHandler
*/
+ (void)setUserConfirmationHandler:(_Nullable MSUserConfirmationHandler)userConfirmationHandler;
/**
* Notify SDK with a confirmation to handle the crash report.
*
* @param userConfirmation A user confirmation.
*
* @see MSUserConfirmation.
*/
+ (void)notifyWithUserConfirmation:(MSUserConfirmation)userConfirmation;
@end
@@ -0,0 +1,65 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
@class MSCrashes;
@class MSErrorReport;
@class MSErrorAttachmentLog;
@protocol MSCrashesDelegate <NSObject>
@optional
/**
* Callback method that will be called before processing errors.
*
* @param crashes The instance of MSCrashes.
* @param errorReport The errorReport that will be sent.
*
* @discussion Crashes will send logs to the server or discard/delete logs based on this method's return value.
*/
- (BOOL)crashes:(MSCrashes *)crashes shouldProcessErrorReport:(MSErrorReport *)errorReport;
/**
* Callback method that will be called before each error will be send to the server.
*
* @param crashes The instance of MSCrashes.
* @param errorReport The errorReport that will be sent.
*
* @discussion Use this callback to display custom UI while crashes are sent to the server.
*/
- (void)crashes:(MSCrashes *)crashes willSendErrorReport:(MSErrorReport *)errorReport;
/**
* Callback method that will be called in case the SDK was unable to send an error report to the server.
*
* @param crashes The instance of MSCrashes.
* @param errorReport The errorReport that App Center sent.
*
* @discussion Use this method to hide your custom UI.
*/
- (void)crashes:(MSCrashes *)crashes didSucceedSendingErrorReport:(MSErrorReport *)errorReport;
/**
* Callback method that will be called in case the SDK was unable to send an error report to the server.
*
* @param crashes The instance of MSCrashes.
* @param errorReport The errorReport that App Center tried to send.
* @param error The error that occurred.
*/
- (void)crashes:(MSCrashes *)crashes didFailSendingErrorReport:(MSErrorReport *)errorReport withError:(NSError *)error;
/**
* Method to get the attachments associated to an error report.
*
* @param crashes The instance of MSCrashes.
* @param errorReport The errorReport associated with the returned attachments.
*
* @return The attachments associated with the given error report or nil if the error report doesn't have any attachments.
*
* @discussion Implement this method if you want attachments to the given error report.
*/
- (NSArray<MSErrorAttachmentLog *> *)attachmentsWithCrashes:(MSCrashes *)crashes forErrorReport:(MSErrorReport *)errorReport;
@end
@@ -0,0 +1,32 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import "MSErrorAttachmentLog.h"
// Exporting symbols for category.
extern NSString *MSMSErrorLogAttachmentLogUtilityCategory;
@interface MSErrorAttachmentLog (Utility)
/**
* Create an attachment with a given filename and text.
*
* @param filename The filename the attachment should get. If nil will get an automatically generated filename.
* @param text The attachment text.
*
* @return An instance of `MSErrorAttachmentLog`.
*/
+ (MSErrorAttachmentLog *)attachmentWithText:(NSString *)text filename:(NSString *)filename;
/**
* Create an attachment with a given filename and `NSData` object.
*
* @param filename The filename the attachment should get. If nil will get an automatically generated filename.
* @param data The attachment data as NSData.
* @param contentType The content type of your data as MIME type.
*
* @return An instance of `MSErrorAttachmentLog`.
*/
+ (MSErrorAttachmentLog *)attachmentWithBinary:(NSData *)data filename:(NSString *)filename contentType:(NSString *)contentType;
@end
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSAbstractLog.h"
/**
* Error attachment log.
*/
@interface MSErrorAttachmentLog : MSAbstractLog
/**
* Content type (text/plain for text).
*/
@property(nonatomic, copy) NSString *contentType;
/**
* File name.
*/
@property(nonatomic, copy) NSString *filename;
/**
* The attachment data.
*/
@property(nonatomic, copy) NSData *data;
/**
* Initialize an attachment with a given filename and `NSData` object.
*
* @param filename The filename the attachment should get. If nil will get an automatically generated filename.
* @param data The attachment data as `NSData`.
* @param contentType The content type of your data as MIME type.
*
* @return An instance of `MSErrorAttachmentLog`.
*/
- (instancetype)initWithFilename:(NSString *)filename attachmentBinary:(NSData *)data contentType:(NSString *)contentType;
/**
* Initialize an attachment with a given filename and text.
*
* @param filename The filename the attachment should get. If nil will get an automatically generated filename.
* @param text The attachment text.
*
* @return An instance of `MSErrorAttachmentLog`.
*/
- (instancetype)initWithFilename:(NSString *)filename attachmentText:(NSString *)text;
@end
@@ -0,0 +1,68 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
@class MSDevice;
@interface MSErrorReport : NSObject
/**
* UUID for the crash report.
*/
@property(nonatomic, copy, readonly) NSString *incidentIdentifier;
/**
* UUID for the app installation on the device.
*/
@property(nonatomic, copy, readonly) NSString *reporterKey;
/**
* Signal that caused the crash.
*/
@property(nonatomic, copy, readonly) NSString *signal;
/**
* Exception name that triggered the crash, nil if the crash was not caused by an exception.
*/
@property(nonatomic, copy, readonly) NSString *exceptionName;
/**
* Exception reason, nil if the crash was not caused by an exception.
*/
@property(nonatomic, copy, readonly) NSString *exceptionReason;
/**
* Date and time the app started, nil if unknown.
*/
@property(nonatomic, readonly, strong) NSDate *appStartTime;
/**
* Date and time the error occurred, nil if unknown
*/
@property(nonatomic, readonly, strong) NSDate *appErrorTime;
/**
* Device information of the app when it crashed.
*/
@property(nonatomic, readonly, strong) MSDevice *device;
/**
* Identifier of the app process that crashed.
*/
@property(nonatomic, readonly, assign) NSUInteger appProcessIdentifier;
/**
* Indicates if the app was killed while being in foreground from the iOS.
*
* This can happen if it consumed too much memory or the watchdog killed the app because it took too long to startup or blocks the main
* thread for too long, or other reasons. See Apple documentation:
* https://developer.apple.com/library/ios/qa/qa1693/_index.html.
*
* @return YES if the details represent an app kill instead of a crash.
*
* @see `[MSCrashes didReceiveMemoryWarningInLastSession]`
*/
- (BOOL)isAppKill;
@end
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_SERVICE_H
#define MS_SERVICE_H
#import <Foundation/Foundation.h>
/**
* Protocol declaring service logic.
*/
@protocol MSService <NSObject>
/**
* Enable or disable this service.
* The state is persisted in the device's storage across application launches.
*
* @param isEnabled Whether this service is enabled or not.
*
* @see isEnabled
*/
+ (void)setEnabled:(BOOL)isEnabled;
/**
* Indicates whether this service is enabled.
*
* @return `YES` if this service is enabled, `NO` if it is not.
*
* @see setEnabled:
*/
+ (BOOL)isEnabled;
@end
#endif
@@ -0,0 +1,55 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#ifndef MS_SERVICE_ABSTRACT_H
#define MS_SERVICE_ABSTRACT_H
#import <Foundation/Foundation.h>
#import "MSService.h"
@protocol MSChannelGroupProtocol;
/**
* Abstraction of services common logic.
* This class is intended to be subclassed only not instantiated directly.
*/
@interface MSServiceAbstract : NSObject <MSService>
/**
* The flag indicates whether the service is started from application or not.
*/
@property(nonatomic, assign) BOOL startedFromApplication;
/**
* Start this service with a channel group. Also sets the flag that indicates that a service has been started.
*
* @param channelGroup channel group used to persist and send logs.
* @param appSecret app secret for the SDK.
* @param token default transmission target token for this service.
* @param fromApplication indicates whether the service started from an application or not.
*/
- (void)startWithChannelGroup:(id<MSChannelGroupProtocol>)channelGroup
appSecret:(NSString *)appSecret
transmissionTargetToken:(NSString *)token
fromApplication:(BOOL)fromApplication;
/**
* Update configuration when the service requires to start again. This method should only be called if the service is started from libraries
* and then is being started from an application.
*
* @param appSecret app secret for the SDK.
* @param token default transmission target token for this service.
*/
- (void)updateConfigurationWithAppSecret:(NSString *)appSecret transmissionTargetToken:(NSString *)token;
/**
* Checks if the service needs the application secret.
*
* @return `YES` if the application secret is required, `NO` otherwise.
*/
- (BOOL)isAppSecretRequired;
@end
#endif
@@ -0,0 +1,90 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "MSCrashHandlerSetupDelegate.h"
NS_ASSUME_NONNULL_BEGIN
@class MSErrorReport;
@class MSErrorAttachmentLog;
@class MSException;
/**
* This general class allows wrappers to supplement the Crashes SDK with their own behavior.
*/
@interface MSWrapperCrashesHelper : NSObject
/**
* Sets the crash handler setup delegate.
*
* @param delegate The delegate to set.
*/
+ (void)setCrashHandlerSetupDelegate:(id<MSCrashHandlerSetupDelegate>)delegate;
/**
* Gets the crash handler setup delegate.
*
* @return The delegate being used by Crashes.
*/
+ (id<MSCrashHandlerSetupDelegate>)getCrashHandlerSetupDelegate;
/**
* Enables or disables automatic crash processing.
*
* @param automaticProcessing Passing NO causes SDK not to send reports immediately, even if "Always Send" is true.
*/
+ (void)setAutomaticProcessing:(BOOL)automaticProcessing;
/**
* Gets a list of unprocessed crash reports. Will block until the service starts.
*
* @return An array of unprocessed error reports.
*/
+ (NSArray<MSErrorReport *> *)unprocessedCrashReports;
/**
* Resumes processing for a given subset of the unprocessed reports.
*
* @param filteredIds An array containing the errorId/incidentIdentifier of each report that should be sent.
*
* @return YES if should "Always Send" is true.
*/
+ (BOOL)sendCrashReportsOrAwaitUserConfirmationForFilteredIds:(NSArray<NSString *> *)filteredIds;
/**
* Sends error attachments for a particular error report.
*
* @param errorAttachments An array of error attachments that should be sent.
* @param incidentIdentifier The identifier of the error report that the attachments will be associated with.
*/
+ (void)sendErrorAttachments:(NSArray<MSErrorAttachmentLog *> *)errorAttachments withIncidentIdentifier:(NSString *)incidentIdentifier;
/**
* Track handled exception directly as model form.
* This API is used by wrapper SDKs.
*
* @param exception model form exception.
* @param properties dictionary of properties.
* @param attachments a list of attachments.
*
* @return handled error ID.
*/
+ (nullable NSString *)trackModelException:(MSException *)exception
withProperties:(nullable NSDictionary<NSString *, NSString *> *)properties
withAttachments:(nullable NSArray<MSErrorAttachmentLog *> *)attachments;
/**
* Get a generic error report representation for an handled exception.
* This API is used by wrapper SDKs.
*
* @param errorID handled error ID.
*
* @return an error report.
*/
+ (MSErrorReport *)buildHandledErrorReportWithErrorID:(NSString *)errorID;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,10 @@
framework module AppCenterCrashes {
umbrella header "AppCenterCrashes.h"
export *
module * { export * }
link framework "Foundation"
link "c++"
link "z"
}
@@ -0,0 +1,44 @@
<?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>BuildMachineOSBuild</key>
<string>19F101</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>AppCenterCrashes</string>
<key>CFBundleIdentifier</key>
<string>com.microsoft.appcenter.crashes</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>AppCenterCrashes</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>11C505</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>19B90</string>
<key>DTSDKName</key>
<string>macosx10.15</string>
<key>DTXcode</key>
<string>1130</string>
<key>DTXcodeBuild</key>
<string>11C505</string>
<key>LSMinimumSystemVersion</key>
<string>10.9</string>
</dict>
</plist>
@@ -0,0 +1 @@
A
+7 -1
View File
@@ -1,4 +1,7 @@
PODS:
- AppCenter/Core (3.3.1)
- AppCenter/Crashes (3.3.1):
- AppCenter/Core
- LetsMove (1.24)
- Preferences (1.0.1)
- ShortcutRecorder (3.1)
@@ -6,6 +9,7 @@ PODS:
- SwiftyMarkdown (1.1.0)
DEPENDENCIES:
- AppCenter/Crashes (= 3.3.1)
- LetsMove (from `https://github.com/lwouis/LetsMove.git`, commit `7abf4daed1a25218f2b52f2dfd190aee5a50071c`)
- Preferences (= 1.0.1)
- ShortcutRecorder (from `https://github.com/Kentzo/ShortcutRecorder.git`, commit `f718220854575bad86fa89dd2bb3decd0b14b2b0`)
@@ -14,6 +18,7 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- AppCenter
- Preferences
- SwiftyMarkdown
@@ -36,12 +41,13 @@ CHECKOUT OPTIONS:
:git: https://github.com/Kentzo/ShortcutRecorder.git
SPEC CHECKSUMS:
AppCenter: 76ecf7e959a68e36b0fd314e8dc5897660214423
LetsMove: fefe56bc7bc7fb7d37049e28a14f297961229fc5
Preferences: a5afbe0ae3e6bd886328b1960f4998e65d58f2c4
ShortcutRecorder: fdf620aca34101b0cba3b10fca815e0459254189
Sparkle: ea073ba9c69cee3ebaab8685ba1e732e14d249f7
SwiftyMarkdown: 033abc9dad9a37903f81aec5188cade436f40520
PODFILE CHECKSUM: ccd8822c0e64188b9aaf554188c72ef13a7c81f4
PODFILE CHECKSUM: 356279aa09d4eac74abe0d828422386fe7345766
COCOAPODS: 1.9.1
+696 -577
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
CODE_SIGN_IDENTITY =
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppCenter
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/macOS"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "AppKit" -framework "Foundation" -framework "SystemConfiguration"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/AppCenter
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
@@ -0,0 +1,12 @@
CODE_SIGN_IDENTITY =
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppCenter
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/macOS"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"c++" -l"sqlite3" -l"z" -framework "AppKit" -framework "Foundation" -framework "SystemConfiguration"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/AppCenter
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
@@ -1,6 +1,34 @@
# Acknowledgements
This application makes use of the following third party libraries:
## AppCenter
Visual Studio App Center SDK for Apple platforms
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
## Preferences
MIT License
@@ -12,6 +12,40 @@
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>Visual Studio App Center SDK for Apple platforms
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>AppCenter</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>MIT License
@@ -1,9 +1,9 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove" "${PODS_CONFIGURATION_BUILD_DIR}/Preferences" "${PODS_CONFIGURATION_BUILD_DIR}/ShortcutRecorder" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyMarkdown" "${PODS_ROOT}/Sparkle"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove" "${PODS_CONFIGURATION_BUILD_DIR}/Preferences" "${PODS_CONFIGURATION_BUILD_DIR}/ShortcutRecorder" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyMarkdown" "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/macOS" "${PODS_ROOT}/Sparkle"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove/LetsMove.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Preferences/Preferences.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ShortcutRecorder/ShortcutRecorder.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyMarkdown/SwiftyMarkdown.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' @loader_path/../Frameworks
OTHER_LDFLAGS = $(inherited) -framework "Carbon" -framework "Cocoa" -framework "LetsMove" -framework "Preferences" -framework "ShortcutRecorder" -framework "Sparkle" -framework "SwiftyMarkdown"
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AppCenter" -framework "AppCenterCrashes" -framework "AppKit" -framework "Carbon" -framework "Cocoa" -framework "Foundation" -framework "LetsMove" -framework "Preferences" -framework "ShortcutRecorder" -framework "Sparkle" -framework "SwiftyMarkdown" -framework "SystemConfiguration"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
@@ -1,9 +1,9 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove" "${PODS_CONFIGURATION_BUILD_DIR}/Preferences" "${PODS_CONFIGURATION_BUILD_DIR}/ShortcutRecorder" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyMarkdown" "${PODS_ROOT}/Sparkle"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove" "${PODS_CONFIGURATION_BUILD_DIR}/Preferences" "${PODS_CONFIGURATION_BUILD_DIR}/ShortcutRecorder" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyMarkdown" "${PODS_ROOT}/AppCenter/AppCenter-SDK-Apple/macOS" "${PODS_ROOT}/Sparkle"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/LetsMove/LetsMove.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Preferences/Preferences.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/ShortcutRecorder/ShortcutRecorder.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SwiftyMarkdown/SwiftyMarkdown.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' @loader_path/../Frameworks
OTHER_LDFLAGS = $(inherited) -framework "Carbon" -framework "Cocoa" -framework "LetsMove" -framework "Preferences" -framework "ShortcutRecorder" -framework "Sparkle" -framework "SwiftyMarkdown"
OTHER_LDFLAGS = $(inherited) -ObjC -l"c++" -l"sqlite3" -l"z" -framework "AppCenter" -framework "AppCenterCrashes" -framework "AppKit" -framework "Carbon" -framework "Cocoa" -framework "Foundation" -framework "LetsMove" -framework "Preferences" -framework "ShortcutRecorder" -framework "Sparkle" -framework "SwiftyMarkdown" -framework "SystemConfiguration"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+10 -4
View File
@@ -43,6 +43,7 @@
D04BA48B00B4211A465C7337 /* DebugProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BACABD048E62EBE4576CC /* DebugProfile.swift */; };
D04BA4A11F821548EE3C5E95 /* Bash.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA514F1C4B475B3CA6EB6 /* Bash.swift */; };
D04BA530F00E5989D66C6A1F /* Contributors.md in Resources */ = {isa = PBXBuildFile; fileRef = D04BA812B8DCB915B8F4B915 /* Contributors.md */; };
D04BA56789A2AF52557A9BFF /* AppCenterCrashes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA7E3EA104941FE76DA70 /* AppCenterCrashes.swift */; };
D04BA5863E8AD08C36B52F80 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BAC86E60B1B850059BC54 /* Localizable.strings */; };
D04BA6187A91A847844B6ABB /* Window.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA015A45DE7AFDC9794FE /* Window.swift */; };
D04BA6840A558A00A66CE135 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA2E45431E6927F43C0C3 /* Localizable.strings */; };
@@ -58,7 +59,7 @@
D04BA7BE7F3DD24D58ACE942 /* AppearanceTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA64F1F344007EA13BA05 /* AppearanceTab.swift */; };
D04BA7E39FA539DD8316447A /* PermissionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA0726EABD146753B9EF8 /* PermissionView.swift */; };
D04BA7F86F1926FBE31F44BF /* BaseLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA53992F116E5E704CAB3 /* BaseLabel.swift */; };
D04BA8092885B40CE3527370 /* UpdatesTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAD60C97E609A759E721E /* UpdatesTab.swift */; };
D04BA8092885B40CE3527370 /* PoliciesTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BAD60C97E609A759E721E /* PoliciesTab.swift */; };
D04BA83AF2B1C3C5166C119F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BAD58DF3FA085A45BEB50 /* InfoPlist.strings */; };
D04BA8480A8FF466CA89DA5B /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04BA70746DEEC3D30B43F81 /* main.swift */; };
D04BA867733CC32975EEDA7B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D04BA64436BF69C58372968C /* InfoPlist.strings */; };
@@ -183,6 +184,7 @@
D04BA68C2561D9EE4FD851B8 /* Screen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Screen.swift; sourceTree = "<group>"; };
D04BA6BBFD0E87B8458E91D3 /* feature-suggestion.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = "feature-suggestion.md"; sourceTree = "<group>"; };
D04BA6D57A1456C07318B8EA /* GridView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridView.swift; sourceTree = "<group>"; };
D04BA6ED38651224DB117A5A /* upload_symbols_to_appcenter.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = upload_symbols_to_appcenter.sh; sourceTree = "<group>"; };
D04BA6EF1954DCE80E539142 /* base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = base.xcconfig; sourceTree = "<group>"; };
D04BA6F823BC0EDA9AA4B80A /* AXUIElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AXUIElement.swift; sourceTree = "<group>"; };
D04BA70746DEEC3D30B43F81 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
@@ -200,6 +202,7 @@
D04BA7C836A8CE8C0B8D128B /* TextArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextArea.swift; sourceTree = "<group>"; };
D04BA7CF9C2D1BEC7C05AB24 /* Spaces.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spaces.swift; sourceTree = "<group>"; };
D04BA7E388B365A41C92E31B /* safari-pinned-tab.svg */ = {isa = PBXFileReference; lastKnownFileType = file.svg; path = "safari-pinned-tab.svg"; sourceTree = "<group>"; };
D04BA7E3EA104941FE76DA70 /* AppCenterCrashes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppCenterCrashes.swift; sourceTree = "<group>"; };
D04BA7F8F1F44D5D9844BFF5 /* ar */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ar; path = InfoPlist.strings; sourceTree = "<group>"; };
D04BA812B8DCB915B8F4B915 /* Contributors.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Contributors.md; sourceTree = "<group>"; };
D04BA81B25C166EFB3223639 /* extract_l10n_strings.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = extract_l10n_strings.sh; sourceTree = "<group>"; };
@@ -255,7 +258,7 @@
D04BAD241A6928F45355B315 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = Localizable.strings; sourceTree = "<group>"; };
D04BAD2A5EFA477F1BC436B4 /* import_certificate_into_new_keychain.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = import_certificate_into_new_keychain.sh; sourceTree = "<group>"; };
D04BAD40CE2D3A8AAC3819D0 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = file.gitignore; path = .gitignore; sourceTree = "<group>"; };
D04BAD60C97E609A759E721E /* UpdatesTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatesTab.swift; sourceTree = "<group>"; };
D04BAD60C97E609A759E721E /* PoliciesTab.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PoliciesTab.swift; sourceTree = "<group>"; };
D04BAD65AA870A49D2F89DBC /* ensure_generated_files_are_up_to_date.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ensure_generated_files_are_up_to_date.sh; sourceTree = "<group>"; };
D04BAD6700415D6F7C8B2BEE /* travis.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = travis.sh; sourceTree = "<group>"; };
D04BAD7008ED1D9CBC147A75 /* pull_request_template.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = pull_request_template.md; sourceTree = "<group>"; };
@@ -341,6 +344,7 @@
D04BAB74451B79FE18B8BEDF /* BackgroundWork.swift */,
D04BACABD048E62EBE4576CC /* DebugProfile.swift */,
D04BAC8857A527C2E15D6598 /* events */,
D04BA7E3EA104941FE76DA70 /* AppCenterCrashes.swift */,
);
path = logic;
sourceTree = "<group>";
@@ -480,7 +484,7 @@
D04BA64F1F344007EA13BA05 /* AppearanceTab.swift */,
D04BA4A26987F67DD94C827F /* AboutTab.swift */,
D04BACE22DC907F03D193075 /* GeneralTab.swift */,
D04BAD60C97E609A759E721E /* UpdatesTab.swift */,
D04BAD60C97E609A759E721E /* PoliciesTab.swift */,
D04BA788228BA86D9EFBD1ED /* AcknowledgmentsTab.swift */,
D04BA27695D9A5824720BD7B /* BlacklistsTab.swift */,
);
@@ -629,6 +633,7 @@
D04BA4D5DF349429527824A2 /* determine_version.sh */,
D04BAAE6E6823304D66B74F8 /* update_website.sh */,
D04BA7A758026814667273DC /* convert_iconset_to_icns.sh */,
D04BA6ED38651224DB117A5A /* upload_symbols_to_appcenter.sh */,
);
path = scripts;
sourceTree = "<group>";
@@ -1083,7 +1088,7 @@
D04BA7BE7F3DD24D58ACE942 /* AppearanceTab.swift in Sources */,
D04BAD1BE9DC22C48C53D195 /* AboutTab.swift in Sources */,
D04BA15A1B0C4871EA7CB899 /* GeneralTab.swift in Sources */,
D04BA8092885B40CE3527370 /* UpdatesTab.swift in Sources */,
D04BA8092885B40CE3527370 /* PoliciesTab.swift in Sources */,
D04BAD451966B43720120D2E /* Menubar.swift in Sources */,
D04BA2E64C59D96F6EB27D9D /* FeedbackWindow.swift in Sources */,
D04BA76A74267B1346D23687 /* GridView.swift in Sources */,
@@ -1106,6 +1111,7 @@
D04BA446D702C5E252AF2319 /* TitleLabel.swift in Sources */,
D04BAD43C122A1C7E88B0362 /* MouseEvents.swift in Sources */,
D04BAFF30A98CF287F85DA1E /* BlacklistsTab.swift in Sources */,
D04BA56789A2AF52557A9BFF /* AppCenterCrashes.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+27 -3
View File
@@ -34,9 +34,15 @@
/* No comment provided by engineer. */
"Allowed" = "Allowed";
/* No comment provided by engineer. */
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/* No comment provided by engineer. */
"AltTab needs some permissions" = "AltTab needs some permissions";
/* No comment provided by engineer. */
"Always send crash reports" = "Always send crash reports";
/* No comment provided by engineer. */
"and press:" = "and press:";
@@ -52,6 +58,9 @@
/* No comment provided by engineer. */
"Arrow keys" = "Arrow keys";
/* No comment provided by engineer. */
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/* No comment provided by engineer. */
"Auto-install updates periodically" = "Auto-install updates periodically";
@@ -79,9 +88,15 @@
/* No comment provided by engineer. */
"Close window" = "Close window";
/* No comment provided by engineer. */
"Crash reports policy:" = "Crash reports policy:";
/* No comment provided by engineer. */
"Dont check for updates periodically" = "Dont check for updates periodically";
/* No comment provided by engineer. */
"Dont send" = "Dont send";
/* No comment provided by engineer. */
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -148,6 +163,9 @@
/* No comment provided by engineer. */
"Mouse hover" = "Mouse hover";
/* No comment provided by engineer. */
"Never send crash reports" = "Never send crash reports";
/* No comment provided by engineer. */
"Not allowed" = "Not allowed";
@@ -166,6 +184,9 @@
/* No comment provided by engineer. */
"or press:" = "or press:";
/* No comment provided by engineer. */
"Policies" = "Policies";
/* Menubar option */
"Preferences…" = "Preferences…";
@@ -178,6 +199,9 @@
/* No comment provided by engineer. */
"Quit app" = "Quit app";
/* No comment provided by engineer. */
"Remember my choice" = "Remember my choice";
/* No comment provided by engineer. */
"Rows of windows:" = "Rows of windows:";
@@ -205,6 +229,9 @@
/* No comment provided by engineer. */
"Send" = "Send";
/* No comment provided by engineer. */
"Send a crash report?" = "Send a crash report?";
/* No comment provided by engineer. */
"Send anyway" = "Send anyway";
@@ -253,9 +280,6 @@
/* No comment provided by engineer. */
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/* No comment provided by engineer. */
"Updates" = "Updates";
/* No comment provided by engineer. */
"Updates policy:" = "Updates policy:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "أزرار الأسهم";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "تثبيت التحديثات بشكل دوري تلقائي";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "إغلاق النافذة";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "لا تبحث عن تحديثات بشكل دوري";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "تمرير المؤشر";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "التفضيلات…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "إغلاق البرنامج";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "صفوف النوافذ:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "إرسال";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "إرسال على أية حال";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "تحديثات";
/*No comment provided by engineer.*/
"Updates policy:" = "سياسة التحديثات:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Erlaubt";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab braucht einige Berechtigungen";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Pfeiltasten";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Updates regelmäßig automatisch installieren";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Fenster schließen";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Nicht regelmäßig nach Updates suchen";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Fenster dieser Anwendungen nicht anzeigen";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Maus hover";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Nicht erlaubt";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Einstellungen…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "App beenden";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Fenster Reihen:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Senden";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Trotzdem senden";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Diese Erlaubnis is nötig um Bildschirmaufnahmen und Titel offener Fenster anzuzeigen";
/*No comment provided by engineer.*/
"Updates" = "Updates";
/*No comment provided by engineer.*/
"Updates policy:" = "Update Richtlinie:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Arrow keys";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Auto-install updates periodically";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Close window";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Dont check for updates periodically";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Mouse hover";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Preferences…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Quit app";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Rows of windows:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Send";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Updates";
/*No comment provided by engineer.*/
"Updates policy:" = "Updates policy:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Teclas de flecha";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Auto instalar actualizaciones periódicamente";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Cerrar ventana";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "No comprobar actualizaciones periódicamente";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Al pasar el ratón";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Preferencias…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Cerrar aplicación";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Filas de ventanas:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Enviar";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Actualizaciones";
/*No comment provided by engineer.*/
"Updates policy:" = "Política de actualizaciones:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Nuolinäppäimet";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Asenna päivitykset automaattisesti aika ajoin";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Sulje ikkuna";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Älä tarkista päivityksiä";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Hiiren liike";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Asetukset…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Sulje ohjelma";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Ikkunarivejä:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Lähetä";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Päivitykset";
/*No comment provided by engineer.*/
"Updates policy:" = "Päivityspolitiikka:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Autorisé";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab a besoin de permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Touches flèches";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Auto-installer les mises-à-jour périodiquement";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Fermer la fenêtre";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Ne pas chercher de mise-à-jour périodiquement";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Ne pas afficher les fenêtres de ces applications";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Survol de la souris";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Non autorisé";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Préférences…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Quitter lapp";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Rangées de fenêtres:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Envoyer";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Envoyer tout de même";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Cette permission est nécessaire pour afficher les miniatures et titres des fenêtres ouvertes";
/*No comment provided by engineer.*/
"Updates" = "Mises-à-jour";
/*No comment provided by engineer.*/
"Updates policy:" = "Politique de mise-à-jour:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Engedélyezve";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "Az AltTab-nak néhány jogosultságra van szüksége";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Nyíl billentyűk";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Frissítések automatikus telepítése";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Ablak bezárása";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Ne keressen frissítéseket automatikusan";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Ablakok elrejtése ezekből az alkalmazásokból";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Egér főlé vitele";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Nincs engedélyezve";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Beállítások…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Kilépés az alkalmazásból";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Ablak sorok száma:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Küldés";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Küldés mindenképp";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Ez a jogosultság ahhoz szükséges hogy megjeleníthessük a képernyőképeket és csempéket a nyitott ablakokhoz";
/*No comment provided by engineer.*/
"Updates" = "Frissítések";
/*No comment provided by engineer.*/
"Updates policy:" = "Frissítési beállítások:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Dibolehkan";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab membutuhkan beberapa izin";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Tombol panah";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Instal pembaruan secara berkala";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Tutup jendela";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Jangan periksa pembaruan secara berkala";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Jangan tampilkan jendela dari aplikasi ini";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Arahkan mouse";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Tidak dibolehkan";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Preferensi…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Keluar app";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Barisan jendela:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Kirim";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Tetap kirim";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "Izin ini diperlukan untuk menampilkan tangkapan layar dan judul jendela yang terbuka";
/*No comment provided by engineer.*/
"Updates" = "Pembaruan";
/*No comment provided by engineer.*/
"Updates policy:" = "Kebijakan pembaruan:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Tasti freccia";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "La procedure di auto-install aggiorna periodicamente";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Chiudi la finestra";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Non controllare gli aggiornamenti periodicamente";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Passa il mouse";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Preferenze…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Esci dall'app";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "File di finestre:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Invia";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Aggiornamenti";
/*No comment provided by engineer.*/
"Updates policy:" = "Politica sugli aggiornamenti:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "カーソルキー";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "更新を定期的に自動インストールする";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "ウィンドウを閉じる";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "定期的に更新を確認しない";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "マウスホバー";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "環境設定…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "アプリケーションを終了";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "ウィンドウ列:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "送信";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "アップデート";
/*No comment provided by engineer.*/
"Updates policy:" = "アップデートポリシー:";
+31 -7
View File
@@ -35,11 +35,17 @@
/*No comment provided by engineer.*/
"Allowed" = "허용됨";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab이 권한을 필요로 합니다";
/*No comment provided by engineer.*/
"and press:" = "and press:";
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "와 다음을 누르면:";
/*No comment provided by engineer.*/
"Apparition delay:" = "나타나는 지연 시간:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "방향키";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "자동으로 업데이트 설치하기";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "윈도우 닫기";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "주기적으로 업데이트를 확인하지 않기";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "다음 앱들의 윈도우가 보여지지 않습니다";
@@ -93,7 +108,7 @@
"Fade out animation:" = "페이드 아웃 애니메이션:";
/*No comment provided by engineer.*/
"Focus selected window" = "Focus selected window";
"Focus selected window" = "선택된 윈도우로 이동";
/*No comment provided by engineer.*/
"Fullscreen" = "전체화면";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "마우스 올려놓기";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "허용되지 않음";
@@ -168,7 +186,10 @@
"Optional: email (if you want a reply)" = "답변을 원하면 이메일 주소를 남겨주세요";
/*No comment provided by engineer.*/
"or press:" = "or press:";
"or press:" = "또는 다음을 누르면:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "설정…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "앱 종료";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "윈도우 줄 개수:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "보내기";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "보내기";
@@ -249,7 +276,7 @@
"Theme:" = "테마:";
/*No comment provided by engineer.*/
"then release:" = "then release:";
"then release:" = "놓으면:";
/*No comment provided by engineer.*/
"This permission is needed to focus windows after you release the shortcut" = "이 권한은 단축키를 사용했을 때 원하는 윈도우로 이동할 수 있게 해줍니다";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "이 권한은 윈도우의 이미지와 제목을 띄울 수 있게 해줍니다";
/*No comment provided by engineer.*/
"Updates" = "업데이트";
/*No comment provided by engineer.*/
"Updates policy:" = "업데이트 방법:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Feiltasten";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Automatesch reegelméisseg Updates installéiren";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Close window";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Net reegelméisseg no Updates sichen";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Mouse hover";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Astellung…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Quit app";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Rows of windows:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Fortschécken";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Update";
/*No comment provided by engineer.*/
"Updates policy:" = "Updates policy:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Pijltjestoetsen";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Installeer regelmatig automatisch updates";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Sluit venster";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Controleer niet regelmatig op updates";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Muisbeweging";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Voorkeuren…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Sluit programma";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Aantal vensterrijen:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Verstuur";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Verstuur toch";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Updates";
/*No comment provided by engineer.*/
"Updates policy:" = "Updatebeleid:";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Teclas direcionais";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Instalar atualizações periódicas automaticamente";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Fechar janela";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Não verifique periodicamente por atualizações";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Ao passar o mouse";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Preferências";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Fechar aplicação";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Linhas de janelas:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Enviar";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Atualizações";
/*No comment provided by engineer.*/
"Updates policy:" = "Regras de atualização:";
+47 -23
View File
@@ -3,7 +3,7 @@
"About" = "О программе";
/*No comment provided by engineer.*/
"Accessibility" = "Accessibility";
"Accessibility" = "Универсальный доступ";
/*No comment provided by engineer.*/
"Acknowledgments" = "Лицензии";
@@ -33,13 +33,19 @@
"All spaces" = "Все рабочие столы";
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
"Allowed" = "Разрешено";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"and press:" = "and press:";
"AltTab needs some permissions" = "AltTab требуются некоторые разрешения";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "и нажать:";
/*No comment provided by engineer.*/
"Apparition delay:" = "Задержка появления:";
@@ -53,11 +59,14 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Клавиши стрелок";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Автоматически устанавливать обновления";
/*No comment provided by engineer.*/
"Blacklists" = "Blacklists";
"Blacklists" = "Черные списки";
/*Cancel button*/
"Cancel" = "Отмена";
@@ -80,14 +89,20 @@
/*No comment provided by engineer.*/
"Close window" = "Закрыть окно";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Не проверять обновления";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"End" = "End";
"Dont show windows from these apps" = "Не показывать окна этих приложений";
/*No comment provided by engineer.*/
"End" = "Конец";
/*No comment provided by engineer.*/
"Fade out animation:" = "Анимация затухания:";
@@ -105,7 +120,7 @@
"Hidden" = "Скрытые";
/*No comment provided by engineer.*/
"Hide menubar icon:" = "Hide menubar icon:";
"Hide menubar icon:" = "Скрыть иконку из строки меню:";
/*No comment provided by engineer.*/
"Hide space number labels:" = "Скрыть номера рабочих столов:";
@@ -120,7 +135,7 @@
"I think the app could be improved with…" = "Я думаю, что приложение может быть улучшено…";
/*No comment provided by engineer.*/
"Ignore shortcuts while a window from these apps is active" = "Ignore shortcuts while a window from these apps is active";
"Ignore shortcuts while a window from these apps is active" = "Игнорировать комбинации клавиш пока окно приложения из этого списка активно";
/*No comment provided by engineer.*/
"Latest releases" = "Последние обновления";
@@ -135,7 +150,7 @@
"Max windows per row:" = "Макс. количество окон в ряду:";
/*No comment provided by engineer.*/
"Middle" = "Middle";
"Middle" = "Посередине";
/*No comment provided by engineer.*/
"Min windows per row:" = "Мин. количество окон в ряду:";
@@ -150,19 +165,22 @@
"Mouse hover" = "Наведение мышью";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Не разрешено";
/*Copyright (human-readable)*/
"NSHumanReadableCopyright" = "Лицензия GPL-3.0";
/*No comment provided by engineer.*/
"Only if the window is fullscreen" = "Only if the window is fullscreen";
"Only if the window is fullscreen" = "Только если окно на полный экран";
/*No comment provided by engineer.*/
"Open Accessibility Preferences…" = "Open Accessibility Preferences…";
"Open Accessibility Preferences…" = "Открыть настройки Универсального доступа…";
/*No comment provided by engineer.*/
"Open Screen Recording Preferences…" = "Open Screen Recording Preferences…";
"Open Screen Recording Preferences…" = "Открыть настройки Записи экрана…";
/*No comment provided by engineer.*/
"Optional: email (if you want a reply)" = "Опционально: эл.почта (если вы хотите ответа)";
@@ -170,11 +188,14 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Настройки…";
/*No comment provided by engineer.*/
"Quit" = "Quit";
"Quit" = "Выход";
/*No comment provided by engineer.*/
"Quit %@" = "Выход из %@";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Выйти из приложения";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Количество рядов окон:";
@@ -192,7 +216,7 @@
"Screen including mouse" = "Экран с курсором";
/*No comment provided by engineer.*/
"Screen Recording" = "Screen Recording";
"Screen Recording" = "Запись экрана";
/*No comment provided by engineer.*/
"Screen showing AltTab" = "Экран, показывающий AltTab";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Отправить";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Все равно отправить";
@@ -240,7 +267,7 @@
"Source code repository" = "Репозиторий исходного кода";
/*No comment provided by engineer.*/
"Start" = "Start";
"Start" = "Начало";
/*No comment provided by engineer.*/
"Start at login:" = "Запускать при входе в систему:";
@@ -252,13 +279,10 @@
"then release:" = "then release:";
/*No comment provided by engineer.*/
"This permission is needed to focus windows after you release the shortcut" = "This permission is needed to focus windows after you release the shortcut";
"This permission is needed to focus windows after you release the shortcut" = "Это разрешение нужно для фокусировки окна после отпускания комбинации клавиш";
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Обновления";
"This permission is needed to show screenshots and titles of open windows" = "Это разрешение нужно для показа скриншотов и заголовков открытых окон";
/*No comment provided by engineer.*/
"Updates policy:" = "Правило обновлений:";
@@ -276,7 +300,7 @@
"Window title font size:" = "Размер заголовка:";
/*No comment provided by engineer.*/
"Window title truncation:" = "Window title truncation:";
"Window title truncation:" = "Обрезка заголовка окна:";
/*No comment provided by engineer.*/
"You didnt write your email, thus cant receive any response." = "Вы не написали свою электронную почту, поэтому не можете получить ответ.";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "Yön tuşları";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "Güncellemeleri periyodik olarak otomatik yükle";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "Pencereyi kapat";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "Güncellemeleri periyodik olarak kontrol etme";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "Fare ";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "Tercihler…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "Uygulamadan çık";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "Pencere satırları:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "Gönder";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "Send anyway";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "Güncellemeler";
/*No comment provided by engineer.*/
"Updates policy:" = "Güncelleme politikası:";
+39 -15
View File
@@ -35,11 +35,17 @@
/*No comment provided by engineer.*/
"Allowed" = "允许";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab 需要获取一些隐私权限";
/*No comment provided by engineer.*/
"and press:" = "and press:";
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "并点击";
/*No comment provided by engineer.*/
"Apparition delay:" = "切换窗口出现延迟:";
@@ -53,11 +59,14 @@
/*No comment provided by engineer.*/
"Arrow keys" = "方向键";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "定期自动安装更新";
/*No comment provided by engineer.*/
"Blacklists" = "Blacklists";
"Blacklists" = "禁止名单";
/*Cancel button*/
"Cancel" = "取消";
@@ -80,20 +89,26 @@
/*No comment provided by engineer.*/
"Close window" = "关闭窗口";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "不自动检查更新";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"End" = "End";
"Dont show windows from these apps" = "不显示这些应用程序的窗口";
/*No comment provided by engineer.*/
"End" = "结尾";
/*No comment provided by engineer.*/
"Fade out animation:" = "淡出动画:";
/*No comment provided by engineer.*/
"Focus selected window" = "Focus selected window";
"Focus selected window" = "前置选中窗口";
/*No comment provided by engineer.*/
"Fullscreen" = "全屏";
@@ -120,7 +135,7 @@
"I think the app could be improved with…" = "我认为该应用程序可以这样改进…";
/*No comment provided by engineer.*/
"Ignore shortcuts while a window from these apps is active" = "Ignore shortcuts while a window from these apps is active";
"Ignore shortcuts while a window from these apps is active" = "这些应用程序的窗口处于活动状态时,忽略快捷键";
/*No comment provided by engineer.*/
"Latest releases" = "最新版本";
@@ -135,7 +150,7 @@
"Max windows per row:" = "每行最多窗口数:";
/*No comment provided by engineer.*/
"Middle" = "Middle";
"Middle" = "中间";
/*No comment provided by engineer.*/
"Min windows per row:" = "每行最少窗口数:";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "鼠标悬停";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "阻止";
@@ -156,7 +174,7 @@
"NSHumanReadableCopyright" = "GPL-3.0 协议";
/*No comment provided by engineer.*/
"Only if the window is fullscreen" = "Only if the window is fullscreen";
"Only if the window is fullscreen" = "仅当窗口全屏时";
/*No comment provided by engineer.*/
"Open Accessibility Preferences…" = "打开辅助功能偏好设置";
@@ -168,7 +186,10 @@
"Optional: email (if you want a reply)" = "电子邮箱地址 (可选,若想接收答复)";
/*No comment provided by engineer.*/
"or press:" = "or press:";
"or press:" = "或点击";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "偏好设置…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "退出应用";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "窗口行数:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "发送";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "仍然发送";
@@ -240,7 +267,7 @@
"Source code repository" = "源代码仓库";
/*No comment provided by engineer.*/
"Start" = "Start";
"Start" = "开始";
/*No comment provided by engineer.*/
"Start at login:" = "开机启动:";
@@ -249,7 +276,7 @@
"Theme:" = "主题:";
/*No comment provided by engineer.*/
"then release:" = "then release:";
"then release:" = "然后松开";
/*No comment provided by engineer.*/
"This permission is needed to focus windows after you release the shortcut" = "需要此权限在释放快捷键后切换鼠标焦点";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "需要此权限来显示打开窗口的截屏和标题";
/*No comment provided by engineer.*/
"Updates" = "更新";
/*No comment provided by engineer.*/
"Updates policy:" = "更新方式:";
@@ -276,7 +300,7 @@
"Window title font size:" = "窗口标题字号:";
/*No comment provided by engineer.*/
"Window title truncation:" = "Window title truncation:";
"Window title truncation:" = "窗口标题截断:";
/*No comment provided by engineer.*/
"You didnt write your email, thus cant receive any response." = "未填写电子邮箱地址将无法收到回复。";
+27 -3
View File
@@ -35,9 +35,15 @@
/*No comment provided by engineer.*/
"Allowed" = "Allowed";
/*No comment provided by engineer.*/
"AltTab crashed last time you used it. Sending a crash report will help get the issue fixed" = "AltTab crashed last time you used it. Sending a crash report will help get the issue fixed";
/*No comment provided by engineer.*/
"AltTab needs some permissions" = "AltTab needs some permissions";
/*No comment provided by engineer.*/
"Always send crash reports" = "Always send crash reports";
/*No comment provided by engineer.*/
"and press:" = "and press:";
@@ -53,6 +59,9 @@
/*No comment provided by engineer.*/
"Arrow keys" = "方向鍵";
/*No comment provided by engineer.*/
"Ask whether to send crash reports" = "Ask whether to send crash reports";
/*No comment provided by engineer.*/
"Auto-install updates periodically" = "定期自動安裝更新";
@@ -80,9 +89,15 @@
/*No comment provided by engineer.*/
"Close window" = "關閉視窗";
/*No comment provided by engineer.*/
"Crash reports policy:" = "Crash reports policy:";
/*No comment provided by engineer.*/
"Dont check for updates periodically" = "不要定期自動檢查更新";
/*No comment provided by engineer.*/
"Dont send" = "Dont send";
/*No comment provided by engineer.*/
"Dont show windows from these apps" = "Dont show windows from these apps";
@@ -149,6 +164,9 @@
/*No comment provided by engineer.*/
"Mouse hover" = "滑鼠懸停";
/*No comment provided by engineer.*/
"Never send crash reports" = "Never send crash reports";
/*No comment provided by engineer.*/
"Not allowed" = "Not allowed";
@@ -170,6 +188,9 @@
/*No comment provided by engineer.*/
"or press:" = "or press:";
/*No comment provided by engineer.*/
"Policies" = "Policies";
/*No comment provided by engineer.*/
"Preferences…" = "偏好設定…";
@@ -182,6 +203,9 @@
/*No comment provided by engineer.*/
"Quit app" = "離開程式";
/*No comment provided by engineer.*/
"Remember my choice" = "Remember my choice";
/*No comment provided by engineer.*/
"Rows of windows:" = "每列視窗數:";
@@ -209,6 +233,9 @@
/*No comment provided by engineer.*/
"Send" = "送出";
/*No comment provided by engineer.*/
"Send a crash report?" = "Send a crash report?";
/*No comment provided by engineer.*/
"Send anyway" = "送出";
@@ -257,9 +284,6 @@
/*No comment provided by engineer.*/
"This permission is needed to show screenshots and titles of open windows" = "This permission is needed to show screenshots and titles of open windows";
/*No comment provided by engineer.*/
"Updates" = "更新";
/*No comment provided by engineer.*/
"Updates policy:" = "更新策略:";
@@ -6,3 +6,4 @@ version="$(cat $VERSION_FILE)"
sed -i '' -e "s/#VERSION#/$version/" Info.plist
sed -i '' -e "s/#FEEDBACK_TOKEN#/$FEEDBACK_TOKEN/" Info.plist
sed -i '' -e "s/#APPCENTER_SECRET#/$APPCENTER_SECRET/" Info.plist
+1
View File
@@ -15,6 +15,7 @@ if [ $IS_RELEASE ]; then
scripts/codesign/setup_ci_master.sh
xcodebuild -workspace alt-tab-macos.xcworkspace -scheme Release -derivedDataPath DerivedData
scripts/package_and_notarize_release.sh
scripts/upload_symbols_to_appcenter.sh
scripts/update_appcast.sh
npx semantic-release
scripts/update_website.sh
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
set -exu
ownerName="alt-tab-macos"
appName="alt-tab-macos"
url="https://api.appcenter.ms/v0.1/apps/$ownerName/$appName"
version="$(cat $VERSION_FILE)"
symbolFile="$APP_NAME.app.dSYM"
function firstCall() {
curl -X POST "$url/symbol_uploads" \
-H "X-API-Token: $APPCENTER_TOKEN" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d "{ \"symbol_type\": \"Apple\", \"version\": \"$version\" }"
}
cd "$XCODE_BUILD_PATH"
ditto -c -k --keepParent "$symbolFile" "$symbolFile.zip"
c1="$(firstCall)"
symbol_upload_id="$(jq -r '.symbol_upload_id' <<<"$c1")"
upload_url="$(jq -r '.upload_url' <<<"$c1")"
curl -X PUT "$upload_url" \
-H "x-ms-blob-type: BlockBlob" \
--upload-file "$symbolFile.zip"
curl -X PATCH "$url/symbol_uploads/$symbol_upload_id" \
-H "X-API-Token: $APPCENTER_TOKEN" \
-H "accept: application/json" \
-H "Content-Type: application/json" \
-d '{ "status": "committed" }'
+55
View File
@@ -0,0 +1,55 @@
import Cocoa
import AppCenter
import AppCenterCrashes
class AppCenterCrash: NSObject, MSCrashesDelegate {
static let secret = Bundle.main.object(forInfoDictionaryKey: "AppCenterSecret") as! String
override init() {
super.init()
// Enable catching uncaught exceptions thrown on the main thread
UserDefaults.standard.register(defaults: ["NSApplicationCrashOnExceptions": true])
// MSAppCenter.setLogLevel(MSLogLevel.none)
MSAppCenter.start(AppCenterCrash.secret, withServices: [MSCrashes.self])
MSCrashes.setDelegate(self)
MSCrashes.setUserConfirmationHandler({ (errorReports: [MSErrorReport]) in
if Preferences.crashPolicy == .ask {
App.app.activate(ignoringOtherApps: true)
let alert = NSAlert()
alert.alertStyle = .warning
alert.messageText = NSLocalizedString("Send a crash report?", comment: "")
alert.informativeText = NSLocalizedString("AltTab crashed last time you used it. Sending a crash report will help get the issue fixed", comment: "")
alert.addButton(withTitle: NSLocalizedString("Send", comment: "")).setAccessibilityFocused(true)
let cancelButton = alert.addButton(withTitle: NSLocalizedString("Dont send", comment: ""))
cancelButton.keyEquivalent = "\u{1b}"
let checkbox = NSButton(checkboxWithTitle: NSLocalizedString("Remember my choice", comment: ""), target: nil, action: nil)
alert.accessoryView = checkbox
let userChoice = alert.runModal()
let id = self.crashButtonIdToUpdate(userChoice, checkbox)
PoliciesTab.crashButtons[id].state = .on
Preferences.set("crashPolicy", String(id))
BackgroundWork.crashReportsQueue.async { MSCrashes.notify(with: userChoice == .alertFirstButtonReturn ? .send : .dontSend) }
} else {
BackgroundWork.crashReportsQueue.async { MSCrashes.notify(with: Preferences.crashPolicy == .always ? .send : .dontSend) }
}
return true
})
}
func crashButtonIdToUpdate(_ userChoice: NSApplication.ModalResponse, _ checkbox: NSButton) -> Int {
if userChoice == .alertFirstButtonReturn {
if checkbox.state == .on {
return 2
}
return 1
}
if checkbox.state == .on {
return 0
}
return 1
}
func attachments(with crashes: MSCrashes, for errorReport: MSErrorReport) -> [MSErrorAttachmentLog] {
return [MSErrorAttachmentLog.attachment(withText: DebugProfile.make(), filename: "debug-profile.md")!]
}
}
+2
View File
@@ -5,6 +5,7 @@ class BackgroundWork {
static var mainQueueConcurrentWorkQueue: DispatchQueue!
static var accessibilityCommandsQueue: DispatchQueue!
static var axCallsQueue: DispatchQueue!
static var crashReportsQueue: DispatchQueue!
static var accessibilityEventsThread: BackgroundThreadWithRunLoop!
static var keyboardEventsThread: BackgroundThreadWithRunLoop!
static var mouseEventsThread: BackgroundThreadWithRunLoop!
@@ -17,6 +18,7 @@ class BackgroundWork {
mainQueueConcurrentWorkQueue = DispatchQueue.globalConcurrent("mainQueueConcurrentWorkQueue", .userInteractive)
accessibilityCommandsQueue = DispatchQueue.globalConcurrent("accessibilityCommandsQueue", .userInteractive)
axCallsQueue = DispatchQueue.globalConcurrent("axCallsQueue", .userInteractive)
crashReportsQueue = DispatchQueue.globalConcurrent("crashReportsQueue", .utility)
accessibilityEventsThread = BackgroundThreadWithRunLoop("accessibilityEventsThread")
keyboardEventsThread = BackgroundThreadWithRunLoop("keyboardEventsThread")
mouseEventsThread = BackgroundThreadWithRunLoop("mouseEventsThread")
+48 -16
View File
@@ -45,6 +45,8 @@ class Preferences {
"dontShowBlacklist": "",
"disableShortcutsBlacklist": ["com.realvnc.vncviewer", "com.microsoft.rdc.macos", "com.teamviewer.TeamViewer", "org.virtualbox.app.VirtualBoxVM", "com.parallels.vm", "com.citrix.XenAppViewer"].joined(separator: "\n"),
"disableShortcutsBlacklistOnlyFullscreen": "true",
"updatePolicy": "1",
"crashPolicy": "1",
].merging(defaultsDependingOnScreenRatio()) { (_, new) in new }
// constant values
@@ -91,6 +93,8 @@ class Preferences {
static var showOnScreen: ShowOnScreenPreference { defaults.macroPref("showOnScreen", ShowOnScreenPreference.allCases) }
static var titleTruncation: TitleTruncationPreference { defaults.macroPref("titleTruncation", TitleTruncationPreference.allCases) }
static var alignThumbnails: AlignThumbnailsPreference { defaults.macroPref("alignThumbnails", AlignThumbnailsPreference.allCases) }
static var updatePolicy: UpdatePolicyPreference { defaults.macroPref("updatePolicy", UpdatePolicyPreference.allCases) }
static var crashPolicy: CrashPolicyPreference { defaults.macroPref("crashPolicy", CrashPolicyPreference.allCases) }
static var appsToShow: [AppsToShowPreference] { ["appsToShow", "appsToShow2"].map { defaults.macroPref($0, AppsToShowPreference.allCases) } }
static var spacesToShow: [SpacesToShowPreference] { ["spacesToShow", "spacesToShow2"].map { defaults.macroPref($0, SpacesToShowPreference.allCases) } }
static var screensToShow: [ScreensToShowPreference] { ["screensToShow", "screensToShow2"].map { defaults.macroPref($0, ScreensToShowPreference.allCases) } }
@@ -198,8 +202,8 @@ enum AppsToShowPreference: String, CaseIterable, MacroPreference {
}
enum SpacesToShowPreference: String, CaseIterable, MacroPreference {
case all = "All spaces"
case active = "Active space"
case all = "0"
case active = "1"
var localizedString: LocalizedString {
switch self {
@@ -210,8 +214,8 @@ enum SpacesToShowPreference: String, CaseIterable, MacroPreference {
}
enum ScreensToShowPreference: String, CaseIterable, MacroPreference {
case all = "All screens"
case showingAltTab = "Screen showing AltTab"
case all = "0"
case showingAltTab = "1"
var localizedString: LocalizedString {
switch self {
@@ -222,9 +226,9 @@ enum ScreensToShowPreference: String, CaseIterable, MacroPreference {
}
enum ShowOnScreenPreference: String, CaseIterable, MacroPreference {
case active = "Active screen"
case includingMouse = "Screen including mouse"
case includingMenubar = "Screen including menu bar"
case active = "0"
case includingMouse = "1"
case includingMenubar = "2"
var localizedString: LocalizedString {
switch self {
@@ -236,9 +240,9 @@ enum ShowOnScreenPreference: String, CaseIterable, MacroPreference {
}
enum TitleTruncationPreference: String, CaseIterable, MacroPreference {
case end = "End"
case middle = "Middle"
case start = "Start"
case end = "0"
case middle = "1"
case start = "2"
var localizedString: LocalizedString {
switch self {
@@ -250,8 +254,8 @@ enum TitleTruncationPreference: String, CaseIterable, MacroPreference {
}
enum AlignThumbnailsPreference: String, CaseIterable, MacroPreference {
case left = "Left"
case center = "Center"
case left = "0"
case center = "1"
var localizedString: LocalizedString {
switch self {
@@ -262,13 +266,13 @@ enum AlignThumbnailsPreference: String, CaseIterable, MacroPreference {
}
enum ThemePreference: String, CaseIterable, MacroPreference {
case macOs = " macOS"
case windows10 = "❖ Windows 10"
case macOs = "0"
case windows10 = "1"
var localizedString: LocalizedString {
switch self {
case .macOs: return ThemePreference.macOs.rawValue
case .windows10: return ThemePreference.windows10.rawValue
case .macOs: return " macOS"
case .windows10: return "❖ Windows 10"
}
}
@@ -280,6 +284,34 @@ enum ThemePreference: String, CaseIterable, MacroPreference {
}
}
enum UpdatePolicyPreference: String, CaseIterable, MacroPreference {
case manual = "0"
case autoCheck = "1"
case autoInstall = "2"
var localizedString: LocalizedString {
switch self {
case .manual: return NSLocalizedString("Dont check for updates periodically", comment: "")
case .autoCheck: return NSLocalizedString("Check for updates periodically", comment: "")
case .autoInstall: return NSLocalizedString("Auto-install updates periodically", comment: "")
}
}
}
enum CrashPolicyPreference: String, CaseIterable, MacroPreference {
case never = "0"
case ask = "1"
case always = "2"
var localizedString: LocalizedString {
switch self {
case .never: return NSLocalizedString("Never send crash reports", comment: "")
case .ask: return NSLocalizedString("Ask whether to send crash reports", comment: "")
case .always: return NSLocalizedString("Always send crash reports", comment: "")
}
}
}
extension UserDefaults {
func string(_ key: String) -> String {
string(forKey: key)!
+16 -10
View File
@@ -3,24 +3,30 @@ import Sparkle
class UserDefaultsEvents: NSObject {
private static var policyObserver = UserDefaultsEvents()
private static var updatesTab: UpdatesTab!
static func observe(_ updatesTab: UpdatesTab) {
UserDefaultsEvents.updatesTab = updatesTab
static func observe() {
UserDefaults.standard.addObserver(policyObserver, forKeyPath: "SUAutomaticallyUpdate", options: [.initial, .new], context: nil)
UserDefaults.standard.addObserver(policyObserver, forKeyPath: "SUEnableAutomaticChecks", options: [.initial, .new], context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
guard !UserDefaultsEvents.updatesTab.policyLock else { return }
if SUUpdater.shared().automaticallyDownloadsUpdates {
UserDefaultsEvents.updatesTab.periodicallyInstall.state = .on
guard !PoliciesTab.policyLock else { return }
let buttons = PoliciesTab.updateButtons!
let id = buttonIdToUpdate()
if id == 2 {
// Sparkle UI "Automatically download and install updates in the future" doesn't activate periodical checks; we do it manually
SUUpdater.shared().automaticallyChecksForUpdates = true
} else if SUUpdater.shared().automaticallyChecksForUpdates {
UserDefaultsEvents.updatesTab.periodicallyCheck.state = .on
} else {
UserDefaultsEvents.updatesTab.dontPeriodicallyCheck.state = .on
}
buttons[id].state = .on
Preferences.set("updatePolicy", String(id))
}
private func buttonIdToUpdate() -> Int {
if SUUpdater.shared().automaticallyDownloadsUpdates {
return 2
} else if SUUpdater.shared().automaticallyChecksForUpdates {
return 1
}
return 0
}
}
+4 -2
View File
@@ -22,6 +22,7 @@ class App: NSApplication, NSApplicationDelegate {
var appIsBeingUsed = false
var shortcutsShouldBeDisabled = false
var shortcutIndex = 0
var appCenterDelegate: AppCenterCrash?
override init() {
super.init()
@@ -34,6 +35,7 @@ class App: NSApplication, NSApplicationDelegate {
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
appCenterDelegate = AppCenterCrash()
#if DEBUG
UserDefaults.standard.set(true, forKey: "NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints")
#endif
@@ -79,7 +81,7 @@ class App: NSApplication, NSApplicationDelegate {
let tabs = [
GeneralTab(),
AppearanceTab(),
UpdatesTab(),
PoliciesTab(),
BlacklistsTab(),
AboutTab(),
AcknowledgmentsTab(),
@@ -153,7 +155,7 @@ class App: NSApplication, NSApplicationDelegate {
}
@objc func checkForUpdatesNow(_ sender: NSMenuItem) {
UpdatesTab.checkForUpdatesNow(sender)
PoliciesTab.checkForUpdatesNow(sender)
}
@objc func showPreferencesPanel() {
+30 -14
View File
@@ -10,8 +10,8 @@ enum LabelPosition {
class LabelAndControl: NSObject {
static func makeLabelWithRecorder(_ labelText: String, _ rawName: String, _ shortcutString: String, _ clearable: Bool = true, labelPosition: LabelPosition = .leftWithSeparator) -> [NSView] {
let input = CustomRecorderControl(shortcutString, clearable)
let views = makeLabelWithProvidedControl(labelText, rawName, input, labelPosition: labelPosition, extraAction: GeneralTab.shortcutChangedCallback)
GeneralTab.shortcutChangedCallback(input)
let views = makeLabelWithProvidedControl(labelText, rawName, input, labelPosition: labelPosition, extraAction: { _ in GeneralTab.shortcutChangedCallback(input, rawName) })
GeneralTab.shortcutChangedCallback(input, rawName)
return views
}
@@ -26,7 +26,7 @@ class LabelAndControl: NSObject {
static func makeTextArea(_ nCharactersWide: CGFloat, _ nLinesHigh: Int, _ placeholder: String, _ rawName: String, extraAction: ActionClosure? = nil) -> [NSView] {
let textArea = TextArea(nCharactersWide, nLinesHigh, placeholder)
textArea.callback = {
controlWasChanged(textArea)
controlWasChanged(textArea, rawName, nil)
extraAction?(textArea)
}
textArea.identifier = NSUserInterfaceItemIdentifier(rawName)
@@ -46,6 +46,18 @@ class LabelAndControl: NSObject {
return popUp
}
static func makeRadioButtons(_ macroPreferences: [MacroPreference], _ rawName: String, extraAction: ActionClosure? = nil) -> [NSButton] {
var i = 0
return macroPreferences.map {
let button = NSButton(radioButtonWithTitle: $0.localizedString, target: nil, action: nil)
button.translatesAutoresizingMaskIntoConstraints = false
button.state = Int(Preferences.getString(rawName)!)! == i ? .on : .off
_ = setupControl(button, rawName, String(i), extraAction: extraAction)
i += 1
return button
}
}
static func makeLabelWithSlider(_ labelText: String, _ rawName: String, _ minValue: Double, _ maxValue: Double, _ numberOfTickMarks: Int, _ allowsTickMarkValuesOnly: Bool, _ unitText: String = "") -> [NSView] {
let value = Preferences.getString(rawName)!
let suffixText = MeasurementFormatter().string(from: Measurement(value: Double(value)!, unit: Unit(symbol: unitText)))
@@ -62,7 +74,7 @@ class LabelAndControl: NSObject {
}
static func makeLabelWithProvidedControl(_ labelText: String, _ rawName: String, _ control: NSControl, _ suffixText: String? = nil, _ suffixUrl: String? = nil, labelPosition: LabelPosition = .leftWithSeparator, extraAction: ActionClosure? = nil) -> [NSView] {
_ = setupControl(control, rawName, extraAction)
_ = setupControl(control, rawName, extraAction: extraAction)
if labelPosition == .right && control is NSButton {
return [control]
}
@@ -79,21 +91,21 @@ class LabelAndControl: NSObject {
return [label, control]
}
static func setupControl(_ control: NSControl, _ rawName: String, _ extraAction: ActionClosure? = nil) -> NSControl {
control.identifier = NSUserInterfaceItemIdentifier(rawName)
static func setupControl(_ control: NSControl, _ rawName: String, _ controlId: String? = nil, extraAction: ActionClosure? = nil) -> NSControl {
control.onAction = {
controlWasChanged($0)
controlWasChanged($0, rawName, controlId)
extraAction?($0)
}
return control
}
static func controlWasChanged(_ senderControl: NSControl) {
let newValue = LabelAndControl.getControlValue(senderControl)
LabelAndControl.updateControlExtras(senderControl, newValue)
Preferences.set(senderControl.identifier!.rawValue, newValue)
static func controlWasChanged(_ senderControl: NSControl, _ rawName: String, _ controlId: String?) {
if let newValue = LabelAndControl.getControlValue(senderControl, controlId) {
LabelAndControl.updateControlExtras(senderControl, newValue)
Preferences.set(rawName, newValue)
}
// some preferences require re-creating some components
if ["iconSize", "fontHeight", "theme", "titleTruncation"].contains(where: { (pref: String) -> Bool in pref == senderControl.identifier!.rawValue }) {
if ["iconSize", "fontHeight", "theme", "titleTruncation"].contains(where: { (pref: String) -> Bool in pref == rawName }) {
(App.shared as! App).resetPreferencesDependentComponents()
}
}
@@ -119,13 +131,17 @@ class LabelAndControl: NSObject {
return suffix
}
static func getControlValue(_ control: NSControl) -> String {
static func getControlValue(_ control: NSControl, _ controlId: String?) -> String? {
if control is NSPopUpButton {
return String((control as! NSPopUpButton).indexOfSelectedItem)
} else if control is NSSlider {
return String(format: "%.0f", control.doubleValue) // we are only interested in decimals of the provided double
} else if control is NSButton {
return String((control as! NSButton).state == NSButton.StateValue.on)
if let controlId = controlId {
return ((control as! NSButton).state == NSButton.StateValue.on) ? controlId : nil
} else {
return String((control as! NSButton).state == NSButton.StateValue.on)
}
} else {
return control.stringValue
}
@@ -130,25 +130,24 @@ class GeneralTab: NSViewController, PreferencePane {
App.shortcutMonitor.addAction(shortcutActions[controlId]!, forKeyEvent: type)
}
@objc static func shortcutChangedCallback(_ sender: NSControl) {
let controlId = sender.identifier!.rawValue
if controlId == "holdShortcut" {
addShortcut(.up, Shortcut(keyEquivalent: Preferences.holdShortcut)!, controlId)
@objc static func shortcutChangedCallback(_ sender: NSControl, _ rawName: String) {
if rawName == "holdShortcut" {
addShortcut(.up, Shortcut(keyEquivalent: Preferences.holdShortcut)!, rawName)
shortcutsDependentOnHoldShortcut.forEach {
if $0.identifier!.rawValue == "arrowKeysEnabled" {
GeneralTab.arrowKeysEnabledCallback($0)
} else {
GeneralTab.shortcutChangedCallback($0)
GeneralTab.shortcutChangedCallback($0, rawName)
}
}
} else {
// remove the holdShortcut character in case they also use it in the other shortcuts
let newValue = Preferences.holdShortcut.reduce((sender as! RecorderControl).stringValue, { $0.replacingOccurrences(of: String($1), with: "") })
if newValue.isEmpty {
removeShortcutIfExists(controlId, .down)
removeShortcutIfExists(rawName, .down)
return
}
addShortcut(.down, Shortcut(keyEquivalent: Preferences.holdShortcut + newValue)!, controlId)
addShortcut(.down, Shortcut(keyEquivalent: Preferences.holdShortcut + newValue)!, rawName)
}
}
@@ -0,0 +1,47 @@
import Cocoa
import Sparkle
import Preferences
class PoliciesTab: NSViewController, PreferencePane {
let preferencePaneIdentifier = PreferencePane.Identifier("Policies")
let preferencePaneTitle = NSLocalizedString("Policies", comment: "")
let toolbarItemIcon = NSImage(named: NSImage.refreshTemplateName)!
static var updateButtons: [NSButton]!
static var crashButtons: [NSButton]!
// this helps prevent double-dipping (i.e. user updates the UI > changes the preference > updates the UI)
static var policyLock = false
override func loadView() {
let updateLabel = LabelAndControl.makeLabel(NSLocalizedString("Updates policy:", comment: ""))
PoliciesTab.updateButtons = LabelAndControl.makeRadioButtons(UpdatePolicyPreference.allCases, "updatePolicy", extraAction: { _ in
PoliciesTab.policyLock = true
let policy = Preferences.updatePolicy
SUUpdater.shared().automaticallyDownloadsUpdates = policy == .autoInstall
SUUpdater.shared().automaticallyChecksForUpdates = policy == .autoInstall || policy == .autoCheck
PoliciesTab.policyLock = false
})
let updateOptions = StackView(PoliciesTab.updateButtons, .vertical)
updateOptions.spacing = GridView.interPadding / 2
let checkForUpdates = NSButton(title: NSLocalizedString("Check for updates now…", comment: ""), target: nil, action: #selector(PoliciesTab.checkForUpdatesNow))
let crashLabel = LabelAndControl.makeLabel(NSLocalizedString("Crash reports policy:", comment: ""))
PoliciesTab.crashButtons = LabelAndControl.makeRadioButtons(CrashPolicyPreference.allCases, "crashPolicy")
let crashOptions = StackView(PoliciesTab.crashButtons, .vertical)
let grid = GridView([
[updateLabel, updateOptions],
[NSView(), checkForUpdates],
[crashLabel, crashOptions],
])
grid.column(at: 0).xPlacement = .trailing
grid.row(at: 2).topPadding = GridView.interPadding * 1.5
grid.fit()
view = grid
UserDefaultsEvents.observe()
}
@objc static func checkForUpdatesNow(_ sender: Any) {
SUUpdater.shared().checkForUpdates(sender)
}
}
@@ -1,53 +0,0 @@
import Cocoa
import Sparkle
import Preferences
class UpdatesTab: NSViewController, PreferencePane {
let preferencePaneIdentifier = PreferencePane.Identifier("Updates")
let preferencePaneTitle = NSLocalizedString("Updates", comment: "")
let toolbarItemIcon = NSImage(named: NSImage.refreshTemplateName)!
var dontPeriodicallyCheck: NSButton!
var periodicallyCheck: NSButton!
var periodicallyInstall: NSButton!
var checkForUpdates: NSButton!
// this helps prevent double-dipping (i.e. user updates the UI > changes the preference > updates the UI)
var policyLock = false
override func loadView() {
dontPeriodicallyCheck = NSButton(radioButtonWithTitle: NSLocalizedString("Dont check for updates periodically", comment: ""), target: self, action: #selector(updatePolicyCallback))
dontPeriodicallyCheck.fit()
periodicallyCheck = NSButton(radioButtonWithTitle: NSLocalizedString("Check for updates periodically", comment: ""), target: self, action: #selector(updatePolicyCallback))
periodicallyCheck.fit()
periodicallyInstall = NSButton(radioButtonWithTitle: NSLocalizedString("Auto-install updates periodically", comment: ""), target: self, action: #selector(updatePolicyCallback))
periodicallyInstall.fit()
let policyLabel = NSTextField(wrappingLabelWithString: NSLocalizedString("Updates policy:", comment: ""))
policyLabel.isSelectable = false
let policies = StackView([dontPeriodicallyCheck, periodicallyCheck, periodicallyInstall], .vertical)
policies.spacing = GridView.interPadding / 2
checkForUpdates = NSButton(title: NSLocalizedString("Check for updates now…", comment: ""), target: nil, action: #selector(UpdatesTab.checkForUpdatesNow))
let grid = GridView([
[policyLabel, policies],
[checkForUpdates]
])
grid.cell(atColumnIndex: 0, rowIndex: 0).xPlacement = .trailing
let row1 = grid.row(at: 1)
row1.mergeCells(in: NSRange(location: 0, length: 2))
row1.topPadding = GridView.interPadding
row1.cell(at: 0).xPlacement = .center
grid.fit()
view = grid
UserDefaultsEvents.observe(self)
}
@objc static func checkForUpdatesNow(_ sender: Any) {
SUUpdater.shared().checkForUpdates(sender)
}
@objc func updatePolicyCallback() {
policyLock = true
SUUpdater.shared().automaticallyDownloadsUpdates = periodicallyInstall.state == .on
SUUpdater.shared().automaticallyChecksForUpdates = periodicallyInstall.state == .on || periodicallyCheck.state == .on
policyLock = false
}
}