1import { spacing } from '@expo/styleguide-native';
2import { StackScreenProps } from '@react-navigation/stack';
3import dedent from 'dedent';
4import { Divider, Spacer, Text, useExpoTheme, View } from 'expo-dev-client-components';
5import * as React from 'react';
6import { ActivityIndicator } from 'react-native';
7
8import { ConstantItem } from '../../components/ConstantItem';
9import ScrollView from '../../components/NavigationScrollView';
10import ShareProjectButton from '../../components/ShareProjectButton';
11import { WebContainerProjectPage_Query } from '../../graphql/types';
12import { HomeStackRoutes } from '../../navigation/Navigation.types';
13import { EASUpdateLaunchSection } from './EASUpdateLaunchSection';
14import { EmptySection } from './EmptySection';
15import { LegacyLaunchSection } from './LegacyLaunchSection';
16import { ProjectHeader } from './ProjectHeader';
17
18const ERROR_TEXT = dedent`
19  An unexpected error has occurred.
20  Sorry about this. We will resolve the issue as soon as possible.
21`;
22
23type Props = {
24  loading: boolean;
25  error?: Error;
26  data?: WebContainerProjectPage_Query;
27} & StackScreenProps<HomeStackRoutes, 'ProjectDetails'>;
28
29type ProjectPageApp = WebContainerProjectPage_Query['app']['byId'];
30
31export function ProjectView({ loading, error, data, navigation }: Props) {
32  const theme = useExpoTheme();
33
34  let contents;
35  if (error && !data?.app?.byId) {
36    console.log(error);
37    contents = (
38      <Text
39        align="center"
40        style={{ marginBottom: spacing[4], marginHorizontal: spacing[4] }}
41        type="InterRegular">
42        {ERROR_TEXT}
43      </Text>
44    );
45  } else if (loading || !data?.app?.byId) {
46    contents = (
47      <View flex="1" align="centered">
48        <ActivityIndicator size="large" color={theme.highlight.accent} />
49      </View>
50    );
51  } else {
52    const app = data.app.byId;
53
54    contents = (
55      <ScrollView style={{ flex: 1 }}>
56        <ProjectHeader app={app} />
57        <View padding="medium">
58          {appHasLegacyUpdate(app) && <LegacyLaunchSection app={app} />}
59          {appHasEASUpdates(app) && <EASUpdateLaunchSection app={app} />}
60          {!appHasLegacyUpdate(app) && !appHasEASUpdates(app) && <EmptySection />}
61          <Spacer.Vertical size="xl" />
62          <View bg="default" border="default" overflow="hidden" rounded="large">
63            <ConstantItem title="Owner" value={app.username} />
64            <Divider style={{ height: 1 }} />
65            <ConstantItem title="SDK Version" value={app.sdkVersion} />
66          </View>
67        </View>
68      </ScrollView>
69    );
70  }
71
72  React.useEffect(() => {
73    if (data?.app?.byId) {
74      const fullName = data?.app.byId.fullName;
75      const title = data?.app.byId.name ?? fullName;
76      navigation.setOptions({
77        title,
78        headerRight: () => <ShareProjectButton fullName={fullName} />,
79      });
80    }
81  }, [navigation, data?.app?.byId]);
82
83  return <View flex="1">{contents}</View>;
84}
85
86function appHasLegacyUpdate(app: ProjectPageApp): boolean {
87  return app.published;
88}
89
90function appHasEASUpdates(app: ProjectPageApp): boolean {
91  return app.updateBranches.some((branch) => branch.updates.length > 0);
92}
93