New User Onboarding Task List (#9083)
* Improve type of AccessibleButton to accurately represent available props * Update analytics events
This commit is contained in:
parent
45f6c32eb6
commit
1e4c336fed
32 changed files with 1261 additions and 22 deletions
85
src/hooks/useSmoothAnimation.ts
Normal file
85
src/hooks/useSmoothAnimation.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
import { useAnimation } from "./useAnimation";
|
||||
|
||||
const debuglog = (...args: any[]) => {
|
||||
if (SettingsStore.getValue("debug_animation")) {
|
||||
logger.log.call(console, "Animation debuglog:", ...args);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Utility function to smoothly animate to a certain target value
|
||||
* @param initialValue Initial value to be used as initial starting point
|
||||
* @param targetValue Desired value to animate to (can be changed repeatedly to whatever is current at that time)
|
||||
* @param duration Duration that each animation should take
|
||||
* @param enabled Whether the animation should run or not
|
||||
*/
|
||||
export function useSmoothAnimation(
|
||||
initialValue: number,
|
||||
targetValue: number,
|
||||
duration: number,
|
||||
enabled: boolean,
|
||||
): number {
|
||||
const state = useRef<{ timestamp: DOMHighResTimeStamp | null, value: number }>({
|
||||
timestamp: null,
|
||||
value: initialValue,
|
||||
});
|
||||
const [currentValue, setCurrentValue] = useState<number>(initialValue);
|
||||
const [currentStepSize, setCurrentStepSize] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
const totalDelta = targetValue - state.current.value;
|
||||
setCurrentStepSize(totalDelta / duration);
|
||||
state.current = { ...state.current, timestamp: null };
|
||||
}, [duration, targetValue]);
|
||||
|
||||
const update = useCallback(
|
||||
(timestamp: DOMHighResTimeStamp): boolean => {
|
||||
if (!state.current.timestamp) {
|
||||
state.current = { ...state.current, timestamp };
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Math.abs(currentStepSize) < Number.EPSILON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const timeDelta = timestamp - state.current.timestamp;
|
||||
const valueDelta = currentStepSize * timeDelta;
|
||||
const maxValueDelta = targetValue - state.current.value;
|
||||
const clampedValueDelta = Math.sign(valueDelta) * Math.min(Math.abs(maxValueDelta), Math.abs(valueDelta));
|
||||
const value = state.current.value + clampedValueDelta;
|
||||
|
||||
debuglog(`Animating to ${targetValue} at ${value} timeDelta=${timeDelta}, valueDelta=${valueDelta}`);
|
||||
|
||||
setCurrentValue(value);
|
||||
state.current = { value, timestamp };
|
||||
|
||||
return Math.abs(maxValueDelta) > Number.EPSILON;
|
||||
},
|
||||
[currentStepSize, targetValue],
|
||||
);
|
||||
|
||||
useAnimation(enabled, update);
|
||||
|
||||
return currentValue;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue