From 40808cd5ffed82abaeb7e7523100f901f336298f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans=20Kn=C3=B6chel?= Date: Tue, 25 Jun 2024 04:58:01 +0200 Subject: [PATCH 1/6] feat: add swipe actions support for Ti.UI.TableView (#14065) * feat: add swipe actions support for Ti.UI.TableView * fix: fix linting issue * feat: support both leading and trailing state * feat: support leading edit actions in list view as well --- apidoc/Titanium/UI/ListItem.yml | 29 +++++++++- apidoc/Titanium/UI/TableView.yml | 34 ++++++++++++ apidoc/Titanium/UI/TableViewRow.yml | 8 +++ iphone/Classes/TiUIListView.m | 86 +++++++++++++++-------------- iphone/Classes/TiUITableView.m | 67 ++++++++++++++++++++++ iphone/Classes/TiUIiOSProxy.h | 2 +- iphone/Classes/TiUIiOSProxy.m | 17 ++---- 7 files changed, 186 insertions(+), 57 deletions(-) diff --git a/apidoc/Titanium/UI/ListItem.yml b/apidoc/Titanium/UI/ListItem.yml index 30065848130..d29225625cb 100644 --- a/apidoc/Titanium/UI/ListItem.yml +++ b/apidoc/Titanium/UI/ListItem.yml @@ -674,12 +674,27 @@ properties: --- name: RowActionType -summary: Represents the custom edit action for a ListItem. +summary: Represents the custom edit action for a ListItem or TableViewRow. description: | - By default when a listItem has [canEdit](Titanium.UI.ListItem.canEdit) set to true, a left swipe on the the row presens the 'Delete' button. + Edit actions can be used to add contextual buttons to your list items / table view rows. The configuration of + this API is the same for list items (if you use ) and table view rows (if you use . + description: | + Do not rely on the `source` property to determine which item fired the event. Use the + `row` and `section`, or the `index` to determine the table row that generated + the event. + + Note that the `index` property of this event correspond to the list view state + before the user action. + platforms: [iphone, ipad, macos] + since: 12.4.0 + properties: + - name: action + summary: The [title](RowActionType.title) as defined in the row action object. + type: String + + - name: identifier + summary: | + The [identifier](RowActionType. identifier) of the row action. Only included in the event + if previously defined. + type: String + + - name: row + summary: The row that fired this event. + type: [Titanium.UI.TableViewRow, Dictionary] + + - name: section + summary: The section that fired this event. + type: Titanium.UI.TableViewSection + + - name: index + summary: The index of the row that fired this event. + type: Number + methods: - name: appendRow summary: Appends a single row or an array of rows to the end of the table. diff --git a/apidoc/Titanium/UI/TableViewRow.yml b/apidoc/Titanium/UI/TableViewRow.yml index a5fb76598bc..a5e511827b9 100644 --- a/apidoc/Titanium/UI/TableViewRow.yml +++ b/apidoc/Titanium/UI/TableViewRow.yml @@ -226,6 +226,14 @@ properties: platforms: [android, iphone, ipad, macos] since: {android: "9.3.0", iphone: "3.2.0", ipad: "3.2.0", macos: "9.2.0"} + - name: editActions + summary: Specifies custom action items to be shown when when a list item is edited. + description: | + For more information see the "Editing Support" section of . + type: Array + since: 12.4.0 + platforms: [iphone, ipad, macos] + - name: filterAlwaysInclude summary: | This row will always be visible when you filter your content. diff --git a/iphone/Classes/TiUIListView.m b/iphone/Classes/TiUIListView.m index f1ca5250794..ae821bb0393 100644 --- a/iphone/Classes/TiUIListView.m +++ b/iphone/Classes/TiUIListView.m @@ -1146,23 +1146,49 @@ - (BOOL)tableView:(UITableView *)tableView canHandleDropSession:(id *editActions = [editActionProxies filteredArrayUsingPredicate:predicate]; + NSMutableArray *nativeEditActions = [NSMutableArray arrayWithCapacity:editActions.count]; + + if (IS_NULL_OR_NIL(editActions) || editActions.count == 0) { + return nil; + } - for (id prop in propArray) { - ENSURE_DICT(prop); + for (id prop in editActions) { NSString *title = [TiUtils stringValue:@"title" properties:prop]; NSString *identifier = [TiUtils stringValue:@"identifier" properties:prop]; - int actionStyle = [TiUtils intValue:@"style" properties:prop def:UITableViewRowActionStyleDefault]; + UIContextualActionStyle style = [TiUtils intValue:@"style" properties:prop def:UIContextualActionStyleNormal]; TiColor *color = [TiUtils colorValue:@"color" properties:prop]; id image = [prop objectForKey:@"image"]; - UITableViewRowAction *theAction = [UITableViewRowAction rowActionWithStyle:actionStyle + UIContextualAction *action = [UIContextualAction contextualActionWithStyle:style title:title - handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) { + handler:^(UIContextualAction *_Nonnull action, __kindof UIView *_Nonnull sourceView, void (^_Nonnull completionHandler)(BOOL)) { + completionHandler(YES); NSString *eventName = @"editaction"; NSIndexPath *realIndexPath = [self pathForSearchPath:indexPath]; @@ -1192,27 +1218,22 @@ - (NSArray *)editActionsFromValue:(id)value } // Hide editActions after selection - [[self tableView] setEditing:NO]; + // [[self tableView] setEditing:NO]; }]; - if (color) { - theAction.backgroundColor = [color color]; + + if (color != nil) { + action.backgroundColor = color.color; } - if (image) { + + if (image != nil) { NSURL *url = [TiUtils toURL:image proxy:(TiProxy *)self.proxy]; - UIImage *nativeImage = [[ImageLoader sharedLoader] loadImmediateImage:url]; - if (color) { - nativeImage = [self generateImage:nativeImage withBackgroundColor:[color color]]; - } - theAction.backgroundColor = [UIColor colorWithPatternImage:nativeImage]; - } - if (!returnArray) { - returnArray = [NSMutableArray arrayWithObject:theAction]; - } else { - [returnArray addObject:theAction]; + action.image = [[ImageLoader sharedLoader] loadImmediateImage:url]; } + + [nativeEditActions addObject:action]; } - return returnArray; + return [UISwipeActionsConfiguration configurationWithActions:nativeEditActions]; } - (UIImage *)generateImage:(UIImage *)image withBackgroundColor:(UIColor *)bgColor @@ -1388,23 +1409,6 @@ - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleFo return UITableViewCellEditingStyleNone; } -- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSIndexPath *realIndexPath = [self pathForSearchPath:indexPath]; - - if (![self canEditRowAtIndexPath:realIndexPath]) { - return nil; - } - - id editValue = [self valueWithKey:@"editActions" atIndexPath:realIndexPath]; - - if (IS_NULL_OR_NIL(editValue)) { - return nil; - } - - return [self editActionsFromValue:editValue]; -} - - (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath { NSIndexPath *realIndexPath = [self pathForSearchPath:indexPath]; diff --git a/iphone/Classes/TiUITableView.m b/iphone/Classes/TiUITableView.m index 31fba206cbb..bb417a072b6 100644 --- a/iphone/Classes/TiUITableView.m +++ b/iphone/Classes/TiUITableView.m @@ -2338,6 +2338,73 @@ - (void)tableViewDidEndMultipleSelectionInteraction:(UITableView *)tableView [self fireRowsSelectedEvent]; } +- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath +{ + return [self swipeConfigurationForState:@"leading" withIndexPath:indexPath isDefault:NO]; +} + +- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath +{ + return [self swipeConfigurationForState:@"trailing" withIndexPath:indexPath isDefault:YES]; +} + +- (UISwipeActionsConfiguration *)swipeConfigurationForState:(NSString *)state withIndexPath:(NSIndexPath *)indexPath isDefault:(BOOL)isDefault +{ + TiUITableViewRowProxy *row = [self rowForIndexPath:indexPath]; + TiUITableViewSectionProxy *section = [self sectionForIndex:indexPath.section]; + + BOOL canEdit = [TiUtils boolValue:[row valueForKey:@"editable"] def:NO]; + + if (!canEdit) { + return nil; + } + + NSArray *editActionProxies = (NSArray *)[row valueForKey:@"editActions"]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:isDefault ? @"state == nil OR state == %@" : @"state == %@", state]; + NSArray *editActions = [editActionProxies filteredArrayUsingPredicate:predicate]; + NSMutableArray *nativeEditActions = [NSMutableArray arrayWithCapacity:editActions.count]; + + if (IS_NULL_OR_NIL(editActions) || editActions.count == 0) { + return nil; + } + + for (id prop in editActions) { + NSString *title = [TiUtils stringValue:@"title" properties:prop]; + NSString *identifier = [TiUtils stringValue:@"identifier" properties:prop]; + UIContextualActionStyle style = [TiUtils intValue:@"style" properties:prop def:UIContextualActionStyleNormal]; + TiColor *color = [TiUtils colorValue:@"color" properties:prop]; + id image = [prop objectForKey:@"image"]; + + UIContextualAction *action = [UIContextualAction contextualActionWithStyle:style + title:title + handler:^(UIContextualAction *_Nonnull action, __kindof UIView *_Nonnull sourceView, void (^_Nonnull completionHandler)(BOOL)) { + completionHandler(YES); + + [[self proxy] fireEvent:@"editaction" + withObject:@{ + @"index" : @(indexPath.row), + @"row" : row, + @"section" : section, + @"action" : NULL_IF_NIL(action.title), + @"identifier" : NULL_IF_NIL(identifier) + }]; + }]; + + if (color != nil) { + action.backgroundColor = color.color; + } + + if (image != nil) { + NSURL *url = [TiUtils toURL:image proxy:(TiProxy *)self.proxy]; + action.image = [[ImageLoader sharedLoader] loadImmediateImage:url]; + } + + [nativeEditActions addObject:action]; + } + + return [UISwipeActionsConfiguration configurationWithActions:nativeEditActions]; +} + #pragma mark Collation - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)ourTableView diff --git a/iphone/Classes/TiUIiOSProxy.h b/iphone/Classes/TiUIiOSProxy.h index 0350a3dea11..ef246632734 100644 --- a/iphone/Classes/TiUIiOSProxy.h +++ b/iphone/Classes/TiUIiOSProxy.h @@ -67,7 +67,7 @@ @property (nonatomic, readonly) NSNumber *CLIP_MODE_ENABLED; @property (nonatomic, readonly) NSNumber *CLIP_MODE_DISABLED; -#ifdef USE_TI_UILISTVIEW +#if defined(USE_TI_UILISTVIEW) || defined(USE_TI_UITABLEVIEW) @property (nonatomic, readonly) NSNumber *ROW_ACTION_STYLE_DEFAULT; @property (nonatomic, readonly) NSNumber *ROW_ACTION_STYLE_DESTRUCTIVE; @property (nonatomic, readonly) NSNumber *ROW_ACTION_STYLE_NORMAL; diff --git a/iphone/Classes/TiUIiOSProxy.m b/iphone/Classes/TiUIiOSProxy.m index ceb94efd132..e06f49302e4 100644 --- a/iphone/Classes/TiUIiOSProxy.m +++ b/iphone/Classes/TiUIiOSProxy.m @@ -154,19 +154,10 @@ - (NSNumber *)CLIP_MODE_DISABLED return NUMINT(-1); } -#ifdef USE_TI_UILISTVIEW -- (NSNumber *)ROW_ACTION_STYLE_DEFAULT -{ - return @(UIContextualActionStyleNormal); -} -- (NSNumber *)ROW_ACTION_STYLE_DESTRUCTIVE -{ - return @(UIContextualActionStyleDestructive); -} -- (NSNumber *)ROW_ACTION_STYLE_NORMAL -{ - return @(UIContextualActionStyleNormal); -} +#if defined(USE_TI_UILISTVIEW) || defined(USE_TI_UITABLEVIEW) +MAKE_SYSTEM_PROP(ROW_ACTION_STYLE_DEFAULT, UIContextualActionStyleNormal); +MAKE_SYSTEM_PROP(ROW_ACTION_STYLE_DESTRUCTIVE, UIContextualActionStyleDestructive); +MAKE_SYSTEM_PROP(ROW_ACTION_STYLE_NORMAL, UIContextualActionStyleNormal); #endif #ifdef USE_TI_UIPICKER From 9f85623fa45dda478124a9b52794c77eb60bd5ac Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Tue, 25 Jun 2024 04:58:37 +0200 Subject: [PATCH 2/6] docs: add iOS WebViewConfiguration link (#14072) --- .../Titanium/UI/iOS/WebViewConfiguration.yml | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/apidoc/Titanium/UI/iOS/WebViewConfiguration.yml b/apidoc/Titanium/UI/iOS/WebViewConfiguration.yml index e7c2d29788f..7bf7efc2eb2 100644 --- a/apidoc/Titanium/UI/iOS/WebViewConfiguration.yml +++ b/apidoc/Titanium/UI/iOS/WebViewConfiguration.yml @@ -3,10 +3,12 @@ name: Titanium.UI.iOS.WebViewConfiguration summary: A collection of properties used to initialize a web view. description: | Use the method to create and use as a parameter of . - Using this you can determine how soon a webpage is rendered, how media playback is handled, the granularity of items that the + Using this you can determine how soon a webpage is rendered, how media playback is handled, the granularity of items that the user can select, and many other options. This property can only be set when creating the webview and will be ignored when set afterwards. See the example section "Usage of WebViewConfiguration with WebView in iOS". + Information on additional available preferences can be derived from the original WebKit sources: + [WKPreferences.mm](https://github.com/WebKit/webkit/blob/main/Source/WebKit/UIProcess/API/Cocoa/WKPreferences.mm) extends: Titanium.Proxy platforms: [iphone, ipad, macos] since: {iphone: "8.0.0", ipad: "8.0.0", macos: "9.2.0"} @@ -30,7 +32,7 @@ properties: - name: suppressesIncrementalRendering summary: | - A Boolean value indicating whether the web view suppresses content rendering until it is fully + A Boolean value indicating whether the web view suppresses content rendering until it is fully loaded into memory. type: Boolean default: false @@ -39,8 +41,8 @@ properties: summary: | A Boolean value indicating whether HTML5 videos play inline or use the native full-screen controller. description: | - You must set this property to play inline video. Set this property to true to play videos inline. - Set this property to false to use the native full-screen controller. When adding a video element + You must set this property to play inline video. Set this property to true to play videos inline. + Set this property to false to use the native full-screen controller. When adding a video element to a HTML document on the iPhone, you must also include the playsinline attribute. The default value for iPhone is false and the default value for iPad is true. type: Boolean @@ -59,7 +61,7 @@ properties: - name: processPool summary: The process pool from which to obtain the Web Content process of view. description: | - When a web view is initialized, either a new web content process is created for it from the + When a web view is initialized, either a new web content process is created for it from the specified pool or an existing process in that pool is used. type: Titanium.UI.iOS.WebViewProcessPool platforms: [iphone, ipad, macos] @@ -77,7 +79,7 @@ properties: - name: javaScriptEnabled summary: A Boolean value indicating whether JavaScript is enabled. description: | - Setting this property to false disables JavaScripts that are loaded or executed by the web page. + Setting this property to false disables JavaScripts that are loaded or executed by the web page. This setting does not affect user scripts. type: Boolean default: true @@ -93,11 +95,11 @@ examples: Creates a configuration object and use it as property of webview. ``` js - var config = Ti.UI.iOS.createWebViewConfiguration({ + var config = Ti.UI.iOS.createWebViewConfiguration({ allowsPictureInPictureMediaPlayback: true, - preferences: { + preferences: { minimumFontSize : 20, - }, + }, }); var webView = Ti.UI.createWebView({ From ada10bb065851d4b8c55e1342b2a888a776ad381 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Tue, 25 Jun 2024 05:00:32 +0200 Subject: [PATCH 3/6] chore(android): prepare SDK for Android 34 (#13940) * chore(android): target API 34 * stay on target 33 --- android/gradle.properties | 2 +- .../ti/modules/titanium/android/AndroidModule.java | 9 ++++++++- .../ti/modules/titanium/network/TiNetworkListener.java | 10 +++++++++- .../java/org/appcelerator/titanium/TiApplication.java | 9 ++++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index e5e7569a7a5..a5678e41a60 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -14,4 +14,4 @@ android.useAndroidX=true android.enableJetifier=false # remove if com.android.tools.build:gradle can be raised in /android/build.gradle -android.suppressUnsupportedCompileSdk=33 +android.suppressUnsupportedCompileSdk=33,34 diff --git a/android/modules/android/src/java/ti/modules/titanium/android/AndroidModule.java b/android/modules/android/src/java/ti/modules/titanium/android/AndroidModule.java index 947cc59cde4..fdc5c89431a 100644 --- a/android/modules/android/src/java/ti/modules/titanium/android/AndroidModule.java +++ b/android/modules/android/src/java/ti/modules/titanium/android/AndroidModule.java @@ -756,7 +756,14 @@ public void registerBroadcastReceiver(BroadcastReceiverProxy receiverProxy, Obje filter.addAction(TiConvert.toString(action)); } - TiApplication.getInstance().registerReceiver(receiverProxy.getBroadcastReceiver(), filter); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU + && TiApplication.getInstance().getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.TIRAMISU) { + int receiverFlags = Context.RECEIVER_EXPORTED; + TiApplication.getInstance().registerReceiver( + receiverProxy.getBroadcastReceiver(), filter, receiverFlags); + } else { + TiApplication.getInstance().registerReceiver(receiverProxy.getBroadcastReceiver(), filter); + } if (this.registeredBroadcastReceiverProxyList.contains(receiverProxy) == false) { this.registeredBroadcastReceiverProxyList.add(receiverProxy); } diff --git a/android/modules/network/src/java/ti/modules/titanium/network/TiNetworkListener.java b/android/modules/network/src/java/ti/modules/titanium/network/TiNetworkListener.java index 9474800138d..88eec58c041 100644 --- a/android/modules/network/src/java/ti/modules/titanium/network/TiNetworkListener.java +++ b/android/modules/network/src/java/ti/modules/titanium/network/TiNetworkListener.java @@ -7,6 +7,7 @@ package ti.modules.titanium.network; import org.appcelerator.kroll.common.Log; +import org.appcelerator.titanium.TiApplication; import android.content.BroadcastReceiver; import android.content.Context; @@ -14,6 +15,7 @@ import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.NetworkInfo; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -110,7 +112,13 @@ public void attach(Context context) } else { throw new IllegalStateException("Context was not cleaned up from last release."); } - context.registerReceiver(receiver, connectivityIntentFilter); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU + && TiApplication.getInstance().getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.TIRAMISU) { + int receiverFlags = Context.RECEIVER_EXPORTED; + context.registerReceiver(receiver, connectivityIntentFilter, receiverFlags); + } else { + context.registerReceiver(receiver, connectivityIntentFilter); + } listening = true; } else { Log.w(TAG, "Connectivity listener is already attached"); diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java index eff4749d181..cbaef3950dd 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java +++ b/android/titanium/src/java/org/appcelerator/titanium/TiApplication.java @@ -14,6 +14,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; +import android.os.Build; import android.os.Looper; import android.os.SystemClock; import android.util.DisplayMetrics; @@ -961,7 +962,13 @@ public void onReceive(Context context, Intent intent) } }; - registerReceiver(localeReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU + && TiApplication.getInstance().getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.TIRAMISU) { + int receiverFlags = Context.RECEIVER_EXPORTED; + registerReceiver(localeReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED), receiverFlags); + } else { + registerReceiver(localeReceiver, new IntentFilter(Intent.ACTION_LOCALE_CHANGED)); + } } private void stopLocaleMonitor() From 07df6890e2a363f40e44757147287bf307e86808 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Tue, 25 Jun 2024 05:06:12 +0200 Subject: [PATCH 4/6] feat(android): track color of the Ti.UI.Switch (#14054) * feat(android): track color of the Ti.UI.Switch * docs * thumb colors * update * docs * doc update --- .../ti/modules/titanium/ui/SwitchProxy.java | 6 +- .../titanium/ui/widget/TiUISwitch.java | 68 ++++++++++++++++++- .../java/org/appcelerator/titanium/TiC.java | 3 + apidoc/Titanium/UI/Switch.yml | 32 +++++++-- 4 files changed, 101 insertions(+), 8 deletions(-) diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/SwitchProxy.java b/android/modules/ui/src/java/ti/modules/titanium/ui/SwitchProxy.java index a4389620c6a..3bdcac73f38 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/SwitchProxy.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/SwitchProxy.java @@ -23,7 +23,11 @@ TiC.PROPERTY_COLOR, TiC.PROPERTY_FONT, TiC.PROPERTY_TEXT_ALIGN, - TiC.PROPERTY_VERTICAL_ALIGN + TiC.PROPERTY_TINT_COLOR, + TiC.PROPERTY_ON_TINT_COLOR, + TiC.PROPERTY_VERTICAL_ALIGN, + TiC.PROPERTY_ON_THUMB_COLOR, + TiC.PROPERTY_THUMB_COLOR }) public class SwitchProxy extends TiViewProxy { diff --git a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUISwitch.java b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUISwitch.java index cd4f66f0482..da3bb4a1112 100644 --- a/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUISwitch.java +++ b/android/modules/ui/src/java/ti/modules/titanium/ui/widget/TiUISwitch.java @@ -7,13 +7,17 @@ package ti.modules.titanium.ui.widget; import android.app.Activity; +import android.content.res.ColorStateList; import android.view.View; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; + import androidx.appcompat.widget.AppCompatToggleButton; + import com.google.android.material.checkbox.MaterialCheckBox; import com.google.android.material.chip.Chip; import com.google.android.material.switchmaterial.SwitchMaterial; + import org.appcelerator.kroll.KrollDict; import org.appcelerator.kroll.KrollProxy; import org.appcelerator.kroll.common.Log; @@ -23,13 +27,14 @@ import org.appcelerator.titanium.util.TiConvert; import org.appcelerator.titanium.util.TiUIHelper; import org.appcelerator.titanium.view.TiUIView; + import ti.modules.titanium.ui.UIModule; public class TiUISwitch extends TiUIView implements OnCheckedChangeListener { private static final String TAG = "TiUISwitch"; - private View.OnLayoutChangeListener layoutListener; + private final View.OnLayoutChangeListener layoutListener; private boolean oldValue = false; public TiUISwitch(TiViewProxy proxy) @@ -37,7 +42,8 @@ public TiUISwitch(TiViewProxy proxy) super(proxy); Log.d(TAG, "Creating a switch", Log.DEBUG_MODE); - this.layoutListener = new View.OnLayoutChangeListener() { + this.layoutListener = new View.OnLayoutChangeListener() + { @Override public void onLayoutChange( View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) @@ -58,6 +64,62 @@ public void processProperties(KrollDict d) setStyle(TiConvert.toInt(d.get(TiC.PROPERTY_STYLE), UIModule.SWITCH_STYLE_SLIDER)); } + if (d.containsKeyAndNotNull(TiC.PROPERTY_THUMB_COLOR) + || d.containsKeyAndNotNull(TiC.PROPERTY_ON_THUMB_COLOR)) { + CompoundButton currentButton = (CompoundButton) getNativeView(); + if (currentButton instanceof SwitchMaterial) { + + int colActive = d.containsKeyAndNotNull(TiC.PROPERTY_ON_THUMB_COLOR) + ? TiConvert.toColor(d, TiC.PROPERTY_ON_THUMB_COLOR) + : TiConvert.toColor(d, TiC.PROPERTY_THUMB_COLOR); + int colNormal = d.containsKeyAndNotNull(TiC.PROPERTY_THUMB_COLOR) + ? TiConvert.toColor(d, TiC.PROPERTY_THUMB_COLOR) + : TiConvert.toColor(d, TiC.PROPERTY_ON_THUMB_COLOR); + + ColorStateList trackStates = new ColorStateList( + new int[][] { + new int[] { -android.R.attr.state_enabled }, + new int[] { android.R.attr.state_checked }, + new int[] {} + }, + new int[] { + colNormal, + colActive, + colNormal + } + ); + ((SwitchMaterial) currentButton).setThumbTintList(trackStates); + } + } + + if (d.containsKeyAndNotNull(TiC.PROPERTY_TINT_COLOR) + || d.containsKeyAndNotNull(TiC.PROPERTY_ON_TINT_COLOR)) { + CompoundButton currentButton = (CompoundButton) getNativeView(); + if (currentButton instanceof SwitchMaterial) { + + int colActive = d.containsKeyAndNotNull(TiC.PROPERTY_ON_TINT_COLOR) + ? TiConvert.toColor(d, TiC.PROPERTY_ON_TINT_COLOR) + : TiConvert.toColor(d, TiC.PROPERTY_TINT_COLOR); + int colNormal = d.containsKeyAndNotNull(TiC.PROPERTY_TINT_COLOR) + ? TiConvert.toColor(d, TiC.PROPERTY_TINT_COLOR) + : TiConvert.toColor(d, TiC.PROPERTY_ON_TINT_COLOR); + + ColorStateList trackStates = new ColorStateList( + new int[][] { + new int[] { -android.R.attr.state_enabled }, + new int[] { android.R.attr.state_checked }, + new int[] {} + }, + new int[] { + colNormal, + colActive, + colNormal + } + ); + ((SwitchMaterial) currentButton).setTrackTintList(trackStates); + } + } + if (d.containsKey(TiC.PROPERTY_VALUE)) { oldValue = TiConvert.toBoolean(d, TiC.PROPERTY_VALUE); } @@ -151,7 +213,7 @@ public void propertyChanged(String key, Object oldValue, Object newValue, KrollP } else { super.propertyChanged(key, oldValue, newValue, proxy); } - } + } @Override public void onCheckedChanged(CompoundButton btn, boolean value) diff --git a/android/titanium/src/java/org/appcelerator/titanium/TiC.java b/android/titanium/src/java/org/appcelerator/titanium/TiC.java index 58beebdde16..4f219b4c308 100644 --- a/android/titanium/src/java/org/appcelerator/titanium/TiC.java +++ b/android/titanium/src/java/org/appcelerator/titanium/TiC.java @@ -142,6 +142,8 @@ public class TiC public static final String EVENT_PROPERTY_TAB = "tab"; public static final String EVENT_PROPERTY_THUMB_OFFSET = "thumbOffset"; public static final String EVENT_PROPERTY_THUMB_SIZE = "thumbSize"; + public static final String PROPERTY_THUMB_COLOR = "thumbColor"; + public static final String PROPERTY_ON_THUMB_COLOR = "onThumbColor"; public static final String EVENT_PROPERTY_TYPE = "type"; public static final String EVENT_PROPERTY_VELOCITY = "velocity"; public static final String EVENT_PROPERTY_X = "x"; @@ -608,6 +610,7 @@ public class TiC public static final String PROPERTY_ON_RESTART = "onRestart"; public static final String PROPERTY_ON_PAUSE = "onPause"; public static final String PROPERTY_ON_STOP = "onStop"; + public static final String PROPERTY_ON_TINT_COLOR = "onTintColor"; public static final String PROPERTY_TLS_VERSION = "tlsVersion"; public static final String PROPERTY_ON_DESTROY = "onDestroy"; public static final String PROPERTY_ON_CREATE_WINDOW = "onCreateWindow"; diff --git a/apidoc/Titanium/UI/Switch.yml b/apidoc/Titanium/UI/Switch.yml index 326e54165f7..4ff5536acd5 100644 --- a/apidoc/Titanium/UI/Switch.yml +++ b/apidoc/Titanium/UI/Switch.yml @@ -118,17 +118,41 @@ properties: - name: tintColor summary: The color used to tint the outline of the switch when it is turned off. + description: | + The color used to tint the outline of the switch when it is turned off. + + Android: Track color of the Material Switch. type: [String, Titanium.UI.Color] default: undefined - platforms: [iphone, ipad, macos] - since: "3.3.0" + platforms: [android, iphone, ipad] + since: {android: 12.4.0, iphone: 3.3.0, ipad: 3.3.0} + + - name: onThumbColor + description: | + The color used to tint the thumb icon of the switch when it is turned on. + + Android: Active thumb color of the Material Switch. + type: [String, Titanium.UI.Color] + default: undefined + platforms: [android] + since: {android: 12.4.0} + + - name: thumbColor + description: | + The color used to tint the thumb icon of the switch when it is turned off. + + Android: Inactive thumb color of the Material Switch. + type: [String, Titanium.UI.Color] + default: undefined + platforms: [android] + since: {android: 12.4.0} - name: onTintColor summary: The color used to tint the appearance of the switch when it is turned on. type: [String, Titanium.UI.Color] default: undefined - platforms: [iphone, ipad, macos] - since: "3.3.0" + platforms: [android, iphone, ipad, macos] + since: {android: 12.4.0, iphone: 3.3.0, ipad: 3.3.0} - name: thumbTintColor summary: The color used to tint the appearance of the thumb. From ceda65eb73492c671b6dc74639dee072fa512439 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Tue, 25 Jun 2024 05:23:27 +0200 Subject: [PATCH 5/6] chore(android): new Android Studio settings xml (#14043) Co-authored-by: Chris Barber --- .../inspectionProfiles/Project_Default.xml | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/android/.idea/inspectionProfiles/Project_Default.xml b/android/.idea/inspectionProfiles/Project_Default.xml index 1eb788b1487..23c812cbcc9 100644 --- a/android/.idea/inspectionProfiles/Project_Default.xml +++ b/android/.idea/inspectionProfiles/Project_Default.xml @@ -10,7 +10,11 @@ - + + @@ -155,11 +159,21 @@ - - + + \ No newline at end of file From 420ccdceadff8658803e02bb6144e853c8767a20 Mon Sep 17 00:00:00 2001 From: Michael Gangolf Date: Tue, 25 Jun 2024 05:23:34 +0200 Subject: [PATCH 6/6] chore: fix webpack command name issue (#14067) --- cli/hooks/webpack.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cli/hooks/webpack.js b/cli/hooks/webpack.js index cd9c06a36a8..943e87c29d6 100644 --- a/cli/hooks/webpack.js +++ b/cli/hooks/webpack.js @@ -35,6 +35,9 @@ exports.init = (logger, config, cli) => { cli.on('cli:command-loaded', (hookData) => { const command = hookData.command; commandName = command.name; + if (typeof command.name === 'function') { + commandName = command.name(); + } }); cli.on('cli:post-validate', () => {