2025-04-01 10:38:02 +09:00

57 lines
2.0 KiB
TypeScript

import { useEffect, useState } from 'react';
import { SceneObjectStateChangedEvent } from '@grafana/scenes';
import { DataTrail } from '../DataTrail';
import { isDataTrailsHistoryState } from '../DataTrailsHistory';
import { reportExploreMetrics } from '../interactions';
import { getTrailStore } from './TrailStore';
export function useBookmarkState(trail: DataTrail) {
// Note that trail object may stay the same, but the state used by `getBookmarkIndex` result may
// differ for each re-render of this hook
const getBookmarkIndex = () => getTrailStore().getBookmarkIndex(trail);
const indexOnRender = getBookmarkIndex();
const [bookmarkIndex, setBookmarkIndex] = useState(indexOnRender);
useEffect(() => {
const sub = trail.subscribeToEvent(SceneObjectStateChangedEvent, ({ payload: { prevState, newState } }) => {
if (isDataTrailsHistoryState(prevState) && isDataTrailsHistoryState(newState)) {
if (newState.steps.length > prevState.steps.length) {
// When we add new steps, we need to re-evaluate whether or not it is still a bookmark
setBookmarkIndex(getTrailStore().getBookmarkIndex(trail));
}
}
});
return () => sub.unsubscribe();
}, [trail]);
// Check if index changed and force a re-render
if (indexOnRender !== bookmarkIndex) {
setBookmarkIndex(indexOnRender);
}
const isBookmarked = bookmarkIndex != null;
const toggleBookmark = () => {
reportExploreMetrics('bookmark_changed', { action: isBookmarked ? 'toggled_off' : 'toggled_on' });
if (isBookmarked) {
let indexToRemove = getBookmarkIndex();
while (indexToRemove != null) {
// This loop will remove all indices that have an equivalent bookmark key
getTrailStore().removeBookmark(indexToRemove);
indexToRemove = getBookmarkIndex();
}
} else {
getTrailStore().addBookmark(trail);
}
setBookmarkIndex(getBookmarkIndex());
};
const result: [typeof isBookmarked, typeof toggleBookmark] = [isBookmarked, toggleBookmark];
return result;
}