import {Fragment, useMemo} from 'react';
import {useTheme} from '@emotion/react';
import styled from '@emotion/styled';
import Alert from 'sentry/components/alert';
import LoadingContainer from 'sentry/components/loading/loadingContainer';
import LoadingIndicator from 'sentry/components/loadingIndicator';
import type {CursorHandler} from 'sentry/components/pagination';
import SearchBar from 'sentry/components/performance/searchBar';
import {t} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {NewQuery} from 'sentry/types/organization';
import {defined} from 'sentry/utils';
import {trackAnalytics} from 'sentry/utils/analytics';
import {browserHistory} from 'sentry/utils/browserHistory';
import EventView from 'sentry/utils/discover/eventView';
import {DiscoverDatasets} from 'sentry/utils/discover/types';
import {decodeScalar} from 'sentry/utils/queryString';
import {escapeFilterValue, MutableSearch} from 'sentry/utils/tokenizeSearch';
import {useLocation} from 'sentry/utils/useLocation';
import useOrganization from 'sentry/utils/useOrganization';
import usePageFilters from 'sentry/utils/usePageFilters';
import useRouter from 'sentry/utils/useRouter';
import ChartPanel from 'sentry/views/insights/common/components/chartPanel';
import {useTTFDConfigured} from 'sentry/views/insights/common/queries/useHasTtfdConfigured';
import {useReleaseSelection} from 'sentry/views/insights/common/queries/useReleases';
import {appendReleaseFilters} from 'sentry/views/insights/common/utils/releaseComparison';
import {useHasDataTrackAnalytics} from 'sentry/views/insights/common/utils/useHasDataTrackAnalytics';
import useCrossPlatformProject from 'sentry/views/insights/mobile/common/queries/useCrossPlatformProject';
import useTruncatedReleaseNames from 'sentry/views/insights/mobile/common/queries/useTruncatedRelease';
import {TOP_SCREENS} from 'sentry/views/insights/mobile/constants';
import {ScreensBarChart} from 'sentry/views/insights/mobile/screenload/components/charts/screenBarChart';
import {TabbedCodeSnippet} from 'sentry/views/insights/mobile/screenload/components/tabbedCodeSnippets';
import {
ScreensTable,
useTableQuery,
} from 'sentry/views/insights/mobile/screenload/components/tables/screensTable';
import {
CHART_TITLES,
MobileCursors,
YAxis,
YAXIS_COLUMNS,
} from 'sentry/views/insights/mobile/screenload/constants';
import {SETUP_CONTENT} from 'sentry/views/insights/mobile/screenload/data/setupContent';
import {transformReleaseEvents} from 'sentry/views/insights/mobile/screenload/utils';
import {ModuleName, SpanMetricsField} from 'sentry/views/insights/types';
import {prepareQueryForLandingPage} from 'sentry/views/performance/data';
import {getTransactionSearchQuery} from 'sentry/views/performance/utils';
type Props = {
yAxes: YAxis[];
additionalFilters?: string[];
chartHeight?: number;
};
export function ScreensView({yAxes, additionalFilters, chartHeight}: Props) {
const pageFilter = usePageFilters();
const {selection} = pageFilter;
const location = useLocation();
const theme = useTheme();
const organization = useOrganization();
const {isProjectCrossPlatform, selectedPlatform} = useCrossPlatformProject();
const {query: locationQuery} = location;
const cursor = decodeScalar(location.query?.[MobileCursors.SCREENS_TABLE]);
const yAxisCols = yAxes.map(val => YAXIS_COLUMNS[val]);
const {
primaryRelease,
secondaryRelease,
isLoading: isReleasesLoading,
} = useReleaseSelection();
const {truncatedPrimaryRelease, truncatedSecondaryRelease} = useTruncatedReleaseNames();
const router = useRouter();
const {hasTTFD} = useTTFDConfigured(additionalFilters);
const queryString = useMemo(() => {
const query = new MutableSearch([
'event.type:transaction',
'transaction.op:ui.load',
...(additionalFilters ?? []),
]);
if (isProjectCrossPlatform) {
query.addFilterValue('os.name', selectedPlatform);
}
const searchQuery = decodeScalar(locationQuery.query, '');
if (searchQuery) {
query.addStringFilter(prepareQueryForLandingPage(searchQuery, false));
}
return appendReleaseFilters(query, primaryRelease, secondaryRelease);
}, [
additionalFilters,
isProjectCrossPlatform,
locationQuery.query,
primaryRelease,
secondaryRelease,
selectedPlatform,
]);
const orderby = decodeScalar(locationQuery.sort, `-count`);
const newQuery: NewQuery = {
name: '',
fields: [
'transaction',
SpanMetricsField.PROJECT_ID,
`avg_if(measurements.time_to_initial_display,release,${primaryRelease})`,
`avg_if(measurements.time_to_initial_display,release,${secondaryRelease})`,
`avg_if(measurements.time_to_full_display,release,${primaryRelease})`,
`avg_if(measurements.time_to_full_display,release,${secondaryRelease})`,
'count()',
],
query: queryString,
dataset: DiscoverDatasets.METRICS,
version: 2,
projects: selection.projects,
};
newQuery.orderby = orderby;
const tableEventView = EventView.fromNewQueryWithLocation(newQuery, location);
const {
data: topTransactionsData,
isPending: topTransactionsLoading,
pageLinks,
} = useTableQuery({
eventView: tableEventView,
enabled: !isReleasesLoading,
referrer: 'api.starfish.mobile-screen-table',
cursor,
});
const topTransactions = useMemo(() => {
return (
topTransactionsData?.data?.slice(0, 5).map(datum => datum.transaction as string) ??
[]
);
}, [topTransactionsData?.data]);
const topEventsQueryString = useMemo(() => {
const topEventsQuery = new MutableSearch([
'event.type:transaction',
'transaction.op:ui.load',
...(additionalFilters ?? []),
]);
if (isProjectCrossPlatform) {
topEventsQuery.addFilterValue('os.name', selectedPlatform);
}
return `${appendReleaseFilters(topEventsQuery, primaryRelease, secondaryRelease)} ${
topTransactions.length > 0
? escapeFilterValue(
`transaction:[${topTransactions.map(name => `"${name}"`).join()}]`
)
: ''
}`.trim();
}, [
additionalFilters,
isProjectCrossPlatform,
primaryRelease,
secondaryRelease,
topTransactions,
selectedPlatform,
]);
const {data: releaseEvents, isPending: isReleaseEventsLoading} = useTableQuery({
eventView: EventView.fromNewQueryWithLocation(
{
name: '',
fields: ['transaction', 'release', ...yAxisCols],
orderby: yAxisCols[0],
yAxis: yAxisCols,
query: topEventsQueryString,
dataset: DiscoverDatasets.METRICS,
version: 2,
},
location
),
enabled: !topTransactionsLoading,
referrer: 'api.starfish.mobile-screen-bar-chart',
});
useHasDataTrackAnalytics(ModuleName.SCREEN_LOAD, 'insight.page_loads.screen_load');
if (isReleasesLoading) {
return (