Skip to content
Open
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
167 changes: 115 additions & 52 deletions src/js/worklets/communities.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,45 @@ import {

import { Platform } from 'react-native';

export function useStartScrollValue(isCollapsed, collapseThreshold) {
return useDerivedValue(() => {
return isCollapsed ? -collapseThreshold.value : 0;
});
}

export function useScrollValue(isCollapsed, collapseThreshold) {
return useDerivedValue(() => {
return isCollapsed ? collapseThreshold.value : 0;
});
}

export function useDerivedValueAdd(sharedValue, value) {
return useDerivedValue(() => {
return sharedValue.value + value;
});
}

export function useDerivedValueMul(sharedValue, value) {
return useDerivedValue(() => {
return sharedValue.value * value;
});
}

export function useLogoStyles({
initialState,
scrollAmount,
expandHeaderThreshold,
collapseThreshold,
sheetDisplacementThreshold,
textMovementThreshold,
}) {
return useAnimatedStyle(() => {
const firstDisplacement = scrollAmount.value < expandHeaderThreshold;
if (firstDisplacement) {
const isFirstDisplacement = initialState.value === 'expanded' || scrollAmount.value < collapseThreshold.value;
if (isFirstDisplacement) {
return {
transform: [
{ translateX: 20 },
{ translateY: interpolate(scrollAmount.value, [0, expandHeaderThreshold], [0, -42.5], 'clamp') },
{ scale: interpolate(scrollAmount.value, [0, textMovementThreshold], [1, 0.4], 'clamp') },
{ translateY: interpolate(scrollAmount.value, [0, collapseThreshold.value], [0, -42.5], 'clamp') },
{ scale: interpolate(scrollAmount.value, [0, textMovementThreshold.value], [1, 0.4], 'clamp') },
],
};
} else {
Expand All @@ -33,7 +58,7 @@ export function useLogoStyles({
{
translateY: interpolate(
scrollAmount.value,
[expandHeaderThreshold, sheetDisplacementThreshold],
[collapseThreshold.value, sheetDisplacementThreshold.value],
[-42.5, -50.5],
'clamp',
),
Expand All @@ -45,19 +70,19 @@ export function useLogoStyles({
});
}

export function useSheetStyles({ scrollAmount, expandHeaderThreshold, sheetDisplacementThreshold }) {
export function useSheetStyles({ initialState, scrollAmount, collapseThreshold, sheetDisplacementThreshold }) {
return useAnimatedStyle(() => {
const firstDisplacement = scrollAmount.value < expandHeaderThreshold;
if (firstDisplacement) {
const isFirstDisplacement = initialState.value === 'expanded' || scrollAmount.value < collapseThreshold.value;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny comment: Maybe we can create a helper function for computing isFirstDisplacement?

if (isFirstDisplacement) {
return {
transform: [{ translateY: interpolate(scrollAmount.value, [0, expandHeaderThreshold], [40, 0], 'clamp') }],
transform: [{ translateY: interpolate(scrollAmount.value, [0, collapseThreshold.value], [40, 0], 'clamp') }],
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
};
} else {
const radius = interpolate(
scrollAmount.value,
[expandHeaderThreshold, sheetDisplacementThreshold],
[collapseThreshold.value, sheetDisplacementThreshold.value],
[20, 0],
'clamp',
);
Expand All @@ -66,7 +91,7 @@ export function useSheetStyles({ scrollAmount, expandHeaderThreshold, sheetDispl
{
translateY: interpolate(
scrollAmount.value,
[expandHeaderThreshold, sheetDisplacementThreshold],
[collapseThreshold.value, sheetDisplacementThreshold.value],
[0, -8],
'clamp',
),
Expand All @@ -79,55 +104,81 @@ export function useSheetStyles({ scrollAmount, expandHeaderThreshold, sheetDispl
});
}

export function useNameStyles({ scrollAmount, expandHeaderThreshold, textMovementThreshold }) {
export function useNameStyles({ initialState, scrollAmount, collapseThreshold, textMovementThreshold }) {
return useAnimatedStyle(() => {
const animationProgress = interpolate(
scrollAmount.value,
[textMovementThreshold, expandHeaderThreshold],
[0, 40],
'clamp',
);
let horizontalPosition;
if (initialState.value === 'collapsed') {
horizontalPosition = 40;
} else if (initialState.value === 'expanded') {
horizontalPosition = 0;
} else {
horizontalPosition = interpolate(
scrollAmount.value,
[textMovementThreshold.value, collapseThreshold.value],
[0, 40],
'clamp',
);
}

let verticalPosition;
if (initialState.value === 'collapsed') {
verticalPosition = -44.5;
} else if (initialState.value === 'expanded') {
verticalPosition = 0;
} else {
verticalPosition = interpolate(
scrollAmount.value,
[textMovementThreshold.value, collapseThreshold.value],
[0, -44.5],
'clamp',
);
}

return {
marginRight: animationProgress,
transform: [
{ translateX: animationProgress },
{
translateY: interpolate(
scrollAmount.value,
[textMovementThreshold, expandHeaderThreshold],
[0, -44.5],
'clamp',
),
},
],
marginRight: horizontalPosition,
transform: [{ translateX: horizontalPosition }, { translateY: verticalPosition }],
};
});
}

export function useInfoStyles({ scrollAmount, infoOpacityThreshold }) {
export function useInfoStyles({ initialState, scrollAmount, collapseThreshold, infoOpacityThresholdFactor }) {
return useAnimatedStyle(() => {
let opacity;
if (initialState.value === 'collapsed') {
opacity = 0;
} else if (initialState.value === 'expanded') {
opacity = 1;
Comment on lines +147 to +150
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure who is choosing the names for collapsed or expanded (whether it's us or a library), but maybe we can introduce some constants for the strings?

} else {
const infoOpacityThreshold = collapseThreshold.value * infoOpacityThresholdFactor;
opacity = interpolate(scrollAmount.value, [0, infoOpacityThreshold], [1, 0.2], 'extend');
}
return {
opacity: interpolate(scrollAmount.value, [0, infoOpacityThreshold], [1, 0.2], 'extend'),
opacity: opacity,
};
});
}

export function useChannelsStyles({
scrollAmount,
headerHeight,
expandHeaderThreshold,
collapseThreshold,
sheetDisplacementThreshold,
expandHeaderLimit,
}) {
return useAnimatedStyle(() => {
const headerDisplacement = (headerHeight.value - 55.5) * -1;
const firstDisplacement = scrollAmount.value < expandHeaderThreshold;
const secondDisplacement = scrollAmount.value > sheetDisplacementThreshold;
const firstDisplacement = scrollAmount.value < collapseThreshold.value;
const secondDisplacement = scrollAmount.value > sheetDisplacementThreshold.value;
if (firstDisplacement) {
return {
transform: [
{
translateY: interpolate(scrollAmount.value, [0, expandHeaderThreshold], [39, headerDisplacement], 'clamp'),
translateY: interpolate(
scrollAmount.value,
[0, collapseThreshold.value],
[39, headerDisplacement],
'clamp',
),
},
],
};
Expand All @@ -137,7 +188,7 @@ export function useChannelsStyles({
{
translateY: interpolate(
scrollAmount.value,
[sheetDisplacementThreshold, expandHeaderLimit],
[sheetDisplacementThreshold.value, expandHeaderLimit.value],
[headerDisplacement - 8, headerDisplacement - 64],
'clamp',
),
Expand All @@ -150,27 +201,32 @@ export function useChannelsStyles({
{
translateY: interpolate(
scrollAmount.value,
[expandHeaderThreshold, sheetDisplacementThreshold],
[collapseThreshold.value, sheetDisplacementThreshold.value],
[headerDisplacement, headerDisplacement - 8],
'clamp',
),
},
],
};
}
}, [headerHeight.value]);
});
}

export function useScrollTo({ animatedRef, scrollAmount, expandHeaderLimit }) {
const isAndroid = Platform.OS === 'android';
return useDerivedValue(() => {
scrollTo(animatedRef, 0, scrollAmount.value - expandHeaderLimit, isAndroid);
scrollTo(animatedRef, 0, scrollAmount.value - expandHeaderLimit.value, isAndroid);
});
}

export function useHeaderOpacity({ scrollAmount, expandHeaderThreshold, sheetDisplacementThreshold }) {
export function useHeaderOpacity({ scrollAmount, collapseThreshold, sheetDisplacementThreshold }) {
return useDerivedValue(() => {
return interpolate(scrollAmount.value, [expandHeaderThreshold, sheetDisplacementThreshold], [0, 1], 'clamp');
return interpolate(
scrollAmount.value,
[collapseThreshold.value, sheetDisplacementThreshold.value],
[0, 1],
'clamp',
);
});
}

Expand All @@ -180,9 +236,15 @@ export function useOppositeHeaderOpacity(headerOpacity) {
});
}

export function useNavContentOpacity({ scrollAmount, sheetDisplacementThreshold, expandHeaderLimit }) {
export function useNavContentOpacity({
scrollAmount,
navbarContentThresholdFactor,
sheetDisplacementThreshold,
expandHeaderLimit,
}) {
return useDerivedValue(() => {
return interpolate(scrollAmount.value, [sheetDisplacementThreshold, expandHeaderLimit], [0, 1], 'clamp');
const navbarContentThreshold = sheetDisplacementThreshold.value + navbarContentThresholdFactor;
return interpolate(scrollAmount.value, [navbarContentThreshold, expandHeaderLimit.value], [0, 1], 'clamp');
});
}

Expand Down Expand Up @@ -240,7 +302,7 @@ export function onPanUpdate({ scrollStart, scrollAmount, maxScroll, expandHeader
if (newScrollAmount <= 0) {
scrollAmount.value = 0;
} else {
const limit = expandHeaderLimit + maxScroll.value;
const limit = expandHeaderLimit.value + maxScroll.value;
scrollAmount.value = newScrollAmount <= limit ? newScrollAmount : limit;
}
};
Expand All @@ -251,26 +313,27 @@ export function onPanEnd({
scrollAmount,
maxScroll,
expandHeaderLimit,
expandHeaderThreshold,
snapHeaderThreshold,
collapseThreshold,
snapHeaderThresholdFactor,
animationDuration,
}) {
const isIOS = Platform.OS === 'ios';
return function (event) {
'worklet';
scrollStart.value = -scrollAmount.value;
const snapHeaderThreshold = collapseThreshold.value * snapHeaderThresholdFactor;
const endAnimation = onScrollAnimationEnd(
scrollAmount,
scrollStart,
expandHeaderThreshold,
collapseThreshold.value,
snapHeaderThreshold,
expandHeaderLimit,
expandHeaderLimit.value,
animationDuration,
);
if (scrollAmount.value < expandHeaderLimit) {
if (scrollAmount.value < expandHeaderLimit.value) {
endAnimation();
} else {
const maxValue = maxScroll.value + expandHeaderLimit;
const maxValue = maxScroll.value + expandHeaderLimit.value;
const decelerationRate = isIOS ? { deceleration: 0.998 } : { deceleration: 0.996 };

scrollStart.value = withDecay({
Expand Down
4 changes: 4 additions & 0 deletions src/mocks/js_dependencies.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@
"../src/js/worklets/core.js" worklet-factory
"../src/js/worklets/communities.js" #js {"useLogoStyles" #js {}
"useSheetStyles" #js {}
"useStartScrollValue" #js {}
"useScrollValue" #js {}
"useDerivedValueAdd" #js {}
"useDerivedValueMul" #js {}
"useNameStyles" #js {}
"useInfoStyles" #js {}
"useChannelsStyles" #js {}
Expand Down
42 changes: 23 additions & 19 deletions src/quo/components/info/information_box/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
:container-style style/close-button}]])

(defn- content
[{:keys [theme type button-label on-button-press message colors-map customization-color]}]
[{:keys [theme type button-label on-button-press message colors-map customization-color
button-icon-right]}]
[rn/view {:style {:flex 1}}
[text/text
{:size :paragraph-2
Expand All @@ -40,22 +41,24 @@
:size 24
:customization-color customization-color
:on-press on-button-press
:container-style style/content-button}
:container-style style/content-button
:icon-right button-icon-right}
button-label])])

(defn view
"[view opts \"message\"]
opts
{:type :default/:informative/:error
:closed? bool (false) ;; Information box's state
:icon keyword, required (:i/info)
:icon-size int (16)
:no-icon-color? bool (false)
:style map
:button-label string
:on-button-press function
:on-close function"
[{:keys [type closed? blur? icon style button-label
{:type :default/:informative/:error
:closed? bool (false) ;; Information box's state
:icon keyword, required (:i/info)
:icon-size int (16)
:no-icon-color? bool (false)
:style map
:button-label string
:on-button-press function
:on-close function
:button-icon-right keyword to place an icon to the right of the button's label"
[{:keys [type closed? blur? icon style button-label button-icon-right
on-button-press on-close no-icon-color? icon-size customization-color]
:or {customization-color :primary}}
message]
Expand All @@ -67,12 +70,12 @@
include-button? (not (string/blank? button-label))]
[rn/view
{:accessibility-label :information-box
:style (merge (style/container {:theme theme
:colors-map colors-map
:customization-color customization-color
:type type
:include-button? include-button?})
style)}
:style [(style/container {:theme theme
:colors-map colors-map
:customization-color customization-color
:type type
:include-button? include-button?})
style]}
[icons/icon (or icon :i/info)
{:color (style/get-color-by-type colors-map theme type :icon)
:no-color no-icon-color?
Expand All @@ -85,6 +88,7 @@
:on-button-press on-button-press
:colors-map colors-map
:customization-color customization-color
:message message}]
:message message
:button-icon-right button-icon-right}]
(when on-close
[close-button {:theme theme :colors-map colors-map :on-close on-close}])])))
Loading