Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions ios/bar/BarMenuContainer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@protocol BarMenuContainer <NSObject>
- (void)updateMenu;
- (void)menuItemSelected:(NSString *)identifier;
- (BOOL)hasSelectedItem;
- (NSArray<NSString *> *)selectedItemIDs;
@end

NS_ASSUME_NONNULL_END
78 changes: 78 additions & 0 deletions ios/bar/BarPropHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#import <React/RCTConversions.h>

#include <string>
#include <vector>

static inline NSString * _Nullable ToolbarNSStringFromStringProp(const std::string &value)
{
if (value.empty()) {
return nil;
}

return RCTNSStringFromString(value);
}

static inline NSArray<NSString *> * _Nonnull ToolbarNSStringArrayFromStringArrayProp(
const std::vector<std::string> &value
)
{
if (value.empty()) {
return @[];
}

NSMutableArray<NSString *> *result = [NSMutableArray arrayWithCapacity:value.size()];
for (const auto &item : value) {
if (!item.empty()) {
[result addObject:RCTNSStringFromString(item)];
}
}

return result;
}

static inline std::vector<std::string> ToolbarStringVectorFromNSStringArray(NSArray<NSString *> * _Nonnull value)
{
std::vector<std::string> result;
result.reserve(value.count);

for (NSString *item in value) {
if (item.length == 0) {
continue;
}
result.emplace_back(item.UTF8String);
}

return result;
}

#define APPLY_STRING_PROP(target, oldProps, newProps, prop) \
if (oldProps.prop != newProps.prop) { \
target.prop = ToolbarNSStringFromStringProp(newProps.prop); \
}

#define APPLY_STRING_ARRAY_PROP(target, oldProps, newProps, prop) \
if (oldProps.prop != newProps.prop) { \
target.prop = ToolbarNSStringArrayFromStringArrayProp(newProps.prop); \
}

#define APPLY_BOOL_PROP(target, oldProps, newProps, prop) \
if (oldProps.prop != newProps.prop) { \
target.prop = newProps.prop; \
}

// Codegen non-optional doubles default to 0, so we use negative as a sentinel for "unset".
#define APPLY_OPTIONAL_DOUBLE_PROP(target, oldProps, newProps, prop) \
if (oldProps.prop != newProps.prop) { \
double value = newProps.prop; \
target.prop = value >= 0 ? @(value) : nil; \
}

#define APPLY_COLOR_PROP(target, oldProps, newProps, prop) \
if (oldProps.prop != newProps.prop) { \
target.prop = RCTUIColorFromSharedColor(newProps.prop); \
}

#define APPLY_NUMBER_PROP(target, oldProps, newProps, prop) \
if (oldProps.prop != newProps.prop) { \
target.prop = @(newProps.prop); \
}
41 changes: 41 additions & 0 deletions ios/bar/RNSBarItemView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#import <React/RCTViewComponentView.h>
#import <UIKit/UIKit.h>

@class RNSBarView;

NS_ASSUME_NONNULL_BEGIN

@interface RNSBarItemView : RCTViewComponentView

@property (nonatomic, weak, nullable) RNSBarView *barParent;
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) NSString *icon;
@property (nonatomic, copy, nullable) NSString *placement;
@property (nonatomic, copy, nullable) NSString *variant;
@property (nonatomic, strong, nullable) UIColor *tintColor;
@property (nonatomic, strong, nullable) NSNumber *width;
@property (nonatomic, assign) BOOL disabled;
@property (nonatomic, assign) BOOL selected;
@property (nonatomic, copy, nullable) NSString *identifier;
@property (nonatomic, assign) BOOL hidesSharedBackground;
@property (nonatomic, assign) BOOL hasSharesBackground;
@property (nonatomic, assign) BOOL sharesBackground;
@property (nonatomic, assign) BOOL hasBadge;
@property (nonatomic, strong, nullable) NSNumber *badgeCount;
@property (nonatomic, copy, nullable) NSString *badgeValue;
@property (nonatomic, strong, nullable) UIColor *badgeForegroundColor;
@property (nonatomic, strong, nullable) UIColor *badgeBackgroundColor;
@property (nonatomic, copy, nullable) NSString *badgeFontFamily;
@property (nonatomic, copy, nullable) NSString *badgeFontWeight;
@property (nonatomic, strong, nullable) NSNumber *badgeFontSize;
@property (nonatomic, copy, nullable) NSString *titleFontFamily;
@property (nonatomic, copy, nullable) NSString *titleFontWeight;
@property (nonatomic, strong, nullable) NSNumber *titleFontSize;
@property (nonatomic, strong, nullable) UIColor *titleColor;
@property (nonatomic, copy, nullable) NSString *testID;

- (void)emitPress;

@end

