- 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
141 lines
3.8 KiB
JavaScript
141 lines
3.8 KiB
JavaScript
'use strict';
|
||
|
||
/**
|
||
* https://github.com/gre/bezier-easing
|
||
* BezierEasing - use bezier curve for transition easing function
|
||
* by Gaëtan Renaudeau 2014 - 2015 – MIT License
|
||
*/
|
||
|
||
// These values are established by empiricism with tests (tradeoff: performance VS precision)
|
||
const NEWTON_ITERATIONS = 4;
|
||
const NEWTON_MIN_SLOPE = 0.001;
|
||
const SUBDIVISION_PRECISION = 0.0000001;
|
||
const SUBDIVISION_MAX_ITERATIONS = 10;
|
||
const kSplineTableSize = 11;
|
||
const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);
|
||
function A(aA1, aA2) {
|
||
'worklet';
|
||
|
||
return 1.0 - 3.0 * aA2 + 3.0 * aA1;
|
||
}
|
||
function B(aA1, aA2) {
|
||
'worklet';
|
||
|
||
return 3.0 * aA2 - 6.0 * aA1;
|
||
}
|
||
function C(aA1) {
|
||
'worklet';
|
||
|
||
return 3.0 * aA1;
|
||
}
|
||
|
||
// Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
|
||
function calcBezier(aT, aA1, aA2) {
|
||
'worklet';
|
||
|
||
return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;
|
||
}
|
||
|
||
// Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
|
||
function getSlope(aT, aA1, aA2) {
|
||
'worklet';
|
||
|
||
return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);
|
||
}
|
||
function binarySubdivide(aX, aA, aB, mX1, mX2) {
|
||
'worklet';
|
||
|
||
let currentX;
|
||
let currentT;
|
||
let i = 0;
|
||
do {
|
||
currentT = aA + (aB - aA) / 2.0;
|
||
currentX = calcBezier(currentT, mX1, mX2) - aX;
|
||
if (currentX > 0.0) {
|
||
aB = currentT;
|
||
} else {
|
||
aA = currentT;
|
||
}
|
||
} while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
|
||
return currentT;
|
||
}
|
||
function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {
|
||
'worklet';
|
||
|
||
for (let i = 0; i < NEWTON_ITERATIONS; ++i) {
|
||
const currentSlope = getSlope(aGuessT, mX1, mX2);
|
||
if (currentSlope === 0.0) {
|
||
return aGuessT;
|
||
}
|
||
const currentX = calcBezier(aGuessT, mX1, mX2) - aX;
|
||
aGuessT -= currentX / currentSlope;
|
||
}
|
||
return aGuessT;
|
||
}
|
||
export function Bezier(mX1, mY1, mX2, mY2) {
|
||
'worklet';
|
||
|
||
function LinearEasing(x) {
|
||
'worklet';
|
||
|
||
return x;
|
||
}
|
||
if (!(mX1 >= 0 && mX1 <= 1 && mX2 >= 0 && mX2 <= 1)) {
|
||
throw new Error('[Reanimated] Bezier x values must be in [0, 1] range.');
|
||
}
|
||
if (mX1 === mY1 && mX2 === mY2) {
|
||
return LinearEasing;
|
||
}
|
||
|
||
// FIXME: Float32Array is not available in Hermes right now
|
||
//
|
||
// var float32ArraySupported = typeof Float32Array === 'function';
|
||
// const sampleValues = float32ArraySupported
|
||
// ? new Float32Array(kSplineTableSize)
|
||
// : new Array(kSplineTableSize);
|
||
|
||
// Precompute samples table
|
||
const sampleValues = new Array(kSplineTableSize);
|
||
for (let i = 0; i < kSplineTableSize; ++i) {
|
||
sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);
|
||
}
|
||
function getTForX(aX) {
|
||
'worklet';
|
||
|
||
let intervalStart = 0.0;
|
||
let currentSample = 1;
|
||
const lastSample = kSplineTableSize - 1;
|
||
for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {
|
||
intervalStart += kSampleStepSize;
|
||
}
|
||
--currentSample;
|
||
|
||
// Interpolate to provide an initial guess for t
|
||
const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);
|
||
const guessForT = intervalStart + dist * kSampleStepSize;
|
||
const initialSlope = getSlope(guessForT, mX1, mX2);
|
||
if (initialSlope >= NEWTON_MIN_SLOPE) {
|
||
return newtonRaphsonIterate(aX, guessForT, mX1, mX2);
|
||
} else if (initialSlope === 0.0) {
|
||
return guessForT;
|
||
} else {
|
||
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);
|
||
}
|
||
}
|
||
return function BezierEasing(x) {
|
||
'worklet';
|
||
|
||
if (mX1 === mY1 && mX2 === mY2) {
|
||
return x; // linear
|
||
}
|
||
// Because JavaScript number are imprecise, we should guarantee the extremes are right.
|
||
if (x === 0) {
|
||
return 0;
|
||
}
|
||
if (x === 1) {
|
||
return 1;
|
||
}
|
||
return calcBezier(getTForX(x), mY1, mY2);
|
||
};
|
||
}
|
||
//# sourceMappingURL=Bezier.js.map
|