forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useMemo} from 'react'
2import {Platform} from 'react-native'
3import {setStringAsync} from 'expo-clipboard'
4import * as FileSystem from 'expo-file-system/legacy'
5import {Image} from 'expo-image'
6import {msg, Trans} from '@lingui/macro'
7import {useLingui} from '@lingui/react'
8import {type NativeStackScreenProps} from '@react-navigation/native-stack'
9import {useMutation} from '@tanstack/react-query'
10import {Statsig} from 'statsig-react-native-expo'
11
12import {STATUS_PAGE_URL} from '#/lib/constants'
13import {type CommonNavigatorParams} from '#/lib/routes/types'
14import {isAndroid, isIOS, isNative} from '#/platform/detection'
15import * as Toast from '#/view/com/util/Toast'
16import * as SettingsList from '#/screens/Settings/components/SettingsList'
17import {Atom_Stroke2_Corner0_Rounded as AtomIcon} from '#/components/icons/Atom'
18import {BroomSparkle_Stroke2_Corner2_Rounded as BroomSparkleIcon} from '#/components/icons/BroomSparkle'
19import {CodeLines_Stroke2_Corner2_Rounded as CodeLinesIcon} from '#/components/icons/CodeLines'
20import {Globe_Stroke2_Corner0_Rounded as GlobeIcon} from '#/components/icons/Globe'
21import {Newspaper_Stroke2_Corner2_Rounded as NewspaperIcon} from '#/components/icons/Newspaper'
22import {Wrench_Stroke2_Corner2_Rounded as WrenchIcon} from '#/components/icons/Wrench'
23import * as Layout from '#/components/Layout'
24import {Loader} from '#/components/Loader'
25import * as env from '#/env'
26import {useDemoMode} from '#/storage/hooks/demo-mode'
27import {useDevMode} from '#/storage/hooks/dev-mode'
28import {OTAInfo} from './components/OTAInfo'
29
30type Props = NativeStackScreenProps<CommonNavigatorParams, 'AboutSettings'>
31export function AboutSettingsScreen({}: Props) {
32 const {_, i18n} = useLingui()
33 const [devModeEnabled, setDevModeEnabled] = useDevMode()
34 const [demoModeEnabled, setDemoModeEnabled] = useDemoMode()
35 const stableID = useMemo(() => Statsig.getStableID(), [])
36
37 const {mutate: onClearImageCache, isPending: isClearingImageCache} =
38 useMutation({
39 mutationFn: async () => {
40 const freeSpaceBefore = await FileSystem.getFreeDiskStorageAsync()
41 await Image.clearDiskCache()
42 const freeSpaceAfter = await FileSystem.getFreeDiskStorageAsync()
43 const spaceDiff = freeSpaceBefore - freeSpaceAfter
44 return spaceDiff * -1
45 },
46 onSuccess: sizeDiffBytes => {
47 if (isAndroid) {
48 Toast.show(
49 _(
50 msg({
51 message: `Image cache cleared, freed ${i18n.number(
52 Math.abs(sizeDiffBytes / 1024 / 1024),
53 {
54 notation: 'compact',
55 style: 'unit',
56 unit: 'megabyte',
57 },
58 )}`,
59 comment: `Android-only toast message which includes amount of space freed using localized number formatting`,
60 }),
61 ),
62 )
63 } else {
64 Toast.show(_(msg`Image cache cleared`))
65 }
66 },
67 })
68
69 return (
70 <Layout.Screen>
71 <Layout.Header.Outer>
72 <Layout.Header.BackButton />
73 <Layout.Header.Content>
74 <Layout.Header.TitleText>
75 <Trans>About</Trans>
76 </Layout.Header.TitleText>
77 </Layout.Header.Content>
78 <Layout.Header.Slot />
79 </Layout.Header.Outer>
80 <Layout.Content>
81 <SettingsList.Container>
82 <SettingsList.LinkItem
83 to="https://bsky.social/about/support/tos"
84 label={_(msg`Terms of Service`)}>
85 <SettingsList.ItemIcon icon={NewspaperIcon} />
86 <SettingsList.ItemText>
87 <Trans>Terms of Service</Trans>
88 </SettingsList.ItemText>
89 </SettingsList.LinkItem>
90 <SettingsList.LinkItem
91 to="https://bsky.social/about/support/privacy-policy"
92 label={_(msg`Privacy Policy`)}>
93 <SettingsList.ItemIcon icon={NewspaperIcon} />
94 <SettingsList.ItemText>
95 <Trans>Privacy Policy</Trans>
96 </SettingsList.ItemText>
97 </SettingsList.LinkItem>
98 <SettingsList.LinkItem
99 to={STATUS_PAGE_URL}
100 label={_(msg`Status Page`)}>
101 <SettingsList.ItemIcon icon={GlobeIcon} />
102 <SettingsList.ItemText>
103 <Trans>Status Page</Trans>
104 </SettingsList.ItemText>
105 </SettingsList.LinkItem>
106 <SettingsList.Divider />
107 <SettingsList.LinkItem to="/sys/log" label={_(msg`System log`)}>
108 <SettingsList.ItemIcon icon={CodeLinesIcon} />
109 <SettingsList.ItemText>
110 <Trans>System log</Trans>
111 </SettingsList.ItemText>
112 </SettingsList.LinkItem>
113 {isNative && (
114 <SettingsList.PressableItem
115 onPress={() => onClearImageCache()}
116 label={_(msg`Clear image cache`)}
117 disabled={isClearingImageCache}>
118 <SettingsList.ItemIcon icon={BroomSparkleIcon} />
119 <SettingsList.ItemText>
120 <Trans>Clear image cache</Trans>
121 </SettingsList.ItemText>
122 {isClearingImageCache && <SettingsList.ItemIcon icon={Loader} />}
123 </SettingsList.PressableItem>
124 )}
125 <SettingsList.PressableItem
126 label={_(msg`Version ${env.APP_VERSION}`)}
127 accessibilityHint={_(msg`Copies build version to clipboard`)}
128 onLongPress={() => {
129 const newDevModeEnabled = !devModeEnabled
130 setDevModeEnabled(newDevModeEnabled)
131 Toast.show(
132 newDevModeEnabled
133 ? _(
134 msg({
135 message: 'Developer mode enabled',
136 context: 'toast',
137 }),
138 )
139 : _(
140 msg({
141 message: 'Developer mode disabled',
142 context: 'toast',
143 }),
144 ),
145 )
146 }}
147 onPress={() => {
148 setStringAsync(
149 `Build version: ${env.APP_VERSION}; Bundle info: ${env.APP_METADATA}; Bundle date: ${env.BUNDLE_DATE}; Platform: ${Platform.OS}; Platform version: ${Platform.Version}; Anonymous ID: ${stableID}`,
150 )
151 Toast.show(_(msg`Copied build version to clipboard`))
152 }}>
153 <SettingsList.ItemIcon icon={WrenchIcon} />
154 <SettingsList.ItemText>
155 <Trans>Version {env.APP_VERSION}</Trans>
156 </SettingsList.ItemText>
157 <SettingsList.BadgeText>{env.APP_METADATA}</SettingsList.BadgeText>
158 </SettingsList.PressableItem>
159 {devModeEnabled && (
160 <>
161 <OTAInfo />
162 {isIOS && (
163 <SettingsList.PressableItem
164 onPress={() => {
165 const newDemoModeEnabled = !demoModeEnabled
166 setDemoModeEnabled(newDemoModeEnabled)
167 Toast.show(
168 'Demo mode ' +
169 (newDemoModeEnabled ? 'enabled' : 'disabled'),
170 )
171 }}
172 label={
173 demoModeEnabled ? 'Disable demo mode' : 'Enable demo mode'
174 }
175 disabled={isClearingImageCache}>
176 <SettingsList.ItemIcon icon={AtomIcon} />
177 <SettingsList.ItemText>
178 {demoModeEnabled ? 'Disable demo mode' : 'Enable demo mode'}
179 </SettingsList.ItemText>
180 </SettingsList.PressableItem>
181 )}
182 </>
183 )}
184 </SettingsList.Container>
185 </Layout.Content>
186 </Layout.Screen>
187 )
188}