NS_ASSUME_NONNULL_END
99 changes: 99 additions & 0 deletions ios/bar/RNSBarItemView.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#import "RNSBarItemView.h"

#import <React/RCTConversions.h>

#import <react/renderer/components/RNSBarViewSpec/ComponentDescriptors.h>
#import <react/renderer/components/RNSBarViewSpec/EventEmitters.h>
#import <react/renderer/components/RNSBarViewSpec/Props.h>
#import <react/renderer/components/RNSBarViewSpec/RCTComponentViewHelpers.h>

#import "BarPropHelpers.h"
#import "RNSBarView.h"

using namespace facebook::react;

@interface RNSBarView (BarInternal)
- (void)updateBarItems;
- (void)updateBarItem:(RNSBarItemView *)itemView;
@end

@implementation RNSBarItemView

+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider<RNSBarItemComponentDescriptor>();
}

- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
static const auto defaultProps = std::make_shared<const RNSBarItemProps>();
_props = defaultProps;

self.hidden = YES;
self.userInteractionEnabled = NO;
}

return self;
}

- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
const auto &oldItemProps = *std::static_pointer_cast<RNSBarItemProps const>(_props);
const auto &newItemProps = *std::static_pointer_cast<RNSBarItemProps const>(props);

APPLY_STRING_PROP(self, oldItemProps, newItemProps, title);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, icon);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, placement);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, variant);

APPLY_COLOR_PROP(self, oldItemProps, newItemProps, tintColor);

APPLY_OPTIONAL_DOUBLE_PROP(self, oldItemProps, newItemProps, width);
APPLY_BOOL_PROP(self, oldItemProps, newItemProps, disabled);
APPLY_BOOL_PROP(self, oldItemProps, newItemProps, selected);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, accessibilityLabel);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, accessibilityHint);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, testID);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, titleFontFamily);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, titleFontWeight);
APPLY_OPTIONAL_DOUBLE_PROP(self, oldItemProps, newItemProps, titleFontSize);

APPLY_COLOR_PROP(self, oldItemProps, newItemProps, titleColor);

APPLY_STRING_PROP(self, oldItemProps, newItemProps, identifier);
APPLY_BOOL_PROP(self, oldItemProps, newItemProps, hidesSharedBackground);
APPLY_BOOL_PROP(self, oldItemProps, newItemProps, sharesBackground);
APPLY_BOOL_PROP(self, oldItemProps, newItemProps, hasSharesBackground);
APPLY_BOOL_PROP(self, oldItemProps, newItemProps, hasBadge);

APPLY_NUMBER_PROP(self, oldItemProps, newItemProps, badgeCount);

APPLY_STRING_PROP(self, oldItemProps, newItemProps, badgeValue);

APPLY_COLOR_PROP(self, oldItemProps, newItemProps, badgeForegroundColor);
APPLY_COLOR_PROP(self, oldItemProps, newItemProps, badgeBackgroundColor);

APPLY_STRING_PROP(self, oldItemProps, newItemProps, badgeFontFamily);
APPLY_STRING_PROP(self, oldItemProps, newItemProps, badgeFontWeight);
APPLY_OPTIONAL_DOUBLE_PROP(self, oldItemProps, newItemProps, badgeFontSize);

[super updateProps:props oldProps:oldProps];

if (self.barParent != nil) {
[self.barParent updateBarItem:self];
}
}

- (void)emitPress
{
if (self.disabled) {
return;
}

if (auto eventEmitter = std::static_pointer_cast<RNSBarItemEventEmitter const>(_eventEmitter)) {
eventEmitter->onItemPress({});
}
}

@end
29 changes: 29 additions & 0 deletions ios/bar/RNSBarMenuActionView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#import <React/RCTViewComponentView.h>
#import <UIKit/UIKit.h>

#import "BarMenuContainer.h"

NS_ASSUME_NONNULL_BEGIN

@interface RNSBarMenuActionView : RCTViewComponentView

@property (nonatomic, weak, nullable) id<BarMenuContainer> menuParent;
@property (nonatomic, copy, nullable) NSString *identifier;
@property (nonatomic, copy, nullable) NSString *title;
@property (nonatomic, copy, nullable) NSString *subtitle;
@property (nonatomic, copy, nullable) NSString *icon;
@property (nonatomic, assign) BOOL disabled;
@property (nonatomic, assign) BOOL destructive;
@property (nonatomic, assign) BOOL keepsMenuPresented;
@property (nonatomic, copy, nullable) NSString *discoverabilityLabel;
@property (nonatomic, assign) UIMenuElementState state;

- (void)emitPress;
- (UIAction *)uiAction;
- (void)applySelectionState:(UIMenuElementState)state;
- (void)clearSelectionState;
- (UIMenuElementState)effectiveState;

@end

NS_ASSUME_NONNULL_END
Loading