mattermost-mobile-upstream/app/utils/gallery/vectors.ts
Elias Nahum b6fc85385e
Migrate from RNN to Expo router (#9402)
* Expo-Router partial migration

* Full migration to ExpoRouter

* i18n

* add tests

* Merge branch 'main' into expo-router

* align package-lock.json

* i18n

* feedback review

* feedback review

* android 16kb patch

* Refactored emoji picker keyboard using a state machine

* set android launch_screen in drawables instead of layout

* no conditional hooks

* remove duplicate call in test

* address feedback

* fix tests and address more feedback

* small corrections

* small corrections

* small corrections

* fix draft test

* fix draft test 2

* remove navigateToScreen in draff test

* fix nit in draft test

* remove doc file

* Feedback review

* fix snapshots

* improve test coverage

* fix i18n

* Upgrade t o RN 0.83, other dependencies and new architecture (#9737)

* library hardware-keyboard android new arch support fix

* library rnshare android new arch support fix

* library rnutils android new arch support fix

* library secure-pdf-viewer add new arch support

* Enable new arch on iOS and Android

* update emm and network client with new-arch

* update intune to use new-arch

* performance improvements

* fix tests

* fixes post input on new-arch

* fix android emoji picker

* remove doc

* run tests in parallel

* upgrade to React Native 0.83.9, Expo 55, React 19, and New Architecture

Bumps core dependencies to their latest versions:
- React Native 0.77.3 → 0.83.9 (New Architecture enabled)
- React 18.3.1 → 19.2.5
- Expo SDK 52 → 55
- TypeScript 5.8.3 → 6.0.3
- Node.js 22.16.0 → 24.15.0
- react-native-reanimated 3.17.3 → 4.3.0
- Various other dependency upgrades

Migrates iOS AppDelegate from Objective-C to Swift, updates Android
build tooling and Gradle wrapper, refreshes all patches and font
assets, and adapts app code, tests, and CI workflows throughout for
API changes introduced by these upgrades.

* remove unecessary dismissKeyboard in notifications

* feedback review

* update intune to use new-arch

* update @mattermost deps

* missing i18n string

* additional fixes

* update fastlane
2026-05-13 17:44:55 +08:00

239 lines
5.0 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {useSharedValue, type SharedValue} from 'react-native-reanimated';
type SharedValueType = number;
type Callback = () => unknown;
type VectorType = Vector<any> | SharedVector<any>;
type VectorList = Array<VectorType | SharedValueType>;
type Operation = 'divide' | 'add' | 'sub' | 'multiply';
type VectorProp = 'x' | 'y';
export type Vector<T extends SharedValueType> = {
x: T;
y: T;
};
export type SharedVector<T extends SharedValueType> = {
x: SharedValue<T>;
y: SharedValue<T>;
};
const isVector = (value: any): value is Vector<any> => {
'worklet';
return value.x !== undefined && value.y !== undefined;
};
const isSharedValue = (
value: any,
): value is SharedValue<any> => {
'worklet';
return typeof value.value !== 'undefined';
};
const get = <T extends SharedValue<SharedValueType> | SharedValueType>(
value: T,
) => {
'worklet';
if (isSharedValue(value)) {
return value.value;
}
return value;
};
const reduce = (
operation: Operation,
prop: VectorProp,
vectors: VectorList,
) => {
'worklet';
const first = vectors[0];
const rest = vectors.slice(1);
const initial = get(isVector(first) ? first[prop] : first);
const res = rest.reduce((acc, current) => {
const value = get(isVector(current) ? current[prop] : current);
const r = (() => {
switch (operation) {
case 'divide':
if (value === 0) {
return 0;
}
return acc / value;
case 'add':
return acc + value;
case 'sub':
return acc - value;
case 'multiply':
return acc * value;
default:
return acc;
}
})();
return r;
}, initial);
return res;
};
export type ShareVectorType<T> = {
x: SharedValue<T>;
y: SharedValue<T>;
}
export const useSharedVector = <T>(x: T, y = x): ShareVectorType<T> => {
return {
x: useSharedValue(x),
y: useSharedValue(y),
};
};
export const create = <T extends SharedValueType>(x: T, y: T): Vector<T> => {
'worklet';
return {
x,
y,
};
};
export const add = (...vectors: VectorList) => {
'worklet';
return {
x: reduce('add', 'x', vectors),
y: reduce('add', 'y', vectors),
};
};
export const sub = (...vectors: VectorList) => {
'worklet';
return {
x: reduce('sub', 'x', vectors),
y: reduce('sub', 'y', vectors),
};
};
export const divide = (...vectors: VectorList) => {
'worklet';
return {
x: reduce('divide', 'x', vectors),
y: reduce('divide', 'y', vectors),
};
};
export const multiply = (...vectors: VectorList) => {
'worklet';
return {
x: reduce('multiply', 'x', vectors),
y: reduce('multiply', 'y', vectors),
};
};
export const invert = <T extends Vector<any>>(vector: T) => {
'worklet';
return {
x: get(vector.x) * -1,
y: get(vector.y) * -1,
};
};
export const set = <T extends VectorType>(
vector: T,
value: VectorType | SharedValueType | Callback,
) => {
'worklet';
// handle animation
if (typeof value === 'function') {
vector.x.value = value();
vector.y.value = value();
return;
}
const x = get(isVector(value) ? value.x : value);
const y = get(isVector(value) ? value.y : value);
if (typeof vector.x.value === 'undefined') {
vector.x = x;
vector.y = y;
} else {
vector.x.value = x;
vector.y.value = y;
}
};
export const min = (...vectors: VectorList) => {
'worklet';
const getMin = (prop: VectorProp) => {
return Math.min.apply(
undefined,
vectors.map((item) =>
get(isVector(item) ? item[prop] : item),
),
);
};
return {
x: getMin('x'),
y: getMin('y'),
};
};
export const max = (...vectors: VectorList) => {
'worklet';
const getMax = (prop: VectorProp) =>
Math.max.apply(
undefined,
vectors.map((item) =>
get(isVector(item) ? item[prop] : item),
),
);
return {
x: getMax('x'),
y: getMax('y'),
};
};
export const clamp = <T extends Vector<any>>(
value: T,
lowerBound: VectorType | SharedValueType,
upperBound: VectorType | SharedValueType,
) => {
'worklet';
return min(max(lowerBound, value), upperBound);
};
export const eq = <T extends Vector<any>>(
vector: T,
value: VectorType | SharedValueType,
) => {
'worklet';
const x = get(isVector(value) ? value.x : value);
const y = get(isVector(value) ? value.y : value);
return get(vector.x) === x && get(vector.y) === y;
};