- App.tsx: full navigation (Auth stack + Main tabs with 5 screens) - Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen - HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors - MapScreen: interactive map with layer toggles (6 layers) - MarketplaceScreen: categories (6), products (5), search - ChatScreen: AI chat with quick prompts (4), bot responses - ProfileScreen: user info, stats, menu (9 items), logout - AlertsScreen: alert list with severity, acknowledge - SensorsScreen: sensor list with type filters (6 types), search - ZonesScreen: zone cards with stats - SettingsScreen: language picker (FR/EN/ES/DE), privacy, about - Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n - Hooks: useSensors, useAlerts, useNotifications, useLocation - Components: Card, Button, LoadingSpinner, ErrorBoundary, Header - Services: iotService, notificationService (with axios API client) - Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN) - Theme: colors.ts with full design system (Blue Ocean palette) - Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
249 lines
6.4 KiB
Objective-C
249 lines
6.4 KiB
Objective-C
#import "RNGestureHandlerPointerTracker.h"
|
|
#import "RNGestureHandler.h"
|
|
|
|
#import <React/UIView+React.h>
|
|
|
|
@implementation RNGestureHandlerPointerTracker {
|
|
__weak RNGestureHandler *_gestureHandler;
|
|
RNGHUITouch *_trackedPointers[MAX_POINTERS_COUNT];
|
|
int _trackedPointersCount;
|
|
}
|
|
|
|
- (id)initWithGestureHandler:(id)gestureHandler
|
|
{
|
|
_gestureHandler = gestureHandler;
|
|
_trackedPointersCount = 0;
|
|
_changedPointersData = nil;
|
|
_allPointersData = nil;
|
|
|
|
for (int i = 0; i < MAX_POINTERS_COUNT; i++) {
|
|
_trackedPointers[i] = nil;
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (int)registerTouch:(RNGHUITouch *)touch
|
|
{
|
|
for (int index = 0; index < MAX_POINTERS_COUNT; index++) {
|
|
if (_trackedPointers[index] == nil) {
|
|
_trackedPointers[index] = touch;
|
|
return index;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
- (int)unregisterTouch:(RNGHUITouch *)touch
|
|
{
|
|
for (int index = 0; index < MAX_POINTERS_COUNT; index++) {
|
|
if (_trackedPointers[index] == touch) {
|
|
_trackedPointers[index] = nil;
|
|
return index;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
- (int)findTouchIndex:(RNGHUITouch *)touch
|
|
{
|
|
for (int index = 0; index < MAX_POINTERS_COUNT; index++) {
|
|
if (_trackedPointers[index] == touch) {
|
|
return index;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
- (int)registeredTouchesCount
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i < MAX_POINTERS_COUNT; i++) {
|
|
if (_trackedPointers[i] != nil) {
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
- (NSDictionary *)extractPointerData:(int)index forTouch:(RNGHUITouch *)touch
|
|
{
|
|
#if TARGET_OS_OSX
|
|
CGPoint absolutePos = [touch locationInWindow];
|
|
CGPoint relativePos = [touch.window.contentView convertPoint:absolutePos fromView:_gestureHandler.recognizer.view];
|
|
#else
|
|
CGPoint relativePos = [touch locationInView:_gestureHandler.recognizer.view];
|
|
CGPoint absolutePos = [touch locationInView:_gestureHandler.recognizer.view.window];
|
|
#endif
|
|
|
|
return @{
|
|
@"id" : @(index),
|
|
@"x" : @(relativePos.x),
|
|
@"y" : @(relativePos.y),
|
|
@"absoluteX" : @(absolutePos.x),
|
|
@"absoluteY" : @(absolutePos.y)
|
|
};
|
|
}
|
|
|
|
- (void)extractAllTouches
|
|
{
|
|
int registeredTouches = [self registeredTouchesCount];
|
|
|
|
NSDictionary *data[registeredTouches];
|
|
int nextIndex = 0;
|
|
|
|
for (int i = 0; i < MAX_POINTERS_COUNT; i++) {
|
|
RNGHUITouch *touch = _trackedPointers[i];
|
|
if (touch != nil) {
|
|
data[nextIndex++] = [self extractPointerData:i forTouch:touch];
|
|
}
|
|
}
|
|
|
|
_allPointersData = [[NSArray alloc] initWithObjects:data count:registeredTouches];
|
|
}
|
|
|
|
- (void)touchesBegan:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
|
|
{
|
|
if (!_gestureHandler.needsPointerData) {
|
|
return;
|
|
}
|
|
|
|
_eventType = RNGHTouchEventTypePointerDown;
|
|
|
|
NSDictionary *data[touches.count];
|
|
|
|
for (int i = 0; i < [touches count]; i++) {
|
|
RNGHUITouch *touch = [[touches allObjects] objectAtIndex:i];
|
|
int index = [self registerTouch:touch];
|
|
if (index >= 0) {
|
|
_trackedPointersCount++;
|
|
}
|
|
|
|
data[i] = [self extractPointerData:index forTouch:touch];
|
|
}
|
|
|
|
_changedPointersData = [[NSArray alloc] initWithObjects:data count:[touches count]];
|
|
// extract all touches last to include the ones that were just added
|
|
[self extractAllTouches];
|
|
[self sendEvent];
|
|
}
|
|
|
|
- (void)touchesMoved:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
|
|
{
|
|
if (!_gestureHandler.needsPointerData) {
|
|
return;
|
|
}
|
|
|
|
_eventType = RNGHTouchEventTypePointerMove;
|
|
|
|
NSDictionary *data[touches.count];
|
|
|
|
for (int i = 0; i < [touches count]; i++) {
|
|
RNGHUITouch *touch = [[touches allObjects] objectAtIndex:i];
|
|
int index = [self findTouchIndex:touch];
|
|
data[i] = [self extractPointerData:index forTouch:touch];
|
|
}
|
|
|
|
_changedPointersData = [[NSArray alloc] initWithObjects:data count:[touches count]];
|
|
[self extractAllTouches];
|
|
[self sendEvent];
|
|
}
|
|
|
|
- (void)touchesEnded:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
|
|
{
|
|
if (!_gestureHandler.needsPointerData) {
|
|
return;
|
|
}
|
|
|
|
// extract all touches first to include the ones that were just lifted
|
|
[self extractAllTouches];
|
|
|
|
_eventType = RNGHTouchEventTypePointerUp;
|
|
|
|
NSDictionary *data[touches.count];
|
|
|
|
for (int i = 0; i < [touches count]; i++) {
|
|
RNGHUITouch *touch = [[touches allObjects] objectAtIndex:i];
|
|
int index = [self unregisterTouch:touch];
|
|
if (index >= 0) {
|
|
_trackedPointersCount--;
|
|
}
|
|
|
|
data[i] = [self extractPointerData:index forTouch:touch];
|
|
}
|
|
|
|
_changedPointersData = [[NSArray alloc] initWithObjects:data count:[touches count]];
|
|
[self sendEvent];
|
|
}
|
|
|
|
- (void)touchesCancelled:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
|
|
{
|
|
if (!_gestureHandler.needsPointerData) {
|
|
return;
|
|
}
|
|
|
|
[self reset];
|
|
}
|
|
|
|
- (void)reset
|
|
{
|
|
if (!_gestureHandler.needsPointerData) {
|
|
return;
|
|
}
|
|
|
|
if (_trackedPointersCount == 0) {
|
|
// gesture has finished because all pointers were lifted, reset event type to send state change event
|
|
_eventType = RNGHTouchEventTypeUndetermined;
|
|
} else {
|
|
// turns out that the gesture may be made to fail without calling touchesCancelled in that case there
|
|
// are still tracked pointers but the recognizer state is already set to UIGestureRecognizerStateFailed
|
|
// we need to clear the pointers and send info about their cancellation
|
|
[self cancelPointers];
|
|
}
|
|
|
|
[_gestureHandler reset];
|
|
}
|
|
|
|
- (void)cancelPointers
|
|
{
|
|
// extract all touches first to include the ones that were just cancelled
|
|
[self extractAllTouches];
|
|
|
|
int registeredTouches = [self registeredTouchesCount];
|
|
|
|
if (registeredTouches > 0) {
|
|
int nextIndex = 0;
|
|
NSDictionary *data[registeredTouches];
|
|
|
|
for (int i = 0; i < MAX_POINTERS_COUNT; i++) {
|
|
RNGHUITouch *touch = _trackedPointers[i];
|
|
if (touch != nil) {
|
|
data[nextIndex++] = [self extractPointerData:i forTouch:touch];
|
|
[self unregisterTouch:touch];
|
|
}
|
|
}
|
|
|
|
_eventType = RNGHTouchEventTypeCancelled;
|
|
_changedPointersData = [[NSArray alloc] initWithObjects:data count:registeredTouches];
|
|
[self sendEvent];
|
|
_trackedPointersCount = 0;
|
|
}
|
|
}
|
|
|
|
- (void)sendEvent
|
|
{
|
|
// it may happen that the gesture recognizer is reset after it's been unbound from the view,
|
|
// it that recognizer tried to send event, the app would crash because the target of the event
|
|
// would be nil.
|
|
if (!_gestureHandler.needsPointerData || _gestureHandler.recognizer.view.reactTag == nil) {
|
|
return;
|
|
}
|
|
|
|
[_gestureHandler sendTouchEventInState:[_gestureHandler state]
|
|
forViewWithTag:_gestureHandler.recognizer.view.reactTag];
|
|
}
|
|
|
|
@end
|