diff --git a/apidoc/Titanium/UI/ImageView.yml b/apidoc/Titanium/UI/ImageView.yml index 462baa48608..f658608e7da 100644 --- a/apidoc/Titanium/UI/ImageView.yml +++ b/apidoc/Titanium/UI/ImageView.yml @@ -70,6 +70,26 @@ methods: platforms: [android, iphone, ipad, macos] returns: type: Titanium.Blob + + - name: addSymbolEffect + summary: Adds a symbol effect to the image view with specified options, animation, and callback. + platforms: [iphone, ipad, macos] + since: "12.4.0" + osver: { ios: { min: "17.0" } } + parameters: + - name: symbolEffect + summary: The symbol effect to add. One of `pulse`, `bounce`, `appear`, `disappear`, `variableColor` or `scale`. + type: String + - name: options + summary: The options for the symbol effect. One of `repeating`, `nonRepeating`, `repeatCount` or `speed`. + type: String + - name: animated + summary: A Boolean value that indicates whether to animate the addition of a `scale`, `appear`, or `disappear` effect. + type: Boolean + default: false + - name: callback + summary: A callback the system calls after the effect’s addition is complete. + type: Callback events: - name: change diff --git a/iphone/Classes/TiSymbolEffectManager.h b/iphone/Classes/TiSymbolEffectManager.h new file mode 100644 index 00000000000..a22d19f829f --- /dev/null +++ b/iphone/Classes/TiSymbolEffectManager.h @@ -0,0 +1,23 @@ +/** + * Titanium SDK + * Copyright TiDev, Inc. 04/07/2022-Present. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +API_AVAILABLE(ios(17)) +@interface TiSymbolEffectManager : NSObject + +- (instancetype)initWithConfiguration:(NSDictionary *)configuration; + +@property (nonatomic, strong) NSDictionary *configuration; +@property (nonatomic, strong) NSSymbolEffect *symbolEffect; +@property (nonatomic, strong) NSSymbolEffectOptions *symbolEffectOptions; + +@end + +NS_ASSUME_NONNULL_END diff --git a/iphone/Classes/TiSymbolEffectManager.m b/iphone/Classes/TiSymbolEffectManager.m new file mode 100644 index 00000000000..c898f18cd36 --- /dev/null +++ b/iphone/Classes/TiSymbolEffectManager.m @@ -0,0 +1,59 @@ +/** + * Titanium SDK + * Copyright TiDev, Inc. 04/07/2022-Present. All Rights Reserved. + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ + +#import "TiSymbolEffectManager.h" +#import + +@implementation TiSymbolEffectManager + +- (instancetype)initWithConfiguration:(NSDictionary *)configuration +{ + if (self = [self init]) { + self.configuration = configuration; + } + return self; +} + +- (NSSymbolEffect *)symbolEffect +{ + NSString *symbolEffectString = [self.configuration valueForKey:@"symbolEffect"]; + + if ([symbolEffectString isEqualToString:@"pulse"]) { + return NSSymbolPulseEffect.effect; + } else if ([symbolEffectString isEqualToString:@"bounce"]) { + return NSSymbolBounceEffect.effect; + } else if ([symbolEffectString isEqualToString:@"appear"]) { + return NSSymbolAppearEffect.effect; + } else if ([symbolEffectString isEqualToString:@"disappear"]) { + return NSSymbolDisappearEffect.effect; + } else if ([symbolEffectString isEqualToString:@"variableColor"]) { + return NSSymbolVariableColorEffect.effect; + } else if ([symbolEffectString isEqualToString:@"scale"]) { + return NSSymbolScaleEffect.effect; + } + + @throw [NSException exceptionWithName:@"io.tidev.titanium-sdk" reason:@"Invalid symbol effect provided" userInfo:nil]; +} + +- (NSSymbolEffectOptions *)symbolEffectOptions +{ + NSDictionary *symbolEffectOptions = [self.configuration valueForKey:@"options"]; + + if ([TiUtils boolValue:@"repeating" properties:symbolEffectOptions def:NO]) { + return [NSSymbolEffectOptions optionsWithRepeating]; + } else if ([TiUtils boolValue:@"nonRepeating" properties:symbolEffectOptions def:NO]) { + return [NSSymbolEffectOptions optionsWithNonRepeating]; + } else if ([TiUtils intValue:@"repeatCount" properties:symbolEffectOptions def:0] > 0) { + return [NSSymbolEffectOptions optionsWithRepeatCount:[TiUtils intValue:@"repeatCount" properties:symbolEffectOptions def:1]]; + } else if ([TiUtils doubleValue:@"speed" properties:symbolEffectOptions def:0] > 0) { + return [NSSymbolEffectOptions optionsWithSpeed:[TiUtils doubleValue:@"speed" properties:symbolEffectOptions def:1.0]]; + } + + return [NSSymbolEffectOptions options]; +} + +@end diff --git a/iphone/Classes/TiUIImageView.h b/iphone/Classes/TiUIImageView.h index 005232bce53..5c1aa2c4cf1 100644 --- a/iphone/Classes/TiUIImageView.h +++ b/iphone/Classes/TiUIImageView.h @@ -45,6 +45,7 @@ - (void)resume; - (void)setImage_:(id)arg; +- (void)addSymbolEffect:(NSDictionary *)args; @end diff --git a/iphone/Classes/TiUIImageView.m b/iphone/Classes/TiUIImageView.m index 6dd07fb816f..81b1b4c832a 100644 --- a/iphone/Classes/TiUIImageView.m +++ b/iphone/Classes/TiUIImageView.m @@ -7,6 +7,7 @@ #ifdef USE_TI_UIIMAGEVIEW #import "TiUIImageView.h" +#import "TiSymbolEffectManager.h" #import "TiUIImageViewProxy.h" #import #import @@ -685,6 +686,27 @@ - (void)setTintColor_:(id)value [imageView setTintColor:value ? [[TiUtils colorValue:value] color] : nil]; } +- (void)addSymbolEffect:(NSDictionary *)args +{ + BOOL animated = [TiUtils boolValue:@"animated" properties:args def:NO]; + KrollCallback *callback = [args valueForKey:@"callback"]; + + if (@available(iOS 17.0, *)) { + TiSymbolEffectManager *symbolEffectManager = [[TiSymbolEffectManager alloc] initWithConfiguration:args]; + + [imageView addSymbolEffect:symbolEffectManager.symbolEffect + options:symbolEffectManager.symbolEffectOptions + animated:animated + completion:^(UISymbolEffectCompletionContext *_Nonnull context) { + if (callback != nil) { + [callback call:@[ @{@"finished" : @(context.isFinished)} ] thisObject:self.proxy]; + } + }]; + } else { + NSLog(@"[ERROR] The \"addSymbolEffect\" API is only available on iOS 17+"); + } +} + - (void)setImage_:(id)arg { id currentImage = [self.proxy valueForUndefinedKey:@"image"]; diff --git a/iphone/Classes/TiUIImageViewProxy.m b/iphone/Classes/TiUIImageViewProxy.m index bfa1a34d5f0..d42040d075b 100644 --- a/iphone/Classes/TiUIImageViewProxy.m +++ b/iphone/Classes/TiUIImageViewProxy.m @@ -62,6 +62,14 @@ - (void)_configure [self replaceValue:NUMFLOAT(DEFAULT_IMAGEVIEW_INTERVAL) forKey:@"duration" notification:NO]; } +- (void)addSymbolEffect:(id)args +{ + ENSURE_SINGLE_ARG(args, NSDictionary); + + TiUIImageView *iv = (TiUIImageView *)[self view]; + [iv addSymbolEffect:args]; +} + - (void)start:(id)args { TiThreadPerformOnMainThread( diff --git a/iphone/iphone/Titanium.xcodeproj/project.pbxproj b/iphone/iphone/Titanium.xcodeproj/project.pbxproj index a00c3e2c5c4..5a110b83e4a 100644 --- a/iphone/iphone/Titanium.xcodeproj/project.pbxproj +++ b/iphone/iphone/Titanium.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -160,6 +160,7 @@ 3A0E54371BE811CD003EE654 /* TiUIiOSMenuPopupProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A0E54361BE811CD003EE654 /* TiUIiOSMenuPopupProxy.m */; }; 3A1E40511BEAC73D00943233 /* TiUIiOSMenuPopup.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1E40501BEAC73D00943233 /* TiUIiOSMenuPopup.m */; }; 3A275F3E1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A275F3D1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.m */; }; + 3A320F992B6EDC7600009E90 /* TiSymbolEffectManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A320F982B6EDC7600009E90 /* TiSymbolEffectManager.m */; }; 3A38F30424D6EBBD00CC6EFB /* TiUtils+Addons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A38F30324D6EBBD00CC6EFB /* TiUtils+Addons.swift */; }; 3A3BBAF51D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A3BBAF41D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.m */; }; 3A527EB327E0F77700A470D6 /* TiUITableViewScrollPositionProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A527EB227E0F77700A470D6 /* TiUITableViewScrollPositionProxy.m */; }; @@ -608,6 +609,8 @@ 3A1E40501BEAC73D00943233 /* TiUIiOSMenuPopup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIiOSMenuPopup.m; sourceTree = ""; }; 3A275F3C1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiUIActivityIndicatorStyleProxy.h; sourceTree = ""; }; 3A275F3D1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIActivityIndicatorStyleProxy.m; sourceTree = ""; }; + 3A320F972B6EDC7600009E90 /* TiSymbolEffectManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TiSymbolEffectManager.h; sourceTree = ""; }; + 3A320F982B6EDC7600009E90 /* TiSymbolEffectManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TiSymbolEffectManager.m; sourceTree = ""; }; 3A38F30324D6EBBD00CC6EFB /* TiUtils+Addons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TiUtils+Addons.swift"; sourceTree = ""; }; 3A3BBAF31D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiAppiOSUserNotificationCenterProxy.h; sourceTree = ""; }; 3A3BBAF41D3E2F0F008450DF /* TiAppiOSUserNotificationCenterProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiAppiOSUserNotificationCenterProxy.m; sourceTree = ""; }; @@ -1240,6 +1243,8 @@ 24C012881140D30B00A94CE2 /* TiUIMaskedImageProxy.m */, 24C0128D1140D31C00A94CE2 /* TiUIMaskedImage.h */, 24C0128E1140D31C00A94CE2 /* TiUIMaskedImage.m */, + 3A320F972B6EDC7600009E90 /* TiSymbolEffectManager.h */, + 3A320F982B6EDC7600009E90 /* TiSymbolEffectManager.m */, ); name = ImageView; sourceTree = ""; @@ -2152,6 +2157,7 @@ 3A275F3E1BA881B300EC4912 /* TiUIActivityIndicatorStyleProxy.m in Sources */, 24CA8B74111161FE0084E2DE /* TiUIWebViewProxy.m in Sources */, 3A1E40511BEAC73D00943233 /* TiUIiOSMenuPopup.m in Sources */, + 3A320F992B6EDC7600009E90 /* TiSymbolEffectManager.m in Sources */, 84A0100417FC8D3500D4BF94 /* TiGravityBehavior.m in Sources */, 24CA8B79111161FE0084E2DE /* TiUITextFieldProxy.m in Sources */, 3A38F30424D6EBBD00CC6EFB /* TiUtils+Addons.swift in Sources */,