Skip to content

Commit 34c10ed

Browse files
committed
feat: start oobe changes and update timeout ade
1 parent 72cf3ec commit 34c10ed

10 files changed

Lines changed: 261 additions & 77 deletions

File tree

src/app/_layout.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,17 @@ export default function RootLayout() {
3535
<Stack screenOptions={{ headerShown: false, gestureEnabled: false }}>
3636
<Stack.Screen name="index" />
3737
<Stack.Screen name="splash" />
38-
<Stack.Screen name="oobe" options={{ presentation: 'modal' }} />
38+
<Stack.Screen name="oobe" />
3939
<Stack.Screen name="home" />
4040
<Stack.Screen name="show-edt" />
4141
<Stack.Screen
4242
name="show-ent"
4343
options={{ presentation: 'modal', gestureEnabled: true }}
4444
/>
45-
<Stack.Screen name="settings" />
45+
<Stack.Screen
46+
name="settings"
47+
options={{ gestureEnabled: true }}
48+
/>
4649
<Stack.Screen
4750
name="icon-config"
4851
options={{ presentation: 'modal', gestureEnabled: true }}

src/app/edt-config.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default function EDTConfigScreen() {
2525
const router = useRouter();
2626
const theme = useChoosenTheme();
2727

28-
const { adeid, setAdeid } = useApp();
28+
const { adeid, setAdeid, onboarding } = useApp();
2929
const [tempAde, setTempAde] = useState('');
3030

3131
const [mode, setMode] = useState(adeid?.includes('-VET') ? '1' : '0');
@@ -91,7 +91,8 @@ export default function EDTConfigScreen() {
9191
setAdeid(newAdeid);
9292
saveSecure('adeid', newAdeid);
9393
haptics('heavy');
94-
router.replace('/home');
94+
if (onboarding) router.back();
95+
else router.replace('/home');
9596
}
9697

9798
return (

src/app/home.tsx

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
1-
import { APP_VERSION, RELEASE_NOTES } from '@/src/constants/config';
2-
import { useChoosenTheme } from '@/src/constants/theme';
3-
import { useApp } from '@/src/context/AppContext';
4-
import { edtService } from '@/src/services/edt';
5-
import type { NextEvent } from '@/src/types';
6-
import { handleURL } from '@/src/utils/api';
7-
import { haptics } from '@/src/utils/haptics';
8-
import { NextClassWidgetInstance } from '@/src/widgets/NextClassWidget';
9-
import BottomSheet, {
10-
BottomSheetBackdrop,
11-
BottomSheetBackdropProps,
12-
BottomSheetView,
13-
} from '@gorhom/bottom-sheet';
14-
import { useRouter } from 'expo-router';
15-
import React, { useCallback, useEffect, useRef, useState } from 'react';
1+
import { useCallback, useEffect, useRef, useState } from 'react';
162
import { Platform, StyleSheet, View } from 'react-native';
3+
174
import {
185
ActivityIndicator,
196
Avatar,
7+
Badge,
208
Button,
219
Card,
2210
Chip,
@@ -26,8 +14,26 @@ import {
2614
Tooltip,
2715
TouchableRipple,
2816
} from 'react-native-paper';
17+
18+
import { useRouter } from 'expo-router';
19+
20+
import BottomSheet, {
21+
BottomSheetBackdrop,
22+
BottomSheetBackdropProps,
23+
BottomSheetView,
24+
} from '@gorhom/bottom-sheet';
2925
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
30-
import { saveAsync } from '../utils/storage';
26+
27+
28+
import { APP_VERSION, RELEASE_NOTES } from '@/src/constants/config';
29+
import { useChoosenTheme } from '@/src/constants/theme';
30+
import { useApp } from '@/src/context/AppContext';
31+
import { edtService } from '@/src/services/edt';
32+
import type { NextEvent } from '@/src/types';
33+
import { handleURL } from '@/src/utils/api';
34+
import { haptics } from '@/src/utils/haptics';
35+
import { NextClassWidgetInstance } from '@/src/widgets/NextClassWidget';
36+
import { getSecure, saveAsync } from '../utils/storage';
3137

3238
const WELCOME_MESSAGES = [
3339
'Passe une excellente journée !',
@@ -46,19 +52,28 @@ function getRandomWelcomeMessage() {
4652

4753
export default function HomeScreen() {
4854
const router = useRouter();
49-
const { adeid, setCalendar, updateModalShown, setUpdateModalShown } = useApp();
55+
const {
56+
adeid, setCalendar, setCalendarOffline,
57+
updateModalShown, setUpdateModalShown,
58+
setOnboarding
59+
} = useApp();
5060
const theme = useChoosenTheme();
5161
const insets = useSafeAreaInsets();
5262

5363
const [loading, setLoading] = useState(false);
5464
const [selectable, setSelectable] = useState(true);
65+
5566
const [nextEvent, setNextEvent] = useState<NextEvent>({
5667
summary: 'Chargement...',
5768
location: 'Chargement...',
5869
});
5970
const [nextEventLoaded, setNextEventLoaded] = useState(false);
71+
6072
const [infoTitle, setInfoTitle] = useState('Informations');
6173
const [infoSubtitle, setInfoSubtitle] = useState('');
74+
75+
const isDemo = !adeid || adeid === 'demo';
76+
6277
const [welcomeMessage] = useState(getRandomWelcomeMessage);
6378

6479
const bottomSheetInfoRef = useRef<BottomSheet>(null);
@@ -78,8 +93,13 @@ export default function HomeScreen() {
7893
);
7994

8095
useEffect(() => {
96+
setOnboarding(false);
97+
if (!isDemo) {
8198
getNextEvent('normal');
8299
if (Platform.OS === 'ios') pushWidgetTimeline();
100+
}
101+
102+
83103

84104
// check in app context if update modal has been shown, if not show it and set it to true
85105
if (!updateModalShown) {
@@ -98,6 +118,7 @@ export default function HomeScreen() {
98118
}
99119

100120
async function getNextEvent(mode: 'normal' | 'force') {
121+
if (isDemo) return;
101122
if (mode === 'force') {
102123
setNextEvent({ summary: 'Chargement...', location: 'Chargement...' });
103124
}
@@ -113,11 +134,14 @@ export default function HomeScreen() {
113134
setSelectable(false);
114135
setLoading(true);
115136

116-
const cal = await edtService.getEDT(adeid ?? 'demo');
117-
setCalendar(cal);
137+
const { events, offline } = await edtService.getEDT(adeid ?? 'demo');
138+
setCalendar(events);
139+
setCalendarOffline(offline);
118140
if (Platform.OS === 'ios') {
119141
try {
120-
NextClassWidgetInstance.updateTimeline(edtService.buildWidgetTimeline(cal));
142+
NextClassWidgetInstance.updateTimeline(
143+
edtService.buildWidgetTimeline(events)
144+
);
121145
} catch { }
122146
}
123147

@@ -128,7 +152,7 @@ export default function HomeScreen() {
128152

129153
async function pushWidgetTimeline() {
130154
try {
131-
const events = await edtService.getEDT(adeid ?? 'demo');
155+
const { events } = await edtService.getEDT(adeid ?? 'demo');
132156
const timeline = edtService.buildWidgetTimeline(events);
133157
NextClassWidgetInstance.updateTimeline(timeline);
134158
} catch {
@@ -180,17 +204,27 @@ export default function HomeScreen() {
180204
{welcomeMessage}
181205
</Text>
182206

183-
<Card style={{ marginBottom: 8 }} disabled={!selectable} onPress={getMyCal}>
184-
<Card.Title title="Prochain Cours" />
207+
<Card
208+
style={{ marginBottom: 8 }}
209+
disabled={!selectable}
210+
onPress={isDemo ? () => router.push('/edt-config') : getMyCal}
211+
>
212+
<Card.Title title={isDemo ? 'Emploi du temps' : 'Prochain Cours'} />
185213
<Card.Content>
186214
<Text variant="titleLarge" numberOfLines={1}>
187-
{nextEvent.summary}
215+
{isDemo ? 'Non configuré' : nextEvent.summary}
188216
</Text>
189217
<Text variant="bodyMedium" numberOfLines={1}>
190-
{nextEvent.location || "Salle non précisée"}
218+
{isDemo ? "Appuyez pour choisir votre emploi du temps" : (nextEvent.location || "Salle non précisée")}
191219
</Text>
192220
</Card.Content>
193221
<Card.Actions>
222+
{isDemo && (
223+
<Chip disabled={!selectable} onPress={() => router.push('/edt-config')} icon="calendar-edit">
224+
Configurer l&apos;EDT
225+
</Chip>
226+
)}
227+
{!isDemo && (
194228
<Chip
195229
style={{ marginRight: 4 }}
196230
disabled={!selectable}
@@ -199,14 +233,17 @@ export default function HomeScreen() {
199233
>
200234
Rafraîchir
201235
</Chip>
202-
{nextEvent.summary !== 'ADE Indisponible' ? (
236+
)}
237+
{!isDemo && (
238+
nextEvent.summary !== 'ADE Indisponible' ? (
203239
<Chip disabled={!selectable} onPress={getMyCal} icon="calendar">
204240
Emploi du temps
205241
</Chip>
206242
) : (
207243
<Chip disabled={!selectable} onPress={getMyCal} icon="calendar-alert">
208244
EDT (Hors-ligne)
209245
</Chip>
246+
)
210247
)}
211248
</Card.Actions>
212249
</Card>
@@ -292,4 +329,4 @@ export default function HomeScreen() {
292329
</BottomSheet>
293330
</View>
294331
);
295-
}
332+
}

src/app/oobe.tsx

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,19 @@ import { handleURL } from '@/src/utils/api';
2222
import { haptics } from '@/src/utils/haptics';
2323
import { saveSecure } from '@/src/utils/storage';
2424

25-
type Step = 'welcome' | 'edt' | 'pronote';
25+
type Step = 'welcome' | 'edt';
2626

2727
export default function OOBEScreen() {
2828
const router = useRouter();
29-
const { setAdeid } = useApp();
29+
const { adeid, setAdeid, setOnboarding, setOobeCompleted } = useApp();
3030
const theme = useChoosenTheme();
3131
const insets = useSafeAreaInsets();
32+
const [step, setStep] = useState<Step>('welcome');
33+
const edtDone = !!adeid && adeid !== 'demo';
34+
35+
useEffect(() => {
36+
setOnboarding(true);
37+
}, [setOnboarding]);
3238

3339
const rotation = useSharedValue(0);
3440
const rotateConfig = { damping: 2, stiffness: 15 };
@@ -43,14 +49,30 @@ export default function OOBEScreen() {
4349

4450
const renderNoBackdrop = useCallback(() => null, []);
4551

46-
async function handleStart() {
52+
async function handleWelcomeNext() {
4753
haptics('medium');
54+
// second passage (bouton "Relancer" des paramètres) : on n'écrase pas un EDT déjà configuré
55+
if (!edtDone) {
4856
await saveSecure('adeid', 'demo');
4957
setAdeid('demo');
50-
router.replace('/home');
58+
}
59+
setStep('edt');
60+
}
61+
62+
function configureEdt() {
63+
haptics('medium');
5164
router.push('/edt-config');
5265
}
5366

67+
function skipEdt() {
68+
haptics('light');
69+
setOobeCompleted(true);
70+
setOnboarding(false);
71+
router.replace('/home');
72+
}
73+
74+
const GREEN = '#2E7D32';
75+
5476
const bgStyle = { backgroundColor: theme.colors.background };
5577
const handleStyle = { backgroundColor: theme.colors.onBackground };
5678

@@ -70,7 +92,11 @@ export default function OOBEScreen() {
7092

7193
<View style={{ flex: 1, alignSelf: 'center', height: 'auto', marginTop: insets.top * 2 }}>
7294
<Animated.View style={animatedStyleLogo}>
73-
<Image source={require('../assets/color.png')} style={{ width: 200, height: 200 }} />
95+
<Image source={
96+
theme.dark
97+
? require('../assets/white.png')
98+
: require('../assets/color.png')
99+
} style={{ width: 200, height: 200 }} />
74100
</Animated.View>
75101
</View>
76102

@@ -81,7 +107,9 @@ export default function OOBEScreen() {
81107
handleIndicatorStyle={handleStyle}
82108
backdropComponent={renderNoBackdrop}
83109
>
84-
<BottomSheetView style={{ paddingLeft: 25, paddingRight: 25 }}>
110+
<BottomSheetView style={{ paddingLeft: 25, paddingRight: 25, paddingBottom: insets.bottom }}>
111+
{step === 'welcome' && (
112+
<>
85113
<Text style={{ textAlign: 'left', marginBottom: 8, marginTop: 8 }} variant="displayMedium">
86114
UniceNotes
87115
</Text>
@@ -98,29 +126,62 @@ export default function OOBEScreen() {
98126
<View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center' }}>
99127
<Tooltip title="Mentions légales">
100128
<IconButton
101-
style={{ marginBottom: 4 }}
102129
icon="license"
103130
mode="contained"
104131
onPress={() => handleURL('https://notes.metrixmedia.fr/credits')}
105132
/>
106133
</Tooltip>
107134
<Tooltip title="Code source">
108135
<IconButton
109-
style={{ marginBottom: 16 }}
110136
icon="source-branch"
111137
mode="contained"
112138
onPress={() => handleURL('https://github.com/UniceApps/UniceNotes')}
113139
/>
114140
</Tooltip>
115141
<Tooltip title="Paramètres">
116142
<IconButton
117-
style={{ marginBottom: insets.bottom }}
118143
icon="cog"
119144
mode="contained"
120145
onPress={() => router.push('/settings')}
121146
/>
122147
</Tooltip>
123148
</View>
149+
</>
150+
)}
151+
152+
{step === 'edt' && (
153+
<>
154+
<Text style={{ textAlign: 'left', marginBottom: 8, marginTop: 8 }} variant="displayMedium">
155+
Configuration
156+
</Text>
157+
<Text style={{ textAlign: 'left', marginBottom: 16 }} variant="titleLarge">
158+
&mdash; Emploi du temps
159+
</Text>
160+
<Text style={{ textAlign: 'left', marginBottom: 16 }} variant="titleMedium">
161+
Configurez votre emploi du temps (via ADE) pour le retrouver directement à l&apos;accueil.
162+
</Text>
163+
{edtDone ? (
164+
<Button
165+
style={{ marginBottom: 16 }}
166+
icon="check"
167+
mode="contained"
168+
buttonColor={GREEN}
169+
onPress={skipEdt}
170+
>
171+
Suivant
172+
</Button>
173+
) : (
174+
<>
175+
<Button style={{ marginBottom: 8 }} icon="calendar-edit" mode="contained" onPress={configureEdt}>
176+
Configurer
177+
</Button>
178+
<Button style={{ marginBottom: 16 }} mode="outlined" onPress={skipEdt}>
179+
Plus tard
180+
</Button>
181+
</>
182+
)}
183+
</>
184+
)}
124185
</BottomSheetView>
125186
</BottomSheet>
126187
</View>

0 commit comments

Comments
 (0)