Files
mattermost-mobile/app/utils/gallery/vectors.ts
Elias Nahum 5de54471b7 [Gekidou] Gallery (#6008)
* Gallery screen (ground work)

* Open the gallery from posts

* Open the gallery from post draft

* feedback review

* Feedback review 2

* do not remove dm channel names and localization fix

* update to the latest network-client

* do not override file width, height and imageThumbail if received file does not have it set

* bring back ScrollView wrapper for message component

* Remove Text wrapper for markdown paragraph

* Fix YouTube play icon placeholder

* Make video file play button container round

* Add gif image placeholder

* Save images & videos to camera roll

* Feedback review 3

* load video thumbnail when post is in viewport

* simplify prefix
2022-03-01 13:55:44 -03:00

233 lines
4.9 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import Animated, {useSharedValue} 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: Animated.SharedValue<T>;
y: Animated.SharedValue<T>;
};
const isVector = (value: any): value is Vector<any> => {
'worklet';
return value.x !== undefined && value.y !== undefined;
};
const isSharedValue = (
value: any,
): value is Animated.SharedValue<any> => {
'worklet';
return typeof value.value !== 'undefined';
};
const get = <T extends Animated.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 const useSharedVector = <T>(x: T, y = x) => {
return {
x: useSharedValue(x),
y: useSharedValue(y),
};
};
export const create = <T extends SharedValueType>(x: T, y: 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();
}
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;
};