From ece2835c2b54511e3225a45f8ca2c35ae0d78c1d Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 18:54:42 +0100 Subject: [PATCH 001/102] feat: added new route to types --- src/router/helpers/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/router/helpers/types.ts b/src/router/helpers/types.ts index ede29094a..532f99ba5 100644 --- a/src/router/helpers/types.ts +++ b/src/router/helpers/types.ts @@ -127,6 +127,7 @@ export type RouteParameters = { SettingsSubjects: undefined; SettingsExternalServices: undefined; SettingsMagic: undefined; + SettingsMultiservice: undefined; SettingsFlags: undefined; SettingsFlagsInfos: { title: string; value: any }; SettingsAddons: undefined; From c5ee85d94091b1a2e084486f70d61114ed264e93 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 19:04:09 +0100 Subject: [PATCH 002/102] feat: created new settings screen --- src/views/settings/SettingsMultiservice.tsx | 57 +++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/views/settings/SettingsMultiservice.tsx diff --git a/src/views/settings/SettingsMultiservice.tsx b/src/views/settings/SettingsMultiservice.tsx new file mode 100644 index 000000000..7edf1a934 --- /dev/null +++ b/src/views/settings/SettingsMultiservice.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { Text, ScrollView, View, StyleSheet, Switch } from "react-native"; +import { useTheme } from "@react-navigation/native"; +import type { Screen } from "@/router/helpers/types"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import important_json from "@/utils/magic/regex/important.json"; // Ensure this file contains valid regex patterns +import MagicContainerCard from "@/components/Settings/MagicContainerCard"; +import { NativeIcon, NativeIconGradient, NativeItem, NativeList, NativeListHeader, NativeText } from "@/components/Global/NativeComponents"; +import { PlugZap } from "lucide-react-native"; +import { useCurrentAccount } from "@/stores/account"; + +const SettingsMultiservice: Screen<"SettingsMultiservice"> = ({ navigation }) => { + const theme = useTheme(); + const { colors } = theme; + const insets = useSafeAreaInsets(); + const account = useCurrentAccount(store => store.account); + const mutateProperty = useCurrentAccount(store => store.mutateProperty); + + return ( + + {/**/} + + + + mutateProperty("personalization", { MagicNews: value })} + /> + } + leading={ + } + colors={["#04ACDC", "#6FE3CD"]} + /> + } + > + + Multiservice + + + Connecte plusieurs services différents en un seul environnement virtuel, en associant chaque fonctionnalité à un service connecté. + + + + + ); +}; + + + +export default SettingsMultiservice; From 653f00eb1bebb1244fa00727e148bf3bb5b25078 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 19:04:41 +0100 Subject: [PATCH 003/102] feat: created new route --- src/router/screens/settings/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/router/screens/settings/index.ts b/src/router/screens/settings/index.ts index 68a83b5cf..3be2b45bf 100644 --- a/src/router/screens/settings/index.ts +++ b/src/router/screens/settings/index.ts @@ -27,6 +27,7 @@ import IzlyActivation from "@/views/settings/ExternalAccount/IzlyActivation"; import TurboselfAccountSelector from "@/views/settings/ExternalAccount/TurboselfAccountSelector"; import SettingsApparence from "@/views/settings/SettingsApparence"; import ExternalAliseLogin from "@/views/settings/ExternalAccount/Alise"; +import SettingsMultiservice from "@/views/settings/SettingsMultiservice"; const settingsScreens = [ createScreen("Settings", Settings, { @@ -63,6 +64,9 @@ const settingsScreens = [ createScreen("SettingsMagic", SettingsMagic, { headerTitle: "Papillon Magic", }), + createScreen("SettingsMultiservice", SettingsMultiservice, { + headerTitle: "Multiservice", + }), createScreen("SettingsAddons", SettingsAddons, { headerTitle: "Extensions", }), From bdb836fb78f03ad1cc1d4fa306b4d3dd8f660340 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 19:04:57 +0100 Subject: [PATCH 004/102] feat: added new settings tab --- src/views/settings/Settings.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/views/settings/Settings.tsx b/src/views/settings/Settings.tsx index 8d46498b0..3e3c7049a 100644 --- a/src/views/settings/Settings.tsx +++ b/src/views/settings/Settings.tsx @@ -31,7 +31,8 @@ import { Sparkles, SunMoon, SwatchBook, WandSparkles, - X + X, + Blocks } from "lucide-react-native"; import { NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText } from "@/components/Global/NativeComponents"; @@ -196,6 +197,13 @@ const Settings: Screen<"Settings"> = ({ route, navigation }) => { description: "Fonctionnalités intelligentes", onPress: () => navigation.navigate("SettingsMagic"), }, + { + icon: , + color: "#cb7712", + label: "Multiservice (Bêta)", + description: "Connecte plusieurs services en un seul espace de travail", + onPress: () => navigation.navigate("SettingsMultiservice"), + }, ], }, { From cabacd9453be2fb0adb8f7293fe9e8b2491b11ad Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 19:08:25 +0100 Subject: [PATCH 005/102] fix: renamed to "MultiService" --- src/router/helpers/types.ts | 2 +- src/router/screens/settings/index.ts | 4 ++-- ...ttingsMultiservice.tsx => SettingsMultiService.tsx} | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) rename src/views/settings/{SettingsMultiservice.tsx => SettingsMultiService.tsx} (84%) diff --git a/src/router/helpers/types.ts b/src/router/helpers/types.ts index 532f99ba5..c9dd79d6d 100644 --- a/src/router/helpers/types.ts +++ b/src/router/helpers/types.ts @@ -127,7 +127,7 @@ export type RouteParameters = { SettingsSubjects: undefined; SettingsExternalServices: undefined; SettingsMagic: undefined; - SettingsMultiservice: undefined; + SettingsMultiService: undefined; SettingsFlags: undefined; SettingsFlagsInfos: { title: string; value: any }; SettingsAddons: undefined; diff --git a/src/router/screens/settings/index.ts b/src/router/screens/settings/index.ts index 3be2b45bf..10f0e4a3b 100644 --- a/src/router/screens/settings/index.ts +++ b/src/router/screens/settings/index.ts @@ -27,7 +27,7 @@ import IzlyActivation from "@/views/settings/ExternalAccount/IzlyActivation"; import TurboselfAccountSelector from "@/views/settings/ExternalAccount/TurboselfAccountSelector"; import SettingsApparence from "@/views/settings/SettingsApparence"; import ExternalAliseLogin from "@/views/settings/ExternalAccount/Alise"; -import SettingsMultiservice from "@/views/settings/SettingsMultiservice"; +import SettingsMultiService from "@/views/settings/SettingsMultiService"; const settingsScreens = [ createScreen("Settings", Settings, { @@ -64,7 +64,7 @@ const settingsScreens = [ createScreen("SettingsMagic", SettingsMagic, { headerTitle: "Papillon Magic", }), - createScreen("SettingsMultiservice", SettingsMultiservice, { + createScreen("SettingsMultiService", SettingsMultiService, { headerTitle: "Multiservice", }), createScreen("SettingsAddons", SettingsAddons, { diff --git a/src/views/settings/SettingsMultiservice.tsx b/src/views/settings/SettingsMultiService.tsx similarity index 84% rename from src/views/settings/SettingsMultiservice.tsx rename to src/views/settings/SettingsMultiService.tsx index 7edf1a934..ab594b56f 100644 --- a/src/views/settings/SettingsMultiservice.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -5,11 +5,11 @@ import type { Screen } from "@/router/helpers/types"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import important_json from "@/utils/magic/regex/important.json"; // Ensure this file contains valid regex patterns import MagicContainerCard from "@/components/Settings/MagicContainerCard"; -import { NativeIcon, NativeIconGradient, NativeItem, NativeList, NativeListHeader, NativeText } from "@/components/Global/NativeComponents"; +import { NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText } from "@/components/Global/NativeComponents"; import { PlugZap } from "lucide-react-native"; import { useCurrentAccount } from "@/stores/account"; -const SettingsMultiservice: Screen<"SettingsMultiservice"> = ({ navigation }) => { +const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => { const theme = useTheme(); const { colors } = theme; const insets = useSafeAreaInsets(); @@ -34,9 +34,9 @@ const SettingsMultiservice: Screen<"SettingsMultiservice"> = ({ navigation }) => /> } leading={ - } - colors={["#04ACDC", "#6FE3CD"]} + color="#cb7712" /> } > @@ -54,4 +54,4 @@ const SettingsMultiservice: Screen<"SettingsMultiservice"> = ({ navigation }) => -export default SettingsMultiservice; +export default SettingsMultiService; From 7a7a5934c75792797b540ad6454081cfe5ab5e16 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 19:08:44 +0100 Subject: [PATCH 006/102] fix: renamed to "MultiService" --- src/views/settings/Settings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/settings/Settings.tsx b/src/views/settings/Settings.tsx index 3e3c7049a..36d22ad72 100644 --- a/src/views/settings/Settings.tsx +++ b/src/views/settings/Settings.tsx @@ -202,7 +202,7 @@ const Settings: Screen<"Settings"> = ({ route, navigation }) => { color: "#cb7712", label: "Multiservice (Bêta)", description: "Connecte plusieurs services en un seul espace de travail", - onPress: () => navigation.navigate("SettingsMultiservice"), + onPress: () => navigation.navigate("SettingsMultiService"), }, ], }, From 257440b1d1af84963a2fd696ab422a9d45fb855c Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 19:25:00 +0100 Subject: [PATCH 007/102] feat: added decorative card --- src/components/News/Beta.tsx | 6 +- .../Settings/MultiServiceContainerCard.tsx | 62 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 src/components/Settings/MultiServiceContainerCard.tsx diff --git a/src/components/News/Beta.tsx b/src/components/News/Beta.tsx index da305cdb5..8fc1d5068 100644 --- a/src/components/News/Beta.tsx +++ b/src/components/News/Beta.tsx @@ -4,10 +4,10 @@ import { NativeText } from "../Global/NativeComponents"; import { LinearGradient } from "expo-linear-gradient"; -const BetaIndicator = () => { +const BetaIndicator: React.FC<{ colors?: string[] }> = (props) => { return ( { ); }; -export default BetaIndicator; \ No newline at end of file +export default BetaIndicator; diff --git a/src/components/Settings/MultiServiceContainerCard.tsx b/src/components/Settings/MultiServiceContainerCard.tsx new file mode 100644 index 000000000..38ac18c0d --- /dev/null +++ b/src/components/Settings/MultiServiceContainerCard.tsx @@ -0,0 +1,62 @@ +import React, { useState, useEffect } from "react"; +import type { Screen } from "@/router/helpers/types"; + +import { ScrollView, Image, Text, View } from "react-native"; +import LottieView from "lottie-react-native"; +import { NativeItem, NativeList, NativeText } from "../Global/NativeComponents"; +import { LinearGradient } from "expo-linear-gradient"; +import BetaIndicator from "../News/Beta"; + +const MultiServiceContainerCard = ({ theme }: { theme: any }) => { + const { colors } = theme; + const animationref = React.useRef(null); + + useEffect(() => { + animationref.current?.play(); + }, []); + + return ( + + + + Maybe une image ici, là j'attend l'avis des #designers + {/**/} + + + + + + Activer le multi service + + + + + Rassemble tes services scolaires en un espace virtuel unique, géré par Papillon. + + + + ); +}; + +export default MultiServiceContainerCard; From e52979dffdf1b37be7ecca83cfa3f1406d060dd8 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 22:06:37 +0100 Subject: [PATCH 008/102] feat: added store types --- src/stores/multiService/types.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/stores/multiService/types.ts diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts new file mode 100644 index 000000000..97218376b --- /dev/null +++ b/src/stores/multiService/types.ts @@ -0,0 +1,26 @@ +import {PapillonMultiServiceSpace, PrimaryAccount} from "@/stores/account/types"; + +export enum MultiServiceFeature { + Grades = "grades", + Timetable = "timetable", + Homeworks = "homeworks", + Attendance = "attendance", + News = "news" +} + +export interface MultiServiceSpace { + accountLocalID: string + name: string + featuresServices: { + [key in keyof typeof MultiServiceFeature]: PrimaryAccount | null + } +} + +export interface MultiServiceStore { + enabled?: boolean + spaces: MultiServiceSpace[] + create: (space: MultiServiceSpace, linkAccount: PapillonMultiServiceSpace) => void + remove: (localID: string) => void + update: (localID: string, key: T, value: A[T]) => void + getFeatureAccount: (feature: keyof typeof MultiServiceFeature, spaceLocalID: string) => PrimaryAccount | null | undefined +} From 46da1586eb7c3dd204c922fca0e2222d622aa165 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 22:06:46 +0100 Subject: [PATCH 009/102] feat: added store definition --- src/stores/multiService/index.ts | 110 +++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/stores/multiService/index.ts diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts new file mode 100644 index 000000000..eb1917ec0 --- /dev/null +++ b/src/stores/multiService/index.ts @@ -0,0 +1,110 @@ +import AsyncStorage from "@react-native-async-storage/async-storage"; +import { createJSONStorage, persist } from "zustand/middleware"; +import { create } from "zustand"; +import pronote from "pawnote"; + +import { + Account, + PrimaryAccount +} from "@/stores/account/types"; +import { reload } from "@/services/reload-account"; +import { useTimetableStore } from "../timetable"; +import { useHomeworkStore } from "../homework"; +import { useGradesStore } from "../grades"; +import { useNewsStore } from "../news"; +import { useAttendanceStore } from "../attendance"; +import { log } from "@/utils/logger/logger"; +import {MultiServiceSpace, MultiServiceStore} from "@/stores/multiService/types"; +import {useAccounts} from "@/stores/account"; + + +/** + * Store for the MultiService settings & states. + * Persisted, as we want to keep the virtual spaces between app restarts. + */ +export const useMultiService = create()( + persist( + (set, get) => ({ + // When opening the app for the first time, it's null. + enabled: undefined as (boolean | undefined), + + spaces: >[], + + // When creating, we don't want the "instance" to be stored. + create: (space, linkAccount) => { + log(`creating a virtual MultiService space with account id ${linkAccount.localID} (${space.name})`, "multiService:create"); + + set((state) => ({ + spaces: [...state.spaces, space] + })); + + const accountStore = useAccounts(); + accountStore.create(linkAccount); + + log(`stored ${space.name}, and created associated account ${linkAccount.localID}`, "multiService:create"); + }, + + remove: (localID) => { + log(`removing virtual MultiService space ${localID}`, "multiService:remove"); + + set((state) => ({ + spaces: state.spaces.filter( + (space) => space.accountLocalID !== localID + ) + })); + + const accountStore = useAccounts(); + accountStore.remove(localID); + + log(`removed ${localID}`, "multiService:remove"); + }, + + toggleEnabledState: () => { + set((state) => ({ + enabled: !state.enabled + })); + }, + + /** + * Mutates a given property for a given space + * and return the updated space. + */ + update: (localID, key, value) => { + // Find the account to update in the storage. + const space = get().spaces.find((space) => space.accountLocalID === localID); + if (!space) return null; + + let spaceMutated: MultiServiceSpace; + + // Mutate only featureServices and name properties. + if (key in ["featureServices", "name"]) { + spaceMutated = { + ...space, + [key]: value + }; + } + + // Save the update in the store and storage. + set((state) => ({ + spaces: state.spaces.map((space) => + space.accountLocalID === localID + ? spaceMutated + : space + ) + })); + }, + + getFeatureAccount: (feature, spaceLocalID) => { + // Find the account to update in the storage. + const space = get().spaces.find((space) => space.accountLocalID === spaceLocalID); + if (!space) return null; + + return space.featuresServices[feature]; + }, + }), + { + name: "multiservice-storage", + storage: createJSONStorage(() => AsyncStorage) + } + ) +); From 4d579d1fd5119dac5cc03ef26b00b82daf7bfdf8 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 22:07:21 +0100 Subject: [PATCH 010/102] feat: added new account type for multiservice virtual space --- src/stores/account/types.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index ebce54985..790ddee95 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -105,7 +105,8 @@ export enum AccountService { Onisep, Multi, Izly, - Alise + Alise, + PapillonMultiService } /** @@ -240,12 +241,19 @@ export interface IzlyAccount extends BaseExternalAccount { } } +export interface PapillonMultiServiceSpace extends BaseAccount { + service: AccountService.PapillonMultiService + instance: null + authentication: null +} + export type PrimaryAccount = ( | PronoteAccount | EcoleDirecteAccount | SkolengoAccount | MultiAccount | LocalAccount + | PapillonMultiServiceSpace ); export type ExternalAccount = ( | TurboselfAccount From d64299c7704c43de2fac58ce7b3aa5395ba3dff4 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 22:12:58 +0100 Subject: [PATCH 011/102] fix: types for `SettingsExternalServices.tsx` --- src/views/settings/SettingsExternalServices.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/views/settings/SettingsExternalServices.tsx b/src/views/settings/SettingsExternalServices.tsx index 91e66cb07..d4fe6cd39 100644 --- a/src/views/settings/SettingsExternalServices.tsx +++ b/src/views/settings/SettingsExternalServices.tsx @@ -26,7 +26,8 @@ const serviceConfig = { [AccountService.Parcoursup]: { icon: BookmarkMinus, name: "Parcoursup" }, [AccountService.Onisep]: { icon: Compass, name: "Onisep" }, [AccountService.Local]: { icon: GraduationCap, name: "Local" }, - [AccountService.Multi]: { icon: GraduationCap, name: "Polytechnique Hauts-de-France" } + [AccountService.Multi]: { icon: GraduationCap, name: "Polytechnique Hauts-de-France" }, + [AccountService.PapillonMultiService]: { icon: GraduationCap, name: "Environnement virtuel Papillon" } }; const SettingsExternalServices: Screen<"SettingsExternalServices"> = ({ From e02f04a5d38b1c6e5b6115ba243af1296f3cf97d Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 22:13:17 +0100 Subject: [PATCH 012/102] fix: account types for new PapillonMultiService account type --- src/stores/account/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 790ddee95..97366ac01 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -245,6 +245,7 @@ export interface PapillonMultiServiceSpace extends BaseAccount { service: AccountService.PapillonMultiService instance: null authentication: null + identityProvider: undefined } export type PrimaryAccount = ( From 0302644d4adac2170d8e3920ff9c83a266d5139c Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 22:15:43 +0100 Subject: [PATCH 013/102] fix: missing `toggleEnabledState` type definition --- src/stores/multiService/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index 97218376b..cc3a7e2b3 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -22,5 +22,6 @@ export interface MultiServiceStore { create: (space: MultiServiceSpace, linkAccount: PapillonMultiServiceSpace) => void remove: (localID: string) => void update: (localID: string, key: T, value: A[T]) => void + toggleEnabledState: () => void getFeatureAccount: (feature: keyof typeof MultiServiceFeature, spaceLocalID: string) => PrimaryAccount | null | undefined } From 25aa1406a6abb21d4bd78a33a866d5ce4942ea89 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 22:17:45 +0100 Subject: [PATCH 014/102] fix: implemented simple enable functionnality --- src/views/settings/SettingsMultiService.tsx | 24 ++++++++++----------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index ab594b56f..90e1fe050 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -1,20 +1,18 @@ import React from "react"; -import { Text, ScrollView, View, StyleSheet, Switch } from "react-native"; +import { ScrollView, Switch } from "react-native"; import { useTheme } from "@react-navigation/native"; import type { Screen } from "@/router/helpers/types"; -import { useSafeAreaInsets } from "react-native-safe-area-context"; -import important_json from "@/utils/magic/regex/important.json"; // Ensure this file contains valid regex patterns -import MagicContainerCard from "@/components/Settings/MagicContainerCard"; +import MultiServiceContainerCard from "@/components/Settings/MultiServiceContainerCard"; import { NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText } from "@/components/Global/NativeComponents"; import { PlugZap } from "lucide-react-native"; -import { useCurrentAccount } from "@/stores/account"; +import {useAccounts} from "@/stores/account"; +import {useMultiService} from "@/stores/multiService"; const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => { const theme = useTheme(); - const { colors } = theme; - const insets = useSafeAreaInsets(); - const account = useCurrentAccount(store => store.account); - const mutateProperty = useCurrentAccount(store => store.mutateProperty); + const toggleMultiService = useMultiService(store => store.toggleEnabledState); + const multiServiceEnabled = useMultiService(store => store.enabled); + const accounts = useAccounts(); return ( = ({ navigation }) => paddingHorizontal: 15, }} > - {/**/} + mutateProperty("personalization", { MagicNews: value })} + value={multiServiceEnabled ?? false} + onValueChange={() => toggleMultiService()} /> } leading={ @@ -44,7 +42,7 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => Multiservice - Connecte plusieurs services différents en un seul environnement virtuel, en associant chaque fonctionnalité à un service connecté. + Activer le multiservice te permet de créer ton premier espace virtuel. From bb753b8c0f3370a4e394948105249f4a5e2eab61 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Wed, 1 Jan 2025 23:20:33 +0100 Subject: [PATCH 015/102] fix: added image property --- src/stores/multiService/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index cc3a7e2b3..bd9e87fc4 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -11,6 +11,7 @@ export enum MultiServiceFeature { export interface MultiServiceSpace { accountLocalID: string name: string + image: string featuresServices: { [key in keyof typeof MultiServiceFeature]: PrimaryAccount | null } From 91c55606fb3cfa9f0d2b632bb482aea28b6929a0 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 00:06:04 +0100 Subject: [PATCH 016/102] fix: modified types and resolved hook breaking code --- src/stores/multiService/index.ts | 17 +---------------- src/stores/multiService/types.ts | 2 +- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index eb1917ec0..8f1786c6a 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -1,18 +1,6 @@ import AsyncStorage from "@react-native-async-storage/async-storage"; import { createJSONStorage, persist } from "zustand/middleware"; import { create } from "zustand"; -import pronote from "pawnote"; - -import { - Account, - PrimaryAccount -} from "@/stores/account/types"; -import { reload } from "@/services/reload-account"; -import { useTimetableStore } from "../timetable"; -import { useHomeworkStore } from "../homework"; -import { useGradesStore } from "../grades"; -import { useNewsStore } from "../news"; -import { useAttendanceStore } from "../attendance"; import { log } from "@/utils/logger/logger"; import {MultiServiceSpace, MultiServiceStore} from "@/stores/multiService/types"; import {useAccounts} from "@/stores/account"; @@ -38,10 +26,7 @@ export const useMultiService = create()( spaces: [...state.spaces, space] })); - const accountStore = useAccounts(); - accountStore.create(linkAccount); - - log(`stored ${space.name}, and created associated account ${linkAccount.localID}`, "multiService:create"); + log(`stored ${space.name}, with account ${linkAccount.localID}`, "multiService:create"); }, remove: (localID) => { diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index bd9e87fc4..32245616d 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -11,7 +11,7 @@ export enum MultiServiceFeature { export interface MultiServiceSpace { accountLocalID: string name: string - image: string + image?: string featuresServices: { [key in keyof typeof MultiServiceFeature]: PrimaryAccount | null } From 27446555af684fc253f21038884020728e58dc5f Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 00:06:19 +0100 Subject: [PATCH 017/102] feat: PoC settings page to create spaces --- src/views/settings/SettingsMultiService.tsx | 242 +++++++++++++++++++- 1 file changed, 236 insertions(+), 6 deletions(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 90e1fe050..584c36573 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -1,23 +1,105 @@ -import React from "react"; -import { ScrollView, Switch } from "react-native"; -import { useTheme } from "@react-navigation/native"; -import type { Screen } from "@/router/helpers/types"; +import React, {useRef, useState} from "react"; +import {Alert, Image, ScrollView, Switch, TextInput, View} from "react-native"; +import {useTheme} from "@react-navigation/native"; +import type {Screen} from "@/router/helpers/types"; import MultiServiceContainerCard from "@/components/Settings/MultiServiceContainerCard"; -import { NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText } from "@/components/Global/NativeComponents"; -import { PlugZap } from "lucide-react-native"; +import {NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; +import {ImageIcon, PlugZap, Plus, Type} from "lucide-react-native"; import {useAccounts} from "@/stores/account"; import {useMultiService} from "@/stores/multiService"; +import BottomSheet from "@/components/Modals/PapillonBottomSheet"; +import * as ImagePicker from "expo-image-picker"; +import {animPapillon} from "@/utils/ui/animations"; +import {ZoomIn, ZoomOut} from "react-native-reanimated"; +import PapillonSpinner from "@/components/Global/PapillonSpinner"; +import {MultiServiceSpace} from "@/stores/multiService/types"; +import {AccountService, PapillonMultiServiceSpace} from "@/stores/account/types"; +import uuid from "@/utils/uuid-v4"; +import {defaultProfilePicture} from "@/utils/ui/default-profile-picture"; const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => { const theme = useTheme(); const toggleMultiService = useMultiService(store => store.toggleEnabledState); const multiServiceEnabled = useMultiService(store => store.enabled); + const multiServiceSpaces = useMultiService(store => store.spaces); + const createMultiServiceSpace = useMultiService(store => store.create); const accounts = useAccounts(); + const [spaceCreationSheetOpened, setSpaceCreationSheetOpened] = useState(false); + const [spaceName, setSpaceName] = useState(""); + const spaceNameRef = useRef(null); + + const [loadingImage, setLoadingImage] = useState(false); + const [selectedImage, setSelectedImage] = useState(null); + const selectPicture = async () => { + setLoadingImage(true); + + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [1, 1], + quality: 1, + base64: true, + }); + + if (!result.canceled) { + const img = "data:image/jpeg;base64," + result.assets[0].base64; + setSelectedImage(img); + } + + setLoadingImage(false); + }; + + const [loadingCreation, setLoading] = useState(false); + const createSpace = () => { + setLoading(true); + if (spaceName == "") { + Alert.alert("Aucun titre défini", "Vous devez définir un titre à l'environnement multi service pour pouvoir le créer."); + setLoading(false); + return; + } + + const localID = uuid(); + + const linkedAccount: PapillonMultiServiceSpace = { + isExternal: false, + linkedExternalLocalIDs: [], + authentication: null, + identity: {}, + identityProvider: undefined, + instance: null, + localID: localID, + name: spaceName, + personalization: {}, + service: AccountService.PapillonMultiService, + studentName: { // TODO + first: "", last: "" + } + }; + + const space: MultiServiceSpace = { + accountLocalID: localID, + featuresServices: { + Grades: null, + Timetable: null, + Homeworks: null, + Attendance: null, + News: null + }, + name: spaceName + }; + createMultiServiceSpace(space, linkedAccount); + accounts.create(linkedAccount); + setSpaceCreationSheetOpened(false); + setLoading(false); + setSelectedImage(null); + setSpaceName(""); + }; return ( @@ -46,6 +128,154 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => + + {multiServiceEnabled && ( + <> + + + {multiServiceSpaces.map(space => ( + + } + > + + {space.name} + + + ))} + setSpaceCreationSheetOpened(true)} + icon={} + > + + Nouvel espace + + + Créer un nouvel environnement multi service + + + + opened} opened={spaceCreationSheetOpened} contentContainerStyle={{ paddingHorizontal: 16 }}> + + + + + spaceNameRef.current?.focus()} + chevron={false} + icon={} + > + + Titre de l'espace + + + + selectPicture()} + icon={loadingImage ? : } + trailing={selectedImage && } + > + + Image + + + Définir une image + + + + + + + + + createSpace()} + trailing={loadingCreation && } + > + + Créer l'espace + + + setSpaceCreationSheetOpened(false)} + > + + Annuler + + + + + + + + )} ); }; From 24fa06dd3842145c905e91e08cf9b66862c6ba0f Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 00:07:56 +0100 Subject: [PATCH 018/102] fix: setting image --- src/views/settings/SettingsMultiService.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 584c36573..4eeadf3f9 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -86,7 +86,8 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => Attendance: null, News: null }, - name: spaceName + name: spaceName, + image: selectedImage || undefined }; createMultiServiceSpace(space, linkedAccount); accounts.create(linkedAccount); From 60001235ffbd52c35247379f4b46c91432d60f93 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 00:15:24 +0100 Subject: [PATCH 019/102] fix: added identity provider name to MultiServiceSpace (to show space title in account selection) --- src/stores/account/types.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 97366ac01..6a44ec53e 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -245,7 +245,9 @@ export interface PapillonMultiServiceSpace extends BaseAccount { service: AccountService.PapillonMultiService instance: null authentication: null - identityProvider: undefined + identityProvider: { + name: string + } } export type PrimaryAccount = ( From 641679b678b0f5bfbc554a52e622ca8d1a5e4298 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 00:15:50 +0100 Subject: [PATCH 020/102] fix: enhanced PoC with customization... --- src/views/settings/SettingsMultiService.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 4eeadf3f9..7c7f3ec67 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -66,14 +66,19 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => linkedExternalLocalIDs: [], authentication: null, identity: {}, - identityProvider: undefined, + identityProvider: { + name: "Environnement multiservice Papillon" + }, instance: null, localID: localID, name: spaceName, - personalization: {}, + personalization: { + profilePictureB64: selectedImage || undefined + }, service: AccountService.PapillonMultiService, studentName: { // TODO - first: "", last: "" + first: spaceName, + last: "" } }; From 50ecbf7eb01b5ab48c385e239b7d0d42709f1d77 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 00:18:21 +0100 Subject: [PATCH 021/102] fix: removed breaking hooks code --- src/stores/multiService/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index 8f1786c6a..e092b7e92 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -38,9 +38,6 @@ export const useMultiService = create()( ) })); - const accountStore = useAccounts(); - accountStore.remove(localID); - log(`removed ${localID}`, "multiService:remove"); }, From 3f5970f21fe381e22e159efb3afe48de9d5edcde Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 00:26:23 +0100 Subject: [PATCH 022/102] feat: deleting spaces --- src/views/settings/SettingsMultiService.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 7c7f3ec67..46c581f0d 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -4,7 +4,7 @@ import {useTheme} from "@react-navigation/native"; import type {Screen} from "@/router/helpers/types"; import MultiServiceContainerCard from "@/components/Settings/MultiServiceContainerCard"; import {NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; -import {ImageIcon, PlugZap, Plus, Type} from "lucide-react-native"; +import {ImageIcon, PlugZap, Plus, Type, Trash2} from "lucide-react-native"; import {useAccounts} from "@/stores/account"; import {useMultiService} from "@/stores/multiService"; import BottomSheet from "@/components/Modals/PapillonBottomSheet"; @@ -23,6 +23,7 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => const multiServiceEnabled = useMultiService(store => store.enabled); const multiServiceSpaces = useMultiService(store => store.spaces); const createMultiServiceSpace = useMultiService(store => store.create); + const deleteMultiServiceSpace = useMultiService(store => store.remove); const accounts = useAccounts(); const [spaceCreationSheetOpened, setSpaceCreationSheetOpened] = useState(false); @@ -154,6 +155,15 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => }} /> } + trailing={ + { + accounts.remove(space.accountLocalID); + deleteMultiServiceSpace(space.accountLocalID); + }} + color="#CF0029" + /> + } > {space.name} From 84750218f1d78f57702fde0eb2d72f7248972256 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 11:01:09 +0100 Subject: [PATCH 023/102] feat: added asset for multiservice --- assets/images/multiservice.png | Bin 0 -> 8065 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/images/multiservice.png diff --git a/assets/images/multiservice.png b/assets/images/multiservice.png new file mode 100644 index 0000000000000000000000000000000000000000..c15330b5019ca37e7c527fc291aee2f39b13e7db GIT binary patch literal 8065 zcmd^k`9IWO^#7e$B=hQ3W3RIa0s?}H{V$?eF@7fwG<70NArX|7k?v%{3ZX)^WB zitp8Vc^E-1eER$uJLHT4y52H^rh?Ip{}A;u<2_XePFCMh*!GF~B2Qc0&&rZ!-O^>1 zr;!K1~?|nDUqC zLI>pTX=Af412_bil7wyNu~FUQRIzb405)b>^UIsR(?!D6OQRUXakbeY6cn* zcJZ5{A(0Y`_yH2_k{3LIZuthXc8~z&1D$Mf4GoU%;WstOqA5wx(z*hwV0Q8R122Oe z|91@Hpn*P@8X_-Nlc!QrQoj3fhG#a&ek}5zZ#~10-sqJn_F=de{d66&;BFyjC726a zP%#P+mz(p`L!Ue=3({n{9G`(l4P+{!5wi{HSMo}L3-91plobpP^18^{b=$RsODQb8F$_X{Y?+$#{{6Y24V%d{-O?Y;YrlbX1u>y|9T9t zzZI8T>`mMgLTKga0?IA9l4KU+^?#wo(}D9&d5dH#Gi+C3RAj>`D`{_Nqaoy%;1X@i z-jV>62V9smJUrYk>%)|-X!-m2>i!%w(E83F+D6HBa^|3=K-!(|O$nPOu5x5U?PzfB z*p^)7JHb8{uTROrgH?u0Ab=bSApp ztJqLB*bk5LSj_L+8duJ2`ye8bI9~H~^CzjQnbTso{(kjpEmOL!7_QUorR<|Dmz*B~ zRk+sMtAnb6kZ3&tIh4)6m=_0#RIm*YEwVPuKXz``i?(IL>a#2~!Vv?pu4mIxs!)^W zYe|~j6_xAN{LCk}c)^v2_O4F{r=wof6RTm6w_XVh9vm(X4*u}%$QX5ll6V<3`>i_P zf6z*gg4;d}c;@`f_FBw<+K|2}@L)jou6|R{!lVA4&}Y95tX)HSI?zdT0I3S8cM}rC zDt15TJx1SJy>-P^?FP_U>``Gqtu!Dyq=V!Ch{>M9*(*1trJ8J+}_+Q>(dZ(SB! z+G^}e7b1eC?~mhoX54zKnP5tUhvEufU!SDWa1|#`Crgwv9^~@+L|&`EIxcI;IE!kT z%V|2bMS7-%<0)~(%tdNU1KBF_^~)R_PbQ9h*Do)5Ye=8RzIeK@sagUsH?SDzMR=_s zcm%OWm(B}Z36TLsC+CXL6S|e82#HyYWYJI?xgZ0FHY^5PG}J_b;~{z~aGl*CZtRt$ z=D@Q*M&WmxLZUDhV+$0FT`8#Cg#z{&yb?z!IG#>E4FMakiHwR^A>DM@v`4?sADpRNK~ zkFyvA2sMUyK_SGCpesBb2m=&pI=K|Gs;oy^8`a_YHipHS|BHXFZnz zrn!<#CfTm(-+|3C1^?=Hk-5%B1YrN>)Rsd@0(PI(H)ZwdsTNoHjz6KEFb%PLL#)8! z=TD`yC3U0~Vi@*vBQ?s@CuzZ^rRz$IMqN^ha$Lf4R=XFvMgwWR{x2$;&@>Plt#rfL z$vXYWP5y8ynf_{e+uphL?Wo*22&{#G;yln3D|7wf!-rj&5DP-1qid9&_+`tAc5=W; znz_QnG&Xv<<~`5vg*S2oo}>X)rvon-+KZyy_^qJwC)akVbDbv%Fpn_u6{vw<_Q+LT zZr}O`BU)jot=-MNHeDlLTe_~g$JOm7UU1wEFvUoYitIm`m$zZMOqT16CBWQr^<>NR zB<*v|>Q8&~7DE;@I|x|ec3seQKf{=i3ls6Fv8?$in^8K|5>oFTJ8*>~O2}(2a{{9N zak_3MFF3ysFflK_u8W9{UhT=5ZVl7T=9QMcH20G&a;#1aW^5aIJs|Jb)N-w%QP6(uD#bB1zDS0};E;f+p2U$D zPlxWMBKEpz4v{K(aWL%8PshvzFFyxqp;ceIck{gNFy|2e+!_q+b#vA7Gh(_5@yI#R zssH2qd*d3Hfo$OifBn$sdD1lA@E&)nibBG4$;Wc@7oK`nom;HB>&72`+;ewst5|6L z#Kc6JCd?}_GZ!kY;zdV1@kl(Q_6M=Ny#I_@=PgOT0gC?*+^*6dozJ9icGRmdCnu=GZEj6om953C;uQ0;UR_rDzebGa0{yL^O@6{h` z;?A(VwAxh%`AkPQympm&UA%{4IKPm}9&Ctq^^=enoN_?0#Di#8J4fkh^|;qFPA+mKH$HFM;6Aqd)G_NnD3Iz<|ay_6vI6VF(#J5(m zK9;YJ1n;%Tlq=~DjXA5@BR|!1S@BFwM8bL!Kn^(uwrrLc^uC12da6&T5-{TxWL-P4 zVbZeyf^22udx`;8_*7CD`^ZSnqP|*^&9>vt{ya4}^=|Bi*vpqM;~5?#ASq-?3I#2O znSPV?-h$t!tZ)^d4gOIi4@Mev;vdzWoUXW9&i85=mpn4UrhafI`?vr-9i)97(!G*1 zaJMym-R6oTta<|$@e>{GLgM`x0`DfY6jzOBVI@0dChtD4TjUX0z_wFXPKWq;T3;P?Xcps+Pm)z+81Tj;&QAT`d zu7Y7IOHqD6X(uFwpHDrLSx&9LR6A3BoobvJA7sTy4z7-+MlgORP0tJ;4rKq7v`9jy znQ;9w-!_pYgxr6_m4Dz?rT+fES|6}wI5!>IAoEreS*;+sy9pi{K8KLfEGo!;US}VE zy49;LxnYq&lY#rmP!)uoCaXRCKYF0>X|=kIYrq

`j_*BWL;SqrYKT9+DN_Zf}{2 znwjhP6^S0-2R5#Qv(fy>OOJfBXwMzMqur=Ce{33J_ook{kl+%MqO*_i$)atoGY-XJ zVCIC!RKF(7%s<*xwjqlo%AwG_y;mbw{PUv%e04&>Y--Gb^?{`Dh9j)k`u7lM;_nH9 z=||O>vfi=Fy!>kYcWz{lz?m0bfRDzgn^YxI^YE$VDh>@}QomgtC`RnD(NQmO#uec4 zk&a6Xy)XY_k)5uvv+!wIc~{3S;nv06Tw4Jge_UHi;T{wot` z4fGEDQ~!bIw-5a`YaD<3IH=x@vTrCS#`?%SQp^t@|0+=;UZ_7j?)Fngaw`c~ns2u{ zftZw%dWO`ZwAC$N_~o6zidK&%d|WQEv&#?1eFk<|dpm4oakZqpXu`c|A~yB&vJ-a1 zkMz7q4}_+pyV9FR4^NNZay)hEq4+HOOoq!A40FZiy~|r)OufQ)y?V>4&+J`)cxBxx z%gbUXTYI8LuH(Dz;yK83i9;yZBruN_IWIq7Xg1eoUMg~0%0)rGmfKz_L{3U{FWl3;Lp8-ONR zdzqtY>?p;pzb}5OER#o+wM!X1YA%{F)DN2=7l~~9;Xt<>)p&khEYuvsJYMv8xkO1M zfBAp+fDID_+Una8bBwbh`FeH=Qk=q#Nbo|ICn9+q-@u6;iTE7Dk!i0IYsOiF>IF46{3Ce1*orl*fOIH@||tT&N-j=6Yvg);8t`4|MDWp)X%7(iI#` zoB2#_6+7Xm&6Hpf)!6o*;=3!l(+X51+_jl9@C`@z)01rz+d1J9%uLjN?3-L(a)1(Q z&FYWBbF&>Oiu+|BI8g4<$)@a)k55!T3J33v4i5je+z2UCAf@tx%9dP?wbO~dO+MH+ z3B2SV%D+`2!on2JZp_~M7mlp0ewsz>Ioy2Gr50=`xma%3v@Z&F1r)6PZC>)6(u7LJ z7YuFsCxc8v1uF=;j5K``IydDAQWM64w#gv3@o5rV+{C7~&AKHMRQBL-+!qpR887IP z)$~p@NFWmosn((j&4vABs8jrZq;TUVi9YOA3Nz{vA@P_zCG3Z&Eh{jsm^0uMy$JS#Rv<^wC zeag*;8q{_zaRM!Xgc?^6q^T8n*qoK3<=yj26VvWL!y>*t)_lUn2$k0DCVehn{Hqh+ zrskT5Y};`jqaz^h2MI;hMl?>_{w48!BhSw}Z$(eOxc5o{yk=nTcya1)^IVRP%%}T3 zduY653tb@FqjDUNj#XT3(u;lpMK?2ZcLPL7yT56e&KwK8d3@i)dxKD2g6|mL#ff zUYKpS@~s<5f@Bm_kZ0L*$|cxyN7Lj;C`uosX+d2wRZUV|Mkep>sIhSXT{_T{o4C3| zZ`6A&wZTXVx-0%)U5+yCf5tFM;{QD&p+4OB^*@3f7&d{dJk6;U~i^b~>c z!e%d;J$A%bR=a;NgxIS94BfzXd?4zcK-cV# z#y*h&6Ru!;C2Z6OhX-Bsppx2Iz+BAwC4qM1(yKcdB^il)ceuWTA?k)kP!_r?A!}(V z|Cs2F0m=wXkAS)1vZ8oqEkPb`NB^-n>@JKjOr0WQ%uWXYuf}Ninky<*wuJ9P*R1Rt z&B94bGpFt%bKZGR7*;scx6d5FZCZl zc^T7$=RqVn3|%I}2?Ba4mnbV86Dt9o#=g0+amTbG#@2yy&OuHXWD2VdODW2_f#|?m zT^FqXT8Qv@0^@0HP8uGguJN}xa>-<+OH)q?o)-$IDq(jZvH;$#ede2{w*R@!bn5K+ z{8Ua-hAzOmqN^PZxx~n}M~6u=i^V|80o(6ZMW?ziR%}#XB}HLnfcrTtYKTR|9B%DC zfG-h$_qdqXcTik-jMGC7--UWZ!@HF9u!QfQm;V&3So`aAJ00(mmBS*dbyuCDV@R;R zxG(-L{~0fp9d7X~4thrRK6Kl9B(6*sD7&KDw2(L>_zph7GOdgRj^z)D&>QyF*?*Bt zJ>U_rh|s&!@>QCsMTLK+AbF`7a=<}XG?j~ny}hs`561WkS0*@S&F{-Nij^0LA`4b6 z#_grBGFI1?q71-mjI$yZ`|Iem4cz*=j6W=eaLfDY1-L9%?46DPNSKLE zQ{oDvre7_M{vHnvk5OGb8y-XWh8Q4m;j-vfc|pfwC|?5^_d5WKvC*ITyQeG6|GTJm z5#!<(pv^UqFA9MuCuirTV;ixYdsfn?ueu59kwq(SAD=`ON$MM@KH&D1weM0F!mF)q z3w)E9S9fHUuG{ACHsRw^ix0!%@gSsQpu0A4`|c`rh55u@yl5_}|4daA8~YFY#qlq+ zScgSN9Nf>dV-ee!VAh^LKR7UO#7t9OHo57z!Y8kccu$Flh%>mVZI7w&QXwGaNh;&e z>HPY2NWQ8R#hFf3Ig&nb$@i9`*wM)^6a=CQ2VSv$m89xIEjMzV&(O*5cA$c8@^rSch+{D7ckOL%D_4R+F#aO~K4wPs*nWt?#wizq@t&19!7c}@>dwWt|kh>4PsDs2UDdkUT zAVgd2NGfl|hr{7@2|TJQgbfzaGwbGpG@ZK1L)#x-x%E_4MWrT^pBQ2KSF`H9V2GDB z32#G|Vi5D=*Vsk`f;BJX(+B_Y)V`{hJB%AoVvA zXyoQnA^a-hQsZ8R?^`pK*xTECBEUO`P=W|!d69w34F#TPev|Q3U-H|ch!jt6JimNO zc<#db_UM6(`rolktnJN2SW0bRaBNy#>&P*%CUa(3ZC(?a9CceL5VUVlkrSh=B+wEE z(+6Fis%}a4>X6u*TFedIF6*7b@Ua+A)y6V+OEs|I_aNQSO+^?RNpJp%-0LERgd)u`-}VyPvXZJ?e_x?xdP*b;82E< z>^}iB-!TaUE2`m3Ki?O>De z+}|?I2WmsCR=?b@aXHtb#m?fn&)mSUJUL;ag=%Bbo+>mfo{w{fnhk)vGX^wXy-$pv zha#@*k;9I!3noU2%?FSQzUt-knYe-aO?85~_kEf3KgxX%9XizhB(mNrZ6!v15Uq}E zJ$H!2_qJGVMOO1@#JSuWlcwaAbxd1RxP5YmaqsRg-Zb*vcMk?t!%?_aL?nZrCrJf4 zaJ!dxLk8BV5{Zf36&1Xt zsrr!FDNoBt|H#M#Jh3i)jK7WfmoMD!f_C_M*r`*q;+5v6SAG0F zI2$Xo%;)_0HM9e?6$1-vi Date: Thu, 2 Jan 2025 11:01:24 +0100 Subject: [PATCH 024/102] feat: default pfp for multiservice --- src/utils/ui/default-profile-picture.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/utils/ui/default-profile-picture.ts b/src/utils/ui/default-profile-picture.ts index a661c384f..3e300875f 100644 --- a/src/utils/ui/default-profile-picture.ts +++ b/src/utils/ui/default-profile-picture.ts @@ -23,7 +23,9 @@ export const defaultProfilePicture = (service: AccountService, accountProvider: return require("../../../assets/images/service_skolengo.png"); case AccountService.Local: return require("../../../assets/images/service_unknown.png"); + case AccountService.PapillonMultiService: + return require("../../../assets/images/multiservice.png"); } return require("../../../assets/images/service_unknown.png"); -}; \ No newline at end of file +}; From 18216846e366dc6b39b63e6dc303fc6c90c9a915 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 11:02:04 +0100 Subject: [PATCH 025/102] feat: added new route for space setting --- src/router/helpers/types.ts | 2 ++ src/router/screens/settings/index.ts | 4 ++++ src/views/settings/SettingsMultiService.tsx | 1 + 3 files changed, 7 insertions(+) diff --git a/src/router/helpers/types.ts b/src/router/helpers/types.ts index c9dd79d6d..b797f783a 100644 --- a/src/router/helpers/types.ts +++ b/src/router/helpers/types.ts @@ -14,6 +14,7 @@ import {Client} from "pawrd"; import { Host } from "turboself-api"; import {Evaluation} from "@/services/shared/Evaluation"; import { ThemesMeta } from "@/utils/chat/themes/Themes.types"; +import {MultiServiceSpace} from "@/stores/multiService/types"; export type RouteParameters = { // welcome.index @@ -128,6 +129,7 @@ export type RouteParameters = { SettingsExternalServices: undefined; SettingsMagic: undefined; SettingsMultiService: undefined; + SettingsMultiServiceSpace: { space: MultiServiceSpace }; SettingsFlags: undefined; SettingsFlagsInfos: { title: string; value: any }; SettingsAddons: undefined; diff --git a/src/router/screens/settings/index.ts b/src/router/screens/settings/index.ts index 10f0e4a3b..3ff7aceff 100644 --- a/src/router/screens/settings/index.ts +++ b/src/router/screens/settings/index.ts @@ -28,6 +28,7 @@ import TurboselfAccountSelector from "@/views/settings/ExternalAccount/Turboself import SettingsApparence from "@/views/settings/SettingsApparence"; import ExternalAliseLogin from "@/views/settings/ExternalAccount/Alise"; import SettingsMultiService from "@/views/settings/SettingsMultiService"; +import SettingsMultiServiceSpace from "@/views/settings/SettingsMultiServiceSpace"; const settingsScreens = [ createScreen("Settings", Settings, { @@ -67,6 +68,9 @@ const settingsScreens = [ createScreen("SettingsMultiService", SettingsMultiService, { headerTitle: "Multiservice", }), + createScreen("SettingsMultiServiceSpace", SettingsMultiServiceSpace, { + headerTitle: "Gérer l'environnement multi-service", + }), createScreen("SettingsAddons", SettingsAddons, { headerTitle: "Extensions", }), diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 46c581f0d..88e6bcc75 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -143,6 +143,7 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => {multiServiceSpaces.map(space => ( navigation.navigate("SettingsMultiServiceSpace", { space })} leading={ Date: Thu, 2 Jan 2025 12:05:50 +0100 Subject: [PATCH 026/102] fix: store property cannot be set to undefined --- src/stores/multiService/index.ts | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index e092b7e92..90d940482 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -59,21 +59,20 @@ export const useMultiService = create()( let spaceMutated: MultiServiceSpace; // Mutate only featureServices and name properties. - if (key in ["featureServices", "name"]) { + if (key === "featureServices" || key === "name") { spaceMutated = { ...space, [key]: value }; + // Save the update in the store and storage. + set((state) => ({ + spaces: state.spaces.map((space) => + space.accountLocalID === localID + ? spaceMutated + : space + ) + })); } - - // Save the update in the store and storage. - set((state) => ({ - spaces: state.spaces.map((space) => - space.accountLocalID === localID - ? spaceMutated - : space - ) - })); }, getFeatureAccount: (feature, spaceLocalID) => { From 1f87d2c62cd5ed787837083cefa600acbfe2df26 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 12:06:31 +0100 Subject: [PATCH 027/102] feat: added multi service space personalization --- src/views/settings/SettingsMultiService.tsx | 37 +-- .../settings/SettingsMultiServiceSpace.tsx | 237 ++++++++++++++++++ 2 files changed, 260 insertions(+), 14 deletions(-) create mode 100644 src/views/settings/SettingsMultiServiceSpace.tsx diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 88e6bcc75..3901bd99a 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -5,7 +5,7 @@ import type {Screen} from "@/router/helpers/types"; import MultiServiceContainerCard from "@/components/Settings/MultiServiceContainerCard"; import {NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; import {ImageIcon, PlugZap, Plus, Type, Trash2} from "lucide-react-native"; -import {useAccounts} from "@/stores/account"; +import {useAccounts, useCurrentAccount} from "@/stores/account"; import {useMultiService} from "@/stores/multiService"; import BottomSheet from "@/components/Modals/PapillonBottomSheet"; import * as ImagePicker from "expo-image-picker"; @@ -25,6 +25,7 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => const createMultiServiceSpace = useMultiService(store => store.create); const deleteMultiServiceSpace = useMultiService(store => store.remove); const accounts = useAccounts(); + const currentAccount = useCurrentAccount(); const [spaceCreationSheetOpened, setSpaceCreationSheetOpened] = useState(false); const [spaceName, setSpaceName] = useState(""); @@ -62,13 +63,14 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => const localID = uuid(); + // TODO: have student name and space title const linkedAccount: PapillonMultiServiceSpace = { isExternal: false, linkedExternalLocalIDs: [], authentication: null, identity: {}, identityProvider: { - name: "Environnement multiservice Papillon" + name: spaceName }, instance: null, localID: localID, @@ -78,8 +80,8 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => }, service: AccountService.PapillonMultiService, studentName: { // TODO - first: spaceName, - last: "" + first: currentAccount.account?.studentName.first || "", + last: currentAccount.account?.studentName.last || "" } }; @@ -102,6 +104,13 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => setSelectedImage(null); setSpaceName(""); }; + + const deleteAllSpaces = () => { + for (const space of multiServiceSpaces) { + accounts.remove(space.accountLocalID); + deleteMultiServiceSpace(space.accountLocalID); + } + }; return ( = ({ navigation }) => trailing={ toggleMultiService()} + onValueChange={() => { + if (multiServiceEnabled) { + Alert.alert("Attention", "La désactivation du multi-service entrainera la suppression de vos environnement multi-services créés.", [ { text: "Annuler", style: "cancel" }, { text: "Confirmer", style: "destructive", onPress: () => { + deleteAllSpaces(); + toggleMultiService(); + } } ]); + } else { + toggleMultiService(); + } + }} /> } leading={ @@ -156,15 +174,6 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => }} /> } - trailing={ - { - accounts.remove(space.accountLocalID); - deleteMultiServiceSpace(space.accountLocalID); - }} - color="#CF0029" - /> - } > {space.name} diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx new file mode 100644 index 000000000..b2afaae0e --- /dev/null +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -0,0 +1,237 @@ +import React, {useRef, useState} from "react"; +import {ActivityIndicator, Image, ScrollView, Switch, TextInput, KeyboardAvoidingView, Alert} from "react-native"; +import {useTheme} from "@react-navigation/native"; +import type {Screen} from "@/router/helpers/types"; +import {NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; +import {Camera, PlugZap, TextCursorInput, User2, Type, Trash2} from "lucide-react-native"; +import {useAccounts} from "@/stores/account"; +import { AccountService, PrimaryAccount} from "@/stores/account/types"; +import * as ImagePicker from "expo-image-picker"; +import {useSafeAreaInsets} from "react-native-safe-area-context"; +import {useMultiService} from "@/stores/multiService"; + +const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ navigation, route }) => { + const theme = useTheme(); + const insets = useSafeAreaInsets(); + const space = route.params.space; + const accounts = useAccounts(); + const availableAccounts = accounts.accounts.filter(account => !account.isExternal && !(account.service == AccountService.PapillonMultiService)); + const deleteMultiServiceSpace = useMultiService(store => store.remove); + const updateMultiServiceSpace = useMultiService(store => store.update); + + const linkedAccount = accounts.accounts.find(account => account.localID === space.accountLocalID) as PrimaryAccount | undefined; + + const firstNameRef = useRef(null); + const lastNameRef = useRef(null); + const spaceNameRef = useRef(null); + + const [firstName, setFirstName] = useState(linkedAccount?.studentName?.first ?? ""); + const [lastName, setLastName] = useState(linkedAccount?.studentName?.last ?? ""); + const [spaceName, setSpaceName] = useState(space.name); + + const [loadingImage, setLoadingImage] = useState(false); + const [selectedImage, setSelectedImage] = useState(null); + const selectPicture = async () => { + setLoadingImage(true); + + let result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [1, 1], + quality: 1, + base64: true, + }); + + if (!result.canceled) { + const img = "data:image/jpeg;base64," + result.assets[0].base64; + setSelectedImage(img); + } + + setLoadingImage(false); + }; + + const deleteSpace = () => { + Alert.alert("Êtes-vous sur ?", "Cette action entrainera la suppression de votre espace multi-service.", [ { text: "Annuler", style: "cancel" }, { text: "Confirmer", style: "destructive", onPress: () => { + accounts.remove(space.accountLocalID); + deleteMultiServiceSpace(space.accountLocalID); + navigation.goBack(); + }}]); + }; + return ( + + + + + + + + selectPicture()} + leading={selectedImage && + + } + icon={!selectedImage && } + trailing={ + + } + > + + {selectedImage ? "Changer la photo" : "Ajouter une photo"} + + {!selectedImage ? ( + + Personnalisez votre espace en ajoutant une photo. + + ) : ( + + La photo de l'espace reste sur votre appareil. + + )} + + + + + + + + spaceNameRef.current?.focus()} + chevron={false} + icon={} + > + + Titre + + { + updateMultiServiceSpace(space.accountLocalID, "name", text); + setSpaceName(text); + }} + ref={spaceNameRef} + /> + + + + + + + + + + firstNameRef.current?.focus()} + chevron={false} + icon={} + > + + Prénom + + { + // @ts-expect-error + accounts.update(space.accountLocalID, "studentName", { + first: text, + last: lastName + }); + setFirstName(text); + }} + ref={firstNameRef} + /> + + + lastNameRef.current?.focus()} + chevron={false} + icon={} + > + + Nom de famille + + { + // @ts-expect-error + accounts.update(space.accountLocalID, "studentName", { + first: firstName, + last: text + }); + setLastName(text); + }} + ref={lastNameRef} + /> + + + + + + + + deleteSpace()} + leading={ + + } + > + + Supprimer + + + Supprimer l'environnement + + + + + + ); +}; + + + +export default SettingsMultiServiceSpace; From 3328b24fa6a6ba260f688a130eab05e4cf18b5fe Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 12:08:07 +0100 Subject: [PATCH 028/102] feat: added config section (WIP) --- src/views/settings/SettingsMultiServiceSpace.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index b2afaae0e..3d05ddfde 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -211,6 +211,11 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga + + + WIP + + Date: Thu, 2 Jan 2025 12:40:35 +0100 Subject: [PATCH 029/102] fix: showing space name in account switcher context menu --- src/components/Home/AccountSwitcherContextMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Home/AccountSwitcherContextMenu.tsx b/src/components/Home/AccountSwitcherContextMenu.tsx index b0f4d4e5b..ef176b1a4 100644 --- a/src/components/Home/AccountSwitcherContextMenu.tsx +++ b/src/components/Home/AccountSwitcherContextMenu.tsx @@ -209,7 +209,7 @@ const ContextMenu: React.FC<{ numberOfLines={1} ellipsizeMode="tail" > - {AccountService[account.service] !== "Local" ? + {AccountService[account.service] !== "Local" && account.service !== AccountService.PapillonMultiService ? AccountService[account.service] : account.identityProvider ? account.identityProvider.name : From 2ce6e566f14cccdb93f57a4aa113c14d5d9b9104 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 13:35:38 +0100 Subject: [PATCH 030/102] fix: possibility to mutate image key --- src/stores/multiService/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index 90d940482..745d1ac88 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -59,7 +59,7 @@ export const useMultiService = create()( let spaceMutated: MultiServiceSpace; // Mutate only featureServices and name properties. - if (key === "featureServices" || key === "name") { + if (key === "featureServices" || key === "name" || key === "image") { spaceMutated = { ...space, [key]: value From 6d35bdcfb0bfd9b4b2889d7839052404c7d0c4b0 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 13:42:59 +0100 Subject: [PATCH 031/102] fix: better typing and setFeatureAccount function added to store --- src/stores/multiService/index.ts | 25 +++++++++++++++++++++++-- src/stores/multiService/types.ts | 5 +++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index 745d1ac88..345344dec 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -58,8 +58,8 @@ export const useMultiService = create()( let spaceMutated: MultiServiceSpace; - // Mutate only featureServices and name properties. - if (key === "featureServices" || key === "name" || key === "image") { + // Mutate only image and name properties. + if (key === "name" || key === "image") { spaceMutated = { ...space, [key]: value @@ -75,6 +75,27 @@ export const useMultiService = create()( } }, + setFeatureAccount: (spaceLocalID, feature, account) => { + const space = get().spaces.find((space) => space.accountLocalID === spaceLocalID); + if (!space) return; + + let mutatedFeatureServices = space.featuresServices; + mutatedFeatureServices[feature] = account; + + const spaceMutated: MultiServiceSpace = { + ...space, + featuresServices: mutatedFeatureServices + }; + // Save the update in the store and storage. + set((state) => ({ + spaces: state.spaces.map((space) => + space.accountLocalID === spaceLocalID + ? spaceMutated + : space + ) + })); + }, + getFeatureAccount: (feature, spaceLocalID) => { // Find the account to update in the storage. const space = get().spaces.find((space) => space.accountLocalID === spaceLocalID); diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index 32245616d..b436fb560 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -13,7 +13,7 @@ export interface MultiServiceSpace { name: string image?: string featuresServices: { - [key in keyof typeof MultiServiceFeature]: PrimaryAccount | null + [key in MultiServiceFeature]?: PrimaryAccount | null } } @@ -24,5 +24,6 @@ export interface MultiServiceStore { remove: (localID: string) => void update: (localID: string, key: T, value: A[T]) => void toggleEnabledState: () => void - getFeatureAccount: (feature: keyof typeof MultiServiceFeature, spaceLocalID: string) => PrimaryAccount | null | undefined + setFeatureAccount: (spaceLocalID: string, feature: MultiServiceFeature, account: PrimaryAccount) => void + getFeatureAccount: (feature: MultiServiceFeature, spaceLocalID: string) => PrimaryAccount | null | undefined } From 2d0ece1d19d0c4c240d7eb2ce8ea4a8f03e218a6 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 13:47:28 +0100 Subject: [PATCH 032/102] fix: image settings --- src/views/settings/SettingsMultiServiceSpace.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index 3d05ddfde..b1b77d0b9 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -44,6 +44,11 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga if (!result.canceled) { const img = "data:image/jpeg;base64," + result.assets[0].base64; + updateMultiServiceSpace(space.accountLocalID, "image", img); + // @ts-expect-error + accounts.update(space.accountLocalID, "personalization", { + profilePictureB64: img + }); setSelectedImage(img); } @@ -78,9 +83,9 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga selectPicture()} - leading={selectedImage && + leading={(selectedImage || space.image) && = ({ naviga }} /> } - icon={!selectedImage && } + icon={!(selectedImage || space.image) && } trailing={ } @@ -135,6 +140,10 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga value={spaceName} onChangeText={(text: string) => { updateMultiServiceSpace(space.accountLocalID, "name", text); + // @ts-expect-error + accounts.update(space.accountLocalID, "identityProvider", { + name: text + }); setSpaceName(text); }} ref={spaceNameRef} From 41ceadecbabf2a8368f19fe320ebf2dead31cf3d Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 14:32:43 +0100 Subject: [PATCH 033/102] feat: configuration interface idea --- .../settings/SettingsMultiServiceSpace.tsx | 122 +++++++++++++++++- 1 file changed, 116 insertions(+), 6 deletions(-) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index b1b77d0b9..cf8ec0c77 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -1,14 +1,27 @@ import React, {useRef, useState} from "react"; -import {ActivityIndicator, Image, ScrollView, Switch, TextInput, KeyboardAvoidingView, Alert} from "react-native"; +import { + ActivityIndicator, + Image, + ScrollView, + Switch, + TextInput, + KeyboardAvoidingView, + Alert, + FlatList +} from "react-native"; import {useTheme} from "@react-navigation/native"; import type {Screen} from "@/router/helpers/types"; import {NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; -import {Camera, PlugZap, TextCursorInput, User2, Type, Trash2} from "lucide-react-native"; +import {Camera, ChevronDown, TextCursorInput, User2, Type, Trash2, CircleAlert} from "lucide-react-native"; import {useAccounts} from "@/stores/account"; import { AccountService, PrimaryAccount} from "@/stores/account/types"; import * as ImagePicker from "expo-image-picker"; import {useSafeAreaInsets} from "react-native-safe-area-context"; import {useMultiService} from "@/stores/multiService"; +import {MultiServiceFeature} from "@/stores/multiService/types"; +import LottieView from "lottie-react-native"; +import {anim2Papillon} from "@/utils/ui/animations"; +import Reanimated, {FadeOut, ZoomIn} from "react-native-reanimated"; const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ navigation, route }) => { const theme = useTheme(); @@ -62,6 +75,42 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga navigation.goBack(); }}]); }; + + const selectFeatureAccount = (feature: MultiServiceFeature) => { + + }; + + + const lottieRef = React.useRef(null); + + const features = [ + { + name: "Notes", + feature: MultiServiceFeature.Grades, + icon: require("@/../assets/lottie/tab_chart.json") + }, + { + name: "Emploi du temps", + feature: MultiServiceFeature.Timetable, + icon: require("@/../assets/lottie/tab_calendar.json") + }, + { + name: "Devoirs", + feature: MultiServiceFeature.Homeworks, + icon: require("@/../assets/lottie/tab_book_2.json") + }, + { + name: "Vie scolaire", + feature: MultiServiceFeature.Attendance, + icon: require("@/../assets/lottie/tab_check.json") + }, + { + name: "Actualités", + feature: MultiServiceFeature.News, + icon: require("@/../assets/lottie/tab_news.json") + } + ]; + return ( = ({ naviga ref={lastNameRef} /> - + Accède à plus d'options en sélectionnant l'espace virtuel, et en personnalisant ton profil dans les paramètres. - - WIP - + <> + {features.map(feature => ( + + + + } + onPress={() => selectFeatureAccount(feature.feature)} + trailing={} + chevron={false} + > + {feature.name} + + {space.featuresServices[feature.feature] ? ( + + Mettre le compte connecté ici + + ): ( + } + style={{ + width: "100%", + padding: 0 + }} + > + Pas de service sélectionné + + )} + + ))} + From 759dde85aff83bf850a3bcad83bc71f96b5eae89 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 14:48:23 +0100 Subject: [PATCH 034/102] fix: styles --- .../settings/SettingsMultiServiceSpace.tsx | 71 +++++++++++++++---- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index cf8ec0c77..1cf9fb602 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -7,7 +7,7 @@ import { TextInput, KeyboardAvoidingView, Alert, - FlatList + FlatList, View, Text } from "react-native"; import {useTheme} from "@react-navigation/native"; import type {Screen} from "@/router/helpers/types"; @@ -22,6 +22,7 @@ import {MultiServiceFeature} from "@/stores/multiService/types"; import LottieView from "lottie-react-native"; import {anim2Papillon} from "@/utils/ui/animations"; import Reanimated, {FadeOut, ZoomIn} from "react-native-reanimated"; +import {defaultProfilePicture} from "@/utils/ui/default-profile-picture"; const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ navigation, route }) => { const theme = useTheme(); @@ -270,9 +271,12 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga - <> - {features.map(feature => ( - + + {features.map((feature, index) => ( + <> = ({ naviga {space.featuresServices[feature.feature] ? ( } + separator={true} > - Mettre le compte connecté ici + + + {space.featuresServices[feature.feature]?.studentName?.first || "Utilisateur"}{" "} + {space.featuresServices[feature.feature]?.studentName?.last || ""} + + + + + {AccountService[space.featuresServices[feature.feature]?.service || AccountService.Local] !== "Local" ? + AccountService[space.featuresServices[feature.feature]?.service || AccountService.Local] : + space.featuresServices[feature.feature]?.identityProvider ? + space.featuresServices[feature.feature]?.identityProvider?.name : + "Compte local" + } + ): ( } - style={{ - width: "100%", - padding: 0 - }} + icon={} + separator={true} > Pas de service sélectionné )} - + ))} - + From f9c70eac36e1f5ac0cbb439f6dfd21b6653b80f9 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 15:30:40 +0100 Subject: [PATCH 035/102] feat: added AccountItem component --- src/components/Global/AccountItem.tsx | 116 ++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/components/Global/AccountItem.tsx diff --git a/src/components/Global/AccountItem.tsx b/src/components/Global/AccountItem.tsx new file mode 100644 index 000000000..9cc942ca7 --- /dev/null +++ b/src/components/Global/AccountItem.tsx @@ -0,0 +1,116 @@ +import {Image, StyleProp, Text, View, ViewStyle} from "react-native"; +import { animPapillon } from "@/utils/ui/animations"; + +import Reanimated, { + FadeOut, + ZoomIn +} from "react-native-reanimated"; +import {PrimaryAccount, AccountService} from "@/stores/account/types"; +import {defaultProfilePicture} from "@/utils/ui/default-profile-picture"; +import {Check} from "lucide-react-native"; +import React from "react"; +import {useTheme} from "@react-navigation/native"; + +const AccountItem: React.FC<{ account: PrimaryAccount, additionalStyles?: StyleProp, endCheckMark: boolean }> = ({ + account, + additionalStyles, + endCheckMark +}) => { + const theme = useTheme(); + return ( + + + + + + + + {account.studentName?.first || "Utilisateur"}{" "} + {account.studentName?.last || ""} + + + + + {AccountService[account.service] !== "Local" ? + AccountService[account.service] : + account.identityProvider ? + account.identityProvider?.name : + "Compte local" + } + + + {endCheckMark && + + + + } + + ); +}; + +export default AccountItem; From 3026da675ce7a8068b0214f74e7879c39dd9ee02 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 15:31:00 +0100 Subject: [PATCH 036/102] feat: functionnals settings for multiservices --- .../settings/SettingsMultiServiceSpace.tsx | 122 +++++++++--------- 1 file changed, 64 insertions(+), 58 deletions(-) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index 1cf9fb602..0b6d200c8 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -1,28 +1,32 @@ import React, {useRef, useState} from "react"; import { ActivityIndicator, + Alert, Image, + KeyboardAvoidingView, + Pressable, ScrollView, - Switch, + Text, TextInput, - KeyboardAvoidingView, - Alert, - FlatList, View, Text + View } from "react-native"; import {useTheme} from "@react-navigation/native"; import type {Screen} from "@/router/helpers/types"; -import {NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; -import {Camera, ChevronDown, TextCursorInput, User2, Type, Trash2, CircleAlert} from "lucide-react-native"; +import {NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; +import {Camera, Check, ChevronDown, CircleAlert, TextCursorInput, Trash2, Type, User2} from "lucide-react-native"; import {useAccounts} from "@/stores/account"; -import { AccountService, PrimaryAccount} from "@/stores/account/types"; +import {AccountService, PrimaryAccount} from "@/stores/account/types"; import * as ImagePicker from "expo-image-picker"; import {useSafeAreaInsets} from "react-native-safe-area-context"; import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature} from "@/stores/multiService/types"; import LottieView from "lottie-react-native"; -import {anim2Papillon} from "@/utils/ui/animations"; +import {anim2Papillon, animPapillon} from "@/utils/ui/animations"; import Reanimated, {FadeOut, ZoomIn} from "react-native-reanimated"; import {defaultProfilePicture} from "@/utils/ui/default-profile-picture"; +import PapillonBottomSheet from "@/components/Modals/PapillonBottomSheet"; +import * as Haptics from "expo-haptics"; +import AccountItem from "@/components/Global/AccountItem"; const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ navigation, route }) => { const theme = useTheme(); @@ -32,6 +36,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga const availableAccounts = accounts.accounts.filter(account => !account.isExternal && !(account.service == AccountService.PapillonMultiService)); const deleteMultiServiceSpace = useMultiService(store => store.remove); const updateMultiServiceSpace = useMultiService(store => store.update); + const setMultiServiceSpaceAccountFeature = useMultiService(store => store.setFeatureAccount); const linkedAccount = accounts.accounts.find(account => account.localID === space.accountLocalID) as PrimaryAccount | undefined; @@ -69,6 +74,10 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga setLoadingImage(false); }; + const [accountSelectorOpened, setAccountSelectorOpened] = useState(false); + const [selectedAccount, setSelectedAccount] = useState(null); + const [featureSelection, setFeatureSelection] = useState(MultiServiceFeature.Grades); + const deleteSpace = () => { Alert.alert("Êtes-vous sur ?", "Cette action entrainera la suppression de votre espace multi-service.", [ { text: "Annuler", style: "cancel" }, { text: "Confirmer", style: "destructive", onPress: () => { accounts.remove(space.accountLocalID); @@ -77,10 +86,17 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga }}]); }; - const selectFeatureAccount = (feature: MultiServiceFeature) => { - + const openAccountSelector = (feature: MultiServiceFeature) => { + setSelectedAccount(space.featuresServices[feature] || null); + setFeatureSelection(feature); + setAccountSelectorOpened(true); }; + const setAccountFeature = (account: PrimaryAccount, feature: MultiServiceFeature) => { + setMultiServiceSpaceAccountFeature(space.accountLocalID, feature, account); + setAccountSelectorOpened(false); + setSelectedAccount(null); + }; const lottieRef = React.useRef(null); @@ -310,60 +326,19 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga ]} /> } - onPress={() => selectFeatureAccount(feature.feature)} + onPress={() => openAccountSelector(feature.feature)} trailing={} chevron={false} > {feature.name} {space.featuresServices[feature.feature] ? ( - } - separator={true} - > - - - {space.featuresServices[feature.feature]?.studentName?.first || "Utilisateur"}{" "} - {space.featuresServices[feature.feature]?.studentName?.last || ""} - - - - - {AccountService[space.featuresServices[feature.feature]?.service || AccountService.Local] !== "Local" ? - AccountService[space.featuresServices[feature.feature]?.service || AccountService.Local] : - space.featuresServices[feature.feature]?.identityProvider ? - space.featuresServices[feature.feature]?.identityProvider?.name : - "Compte local" - } - - + ): ( } @@ -376,6 +351,37 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga ))} + setAccountSelectorOpened(opened)}> + + + + {availableAccounts.map((account, index) => ( + { + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Soft); + setAccountFeature(account, featureSelection); + }} + > + + + ))} + + + + Date: Thu, 2 Jan 2025 15:39:20 +0100 Subject: [PATCH 037/102] feat: redirecting to service for each functionality --- src/services/attendance.ts | 16 ++++++++++++++++ src/services/grades.ts | 16 ++++++++++++++++ src/services/homework.ts | 16 ++++++++++++++++ src/services/news.ts | 16 ++++++++++++++++ src/services/timetable.ts | 9 +++++++++ 5 files changed, 73 insertions(+) diff --git a/src/services/attendance.ts b/src/services/attendance.ts index 0e9739273..d61a1910e 100644 --- a/src/services/attendance.ts +++ b/src/services/attendance.ts @@ -4,6 +4,8 @@ import { useAttendanceStore } from "@/stores/attendance"; import { Attendance } from "./shared/Attendance"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { error } from "@/utils/logger/logger"; +import {useMultiService} from "@/stores/multiService"; +import {MultiServiceFeature} from "@/stores/multiService/types"; export async function updateAttendancePeriodsInCache (account: T): Promise { let periods: Period[] = []; @@ -61,6 +63,13 @@ export async function updateAttendancePeriodsInCache (accoun break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.Attendance, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return updateAttendancePeriodsInCache(service); + } default: throw new Error("Service not implemented"); } @@ -116,6 +125,13 @@ export async function updateAttendanceInCache (account: T, p break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.Attendance, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return updateAttendanceInCache(service, periodName); + } default: throw new Error("Service not implemented"); } diff --git a/src/services/grades.ts b/src/services/grades.ts index 771ef39fb..25c2116ff 100644 --- a/src/services/grades.ts +++ b/src/services/grades.ts @@ -4,6 +4,8 @@ import type { Period } from "./shared/Period"; import type { AverageOverview, Grade } from "./shared/Grade"; import {error } from "@/utils/logger/logger"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; +import {useMultiService} from "@/stores/multiService"; +import {MultiServiceFeature} from "@/stores/multiService/types"; const getDefaultPeriod = (periods: Period[]): string => { const now = Date.now(); @@ -54,6 +56,13 @@ export async function updateGradesPeriodsInCache (account: T break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.Grades, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return updateGradesPeriodsInCache(service); + } default: throw new Error("Service not implemented"); } @@ -120,6 +129,13 @@ export async function updateGradesAndAveragesInCache (accoun break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.Grades, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return updateGradesAndAveragesInCache(service, periodName); + } default: throw new Error(`Service (${AccountService[account.service]}) not implemented for this request`); } diff --git a/src/services/homework.ts b/src/services/homework.ts index e2bfd14a3..f91f72775 100644 --- a/src/services/homework.ts +++ b/src/services/homework.ts @@ -7,6 +7,8 @@ import { pronoteFirstDate } from "./pronote/timetable"; import { dateToEpochWeekNumber, epochWNToPronoteWN } from "@/utils/epochWeekNumber"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { useClassSubjectStore } from "@/stores/classSubject"; +import {useMultiService} from "@/stores/multiService"; +import {MultiServiceFeature} from "@/stores/multiService/types"; /** * Updates the state and cache for the homework of given week number. @@ -44,6 +46,13 @@ export async function updateHomeworkForWeekInCache (account: homeworks = []; break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return updateHomeworkForWeekInCache(service, date); + } default: console.info(`[updateHomeworkForWeekInCache]: updating to empty since ${account.service} not implemented.`); } @@ -70,6 +79,13 @@ export async function toggleHomeworkState (account: T, homew case AccountService.Local: { break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return toggleHomeworkState(service, homework); + } default: { throw new Error("Service not implemented"); } diff --git a/src/services/news.ts b/src/services/news.ts index 0d8f0a4e2..bcc11702c 100644 --- a/src/services/news.ts +++ b/src/services/news.ts @@ -5,6 +5,8 @@ import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { error } from "@/utils/logger/logger"; import { newsRead } from "pawnote"; import { ca } from "date-fns/locale"; +import {useMultiService} from "@/stores/multiService"; +import {MultiServiceFeature} from "@/stores/multiService/types"; /** * Updates the state and cache for the news. @@ -43,6 +45,13 @@ export async function updateNewsInCache (account: T): Promis useNewsStore.getState().updateInformations(informations); break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.News, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return updateNewsInCache(service); + } default: { throw new Error("Service not implemented."); } @@ -70,6 +79,13 @@ export async function setNewsRead (account: T, message: Info } case AccountService.Multi: break; + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.News, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return setNewsRead(service, message, read); + } default: { throw new Error("Service not implemented."); } diff --git a/src/services/timetable.ts b/src/services/timetable.ts index cc48c7d9c..ca442e0a5 100644 --- a/src/services/timetable.ts +++ b/src/services/timetable.ts @@ -4,6 +4,8 @@ import { epochWNToPronoteWN, weekNumberToDateRange } from "@/utils/epochWeekNumb import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { error } from "@/utils/logger/logger"; import { fetchIcalData } from "./local/ical"; +import {useMultiService} from "@/stores/multiService"; +import {MultiServiceFeature} from "@/stores/multiService/types"; /** * Updates the state and cache for the timetable of given week number. @@ -45,6 +47,13 @@ export async function updateTimetableForWeekInCache (account useTimetableStore.getState().updateClasses(epochWeekNumber, timetable); break; } + case AccountService.PapillonMultiService: { + const service = useMultiService().getFeatureAccount(MultiServiceFeature.Timetable, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return updateTimetableForWeekInCache(service, epochWeekNumber, force); + } default: { throw new Error("Service not implemented."); } From 444833fc6f56d1a05d052796f68fbb6122385dcf Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 18:16:30 +0100 Subject: [PATCH 038/102] fix: using new function to retreive account object in services --- src/services/attendance.ts | 6 +++--- src/services/grades.ts | 6 +++--- src/services/homework.ts | 9 +++++---- src/services/news.ts | 6 +++--- src/services/timetable.ts | 4 ++-- src/utils/multiservice/index.ts | 17 +++++++++++++++++ 6 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 src/utils/multiservice/index.ts diff --git a/src/services/attendance.ts b/src/services/attendance.ts index d61a1910e..821f82047 100644 --- a/src/services/attendance.ts +++ b/src/services/attendance.ts @@ -4,8 +4,8 @@ import { useAttendanceStore } from "@/stores/attendance"; import { Attendance } from "./shared/Attendance"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { error } from "@/utils/logger/logger"; -import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature} from "@/stores/multiService/types"; +import {getFeatureAccount} from "@/utils/multiservice"; export async function updateAttendancePeriodsInCache (account: T): Promise { let periods: Period[] = []; @@ -64,7 +64,7 @@ export async function updateAttendancePeriodsInCache (accoun break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.Attendance, account.localID); + const service = getFeatureAccount(MultiServiceFeature.Attendance, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } @@ -126,7 +126,7 @@ export async function updateAttendanceInCache (account: T, p break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.Attendance, account.localID); + const service = getFeatureAccount(MultiServiceFeature.Attendance, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } diff --git a/src/services/grades.ts b/src/services/grades.ts index 25c2116ff..ebc25bbb8 100644 --- a/src/services/grades.ts +++ b/src/services/grades.ts @@ -4,8 +4,8 @@ import type { Period } from "./shared/Period"; import type { AverageOverview, Grade } from "./shared/Grade"; import {error } from "@/utils/logger/logger"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; -import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature} from "@/stores/multiService/types"; +import {getFeatureAccount} from "@/utils/multiservice"; const getDefaultPeriod = (periods: Period[]): string => { const now = Date.now(); @@ -57,7 +57,7 @@ export async function updateGradesPeriodsInCache (account: T break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.Grades, account.localID); + const service = getFeatureAccount(MultiServiceFeature.Grades, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } @@ -130,7 +130,7 @@ export async function updateGradesAndAveragesInCache (accoun break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.Grades, account.localID); + const service = getFeatureAccount(MultiServiceFeature.Grades, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } diff --git a/src/services/homework.ts b/src/services/homework.ts index f91f72775..57b3beff3 100644 --- a/src/services/homework.ts +++ b/src/services/homework.ts @@ -7,8 +7,8 @@ import { pronoteFirstDate } from "./pronote/timetable"; import { dateToEpochWeekNumber, epochWNToPronoteWN } from "@/utils/epochWeekNumber"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { useClassSubjectStore } from "@/stores/classSubject"; -import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature} from "@/stores/multiService/types"; +import {getFeatureAccount} from "@/utils/multiservice"; /** * Updates the state and cache for the homework of given week number. @@ -47,9 +47,10 @@ export async function updateHomeworkForWeekInCache (account: break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); + const service = getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + console.info(`[updateHomeworkForWeekInCache]: updating to empty since multi-service space has no account set for homeworks.`); + break; } return updateHomeworkForWeekInCache(service, date); } @@ -80,7 +81,7 @@ export async function toggleHomeworkState (account: T, homew break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); + const service = getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } diff --git a/src/services/news.ts b/src/services/news.ts index bcc11702c..c05bcb538 100644 --- a/src/services/news.ts +++ b/src/services/news.ts @@ -5,8 +5,8 @@ import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { error } from "@/utils/logger/logger"; import { newsRead } from "pawnote"; import { ca } from "date-fns/locale"; -import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature} from "@/stores/multiService/types"; +import {getFeatureAccount} from "@/utils/multiservice"; /** * Updates the state and cache for the news. @@ -46,7 +46,7 @@ export async function updateNewsInCache (account: T): Promis break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.News, account.localID); + const service = getFeatureAccount(MultiServiceFeature.News, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } @@ -80,7 +80,7 @@ export async function setNewsRead (account: T, message: Info case AccountService.Multi: break; case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.News, account.localID); + const service = getFeatureAccount(MultiServiceFeature.News, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } diff --git a/src/services/timetable.ts b/src/services/timetable.ts index ca442e0a5..3db8f4793 100644 --- a/src/services/timetable.ts +++ b/src/services/timetable.ts @@ -4,8 +4,8 @@ import { epochWNToPronoteWN, weekNumberToDateRange } from "@/utils/epochWeekNumb import { checkIfSkoSupported } from "./skolengo/default-personalization"; import { error } from "@/utils/logger/logger"; import { fetchIcalData } from "./local/ical"; -import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature} from "@/stores/multiService/types"; +import {getFeatureAccount} from "@/utils/multiservice"; /** * Updates the state and cache for the timetable of given week number. @@ -48,7 +48,7 @@ export async function updateTimetableForWeekInCache (account break; } case AccountService.PapillonMultiService: { - const service = useMultiService().getFeatureAccount(MultiServiceFeature.Timetable, account.localID); + const service = getFeatureAccount(MultiServiceFeature.Timetable, account.localID); if (!service) { throw new Error("No service set in multi-service space"); } diff --git a/src/utils/multiservice/index.ts b/src/utils/multiservice/index.ts new file mode 100644 index 000000000..071d6151e --- /dev/null +++ b/src/utils/multiservice/index.ts @@ -0,0 +1,17 @@ +import {MultiServiceFeature} from "@/stores/multiService/types"; +import {useAccounts} from "@/stores/account"; +import {useMultiService} from "@/stores/multiService"; +import {PrimaryAccount} from "@/stores/account/types"; + +export function getFeatureAccount (feature: MultiServiceFeature, spaceLocalID: string) { + const accounts = useAccounts().accounts; + const accountId = useMultiService().getFeatureAccountId(feature, spaceLocalID); + const space = useMultiService().spaces.find(space => space.accountLocalID === spaceLocalID); + const featureAccount = accounts.find(account => account.localID === accountId) as PrimaryAccount; + + if (!space || !featureAccount || !accountId) return undefined; + + featureAccount.authentication = space.authentication[accountId].authentication; + featureAccount.instance = space.authentication[accountId].instance; + return featureAccount; +} From 2732a0ae799129a7d2b9d45473ae6078f4f1dfa5 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 18:19:45 +0100 Subject: [PATCH 039/102] fix: new types and structure: using accounts ids instead of copying account object --- src/stores/account/index.ts | 26 +++++++++++++++++++++++++- src/stores/multiService/index.ts | 8 ++++---- src/stores/multiService/types.ts | 17 +++++++++++++++-- src/utils/multiservice/index.ts | 4 ++-- 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index 77e9fc695..d96795f4f 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -18,6 +18,7 @@ import { useGradesStore } from "../grades"; import { useNewsStore } from "../news"; import { useAttendanceStore } from "../attendance"; import { info, log } from "@/utils/logger/logger"; +import {useMultiService} from "@/stores/multiService"; /** * Store for the currently selected account. @@ -82,7 +83,30 @@ export const useCurrentAccount = create()((set, get) => ({ })); // Account is currently not authenticated, - if (typeof account.instance === "undefined") { + if (account.service === AccountService.PapillonMultiService) { + log("switching to virtual space, reloading all accounts...", "[switchTo]"); + const space = useMultiService().spaces.find(space => space.accountLocalID === account.localID); + if (!space) { + log("Uh oh, no space found, cannot switch to...", "[switchTo]"); + return; + } + let seenAccountsIds: string[] = []; + const spaceAccountsIds: string[] = Object.values(space.featuresServices); + const accounts = useAccounts().accounts.filter(account => spaceAccountsIds.includes(account.localID)); + for (const account of accounts) { + if (account) { + if (!seenAccountsIds.includes(account.localID) && typeof account.instance === "undefined") { + log(`instance undefined for ${account.localID} reloading...`, "[switchTo]"); + const { instance, authentication } = await reload(account); + // TODO: set instance by account + // get().mutateProperty("authentication", authentication); + // get().mutateProperty("instance", instance); + log("instance reload done !", "[switchTo]"); + } + seenAccountsIds.push(account.localID); + } + } + } else if (typeof account.instance === "undefined") { log("instance undefined, reloading...", "[switchTo]"); // Automatically reconnect the main instance. const { instance, authentication } = await reload(account); diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index 345344dec..30350ae9f 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -80,7 +80,7 @@ export const useMultiService = create()( if (!space) return; let mutatedFeatureServices = space.featuresServices; - mutatedFeatureServices[feature] = account; + mutatedFeatureServices[feature] = account.localID; const spaceMutated: MultiServiceSpace = { ...space, @@ -96,10 +96,10 @@ export const useMultiService = create()( })); }, - getFeatureAccount: (feature, spaceLocalID) => { - // Find the account to update in the storage. + getFeatureAccountId: (feature, spaceLocalID) => { + // Find the account associated to the feature const space = get().spaces.find((space) => space.accountLocalID === spaceLocalID); - if (!space) return null; + if (!space) return undefined; return space.featuresServices[feature]; }, diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index b436fb560..6218be6fb 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -12,8 +12,21 @@ export interface MultiServiceSpace { accountLocalID: string name: string image?: string + // TODO use account ids instead: less disk space + supports changes + /* + Each feature returns its linked account localID + */ featuresServices: { - [key in MultiServiceFeature]?: PrimaryAccount | null + [key in MultiServiceFeature]?: string + } + /* + Each key represents an account id, and is associated to its instance and authentication objects + */ + authentication: { + [key: string]: { + authentication: any + instance: any + } | undefined } } @@ -25,5 +38,5 @@ export interface MultiServiceStore { update: (localID: string, key: T, value: A[T]) => void toggleEnabledState: () => void setFeatureAccount: (spaceLocalID: string, feature: MultiServiceFeature, account: PrimaryAccount) => void - getFeatureAccount: (feature: MultiServiceFeature, spaceLocalID: string) => PrimaryAccount | null | undefined + getFeatureAccountId: (feature: MultiServiceFeature, spaceLocalID: string) => string | undefined } diff --git a/src/utils/multiservice/index.ts b/src/utils/multiservice/index.ts index 071d6151e..b666e2949 100644 --- a/src/utils/multiservice/index.ts +++ b/src/utils/multiservice/index.ts @@ -11,7 +11,7 @@ export function getFeatureAccount (feature: MultiServiceFeature, spaceLocalID: s if (!space || !featureAccount || !accountId) return undefined; - featureAccount.authentication = space.authentication[accountId].authentication; - featureAccount.instance = space.authentication[accountId].instance; + featureAccount.authentication = space.authentication[accountId]?.authentication; + featureAccount.instance = space.authentication[accountId]?.instance; return featureAccount; } From be64ca2e9837223ea4a06c96c30bef62b8a299ea Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 18:27:05 +0100 Subject: [PATCH 040/102] fix: adapted settings to new types and structure --- src/views/settings/SettingsMultiService.tsx | 11 ++++++----- src/views/settings/SettingsMultiServiceSpace.tsx | 12 +++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 3901bd99a..1d69e2f18 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -88,12 +88,13 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => const space: MultiServiceSpace = { accountLocalID: localID, featuresServices: { - Grades: null, - Timetable: null, - Homeworks: null, - Attendance: null, - News: null + grades: undefined, + timetable: undefined, + news: undefined, + homeworks: undefined, + attendance: undefined }, + authentication: {}, name: spaceName, image: selectedImage || undefined }; diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index 0b6d200c8..c0933122a 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -6,14 +6,13 @@ import { KeyboardAvoidingView, Pressable, ScrollView, - Text, TextInput, View } from "react-native"; import {useTheme} from "@react-navigation/native"; import type {Screen} from "@/router/helpers/types"; import {NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; -import {Camera, Check, ChevronDown, CircleAlert, TextCursorInput, Trash2, Type, User2} from "lucide-react-native"; +import {Camera, ChevronDown, CircleAlert, TextCursorInput, Trash2, Type, User2} from "lucide-react-native"; import {useAccounts} from "@/stores/account"; import {AccountService, PrimaryAccount} from "@/stores/account/types"; import * as ImagePicker from "expo-image-picker"; @@ -21,9 +20,8 @@ import {useSafeAreaInsets} from "react-native-safe-area-context"; import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature} from "@/stores/multiService/types"; import LottieView from "lottie-react-native"; -import {anim2Papillon, animPapillon} from "@/utils/ui/animations"; +import {anim2Papillon} from "@/utils/ui/animations"; import Reanimated, {FadeOut, ZoomIn} from "react-native-reanimated"; -import {defaultProfilePicture} from "@/utils/ui/default-profile-picture"; import PapillonBottomSheet from "@/components/Modals/PapillonBottomSheet"; import * as Haptics from "expo-haptics"; import AccountItem from "@/components/Global/AccountItem"; @@ -87,7 +85,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga }; const openAccountSelector = (feature: MultiServiceFeature) => { - setSelectedAccount(space.featuresServices[feature] || null); + setSelectedAccount(availableAccounts.find(account => account.localID === space.featuresServices[feature]) || null); setFeatureSelection(feature); setAccountSelectorOpened(true); }; @@ -171,7 +169,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga {!selectedImage ? ( - Personnalisez votre espace en ajoutant une photo. + Personnalise ton espace en ajoutant une photo. ) : ( @@ -333,7 +331,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga {feature.name} {space.featuresServices[feature.feature] ? ( - account.localID === space.featuresServices[feature.feature]) as PrimaryAccount} endCheckMark={false} additionalStyles={{ paddingStart: 10, borderBottomWidth: 1, backgroundColor: theme.dark ? theme.colors.primary + "09" : theme.colors.primary + "11", From e3a4f0ae2d848a1201525cb55eee2278a16feab6 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 19:01:21 +0100 Subject: [PATCH 041/102] fix: removed breaking hooks code --- src/stores/account/index.ts | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index d96795f4f..b73ad49f6 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -18,7 +18,6 @@ import { useGradesStore } from "../grades"; import { useNewsStore } from "../news"; import { useAttendanceStore } from "../attendance"; import { info, log } from "@/utils/logger/logger"; -import {useMultiService} from "@/stores/multiService"; /** * Store for the currently selected account. @@ -82,31 +81,10 @@ export const useCurrentAccount = create()((set, get) => ({ return store.persist.rehydrate(); })); - // Account is currently not authenticated, + // Special case for spaces if (account.service === AccountService.PapillonMultiService) { - log("switching to virtual space, reloading all accounts...", "[switchTo]"); - const space = useMultiService().spaces.find(space => space.accountLocalID === account.localID); - if (!space) { - log("Uh oh, no space found, cannot switch to...", "[switchTo]"); - return; - } - let seenAccountsIds: string[] = []; - const spaceAccountsIds: string[] = Object.values(space.featuresServices); - const accounts = useAccounts().accounts.filter(account => spaceAccountsIds.includes(account.localID)); - for (const account of accounts) { - if (account) { - if (!seenAccountsIds.includes(account.localID) && typeof account.instance === "undefined") { - log(`instance undefined for ${account.localID} reloading...`, "[switchTo]"); - const { instance, authentication } = await reload(account); - // TODO: set instance by account - // get().mutateProperty("authentication", authentication); - // get().mutateProperty("instance", instance); - log("instance reload done !", "[switchTo]"); - } - seenAccountsIds.push(account.localID); - } - } - } else if (typeof account.instance === "undefined") { + log("switching to virtual space, skipping account reload...", "[switchTo]"); + } else if (typeof account.instance === "undefined") { // Account is currently not authenticated, log("instance undefined, reloading...", "[switchTo]"); // Automatically reconnect the main instance. const { instance, authentication } = await reload(account); From d743e730e13f3b8ed9d9ce2d7bbe714ebf849a55 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 19:01:23 +0100 Subject: [PATCH 042/102] fix: removed breaking hooks code --- src/utils/multiservice/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/multiservice/index.ts b/src/utils/multiservice/index.ts index b666e2949..d83150559 100644 --- a/src/utils/multiservice/index.ts +++ b/src/utils/multiservice/index.ts @@ -4,9 +4,9 @@ import {useMultiService} from "@/stores/multiService"; import {PrimaryAccount} from "@/stores/account/types"; export function getFeatureAccount (feature: MultiServiceFeature, spaceLocalID: string) { - const accounts = useAccounts().accounts; - const accountId = useMultiService().getFeatureAccountId(feature, spaceLocalID); - const space = useMultiService().spaces.find(space => space.accountLocalID === spaceLocalID); + const accounts = useAccounts.getState().accounts; + const accountId = useMultiService.getState().getFeatureAccountId(feature, spaceLocalID); + const space = useMultiService.getState().spaces.find(space => space.accountLocalID === spaceLocalID); const featureAccount = accounts.find(account => account.localID === accountId) as PrimaryAccount; if (!space || !featureAccount || !accountId) return undefined; From 163b77a44036cf654b396393d4d0dd7ffe5f5c4b Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 19:01:52 +0100 Subject: [PATCH 043/102] fix: changed space account type --- src/stores/account/types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 6a44ec53e..4af189660 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -247,7 +247,8 @@ export interface PapillonMultiServiceSpace extends BaseAccount { authentication: null identityProvider: { name: string - } + }, + linkedExternalLocalIDs: string[] } export type PrimaryAccount = ( From 442b50b6ba0cc8605e84073ba709a09b1592a194 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 19:04:15 +0100 Subject: [PATCH 044/102] fix: set accounts ids as external accounts to reload --- src/stores/multiService/types.ts | 9 --------- src/views/settings/SettingsMultiServiceSpace.tsx | 5 +++++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index 6218be6fb..344afde40 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -19,15 +19,6 @@ export interface MultiServiceSpace { featuresServices: { [key in MultiServiceFeature]?: string } - /* - Each key represents an account id, and is associated to its instance and authentication objects - */ - authentication: { - [key: string]: { - authentication: any - instance: any - } | undefined - } } export interface MultiServiceStore { diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index c0933122a..ccb23b3c9 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -92,6 +92,10 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga const setAccountFeature = (account: PrimaryAccount, feature: MultiServiceFeature) => { setMultiServiceSpaceAccountFeature(space.accountLocalID, feature, account); + let linkedAccountsIds = [...(linkedAccount?.linkedExternalLocalIDs || []), account.localID]; + linkedAccountsIds = linkedAccountsIds.filter((value, index) => linkedAccountsIds.indexOf(value) === index); // Remove duplicates + // Putting the space's associated accounts ids in linkedExternalLocalIDs permits the reload of their instance / authentication fields (like externals accounts) + accounts.update(space.accountLocalID, "linkedExternalLocalIDs", linkedAccountsIds); setAccountSelectorOpened(false); setSelectedAccount(null); }; @@ -292,6 +296,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga {features.map((feature, index) => ( <> Date: Thu, 2 Jan 2025 19:10:43 +0100 Subject: [PATCH 045/102] fix: set accounts ids as external accounts to reload --- src/views/settings/SettingsMultiService.tsx | 22 ++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 1d69e2f18..375a6a4d2 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -16,6 +16,7 @@ import {MultiServiceSpace} from "@/stores/multiService/types"; import {AccountService, PapillonMultiServiceSpace} from "@/stores/account/types"; import uuid from "@/utils/uuid-v4"; import {defaultProfilePicture} from "@/utils/ui/default-profile-picture"; +import {defaultTabs} from "@/consts/DefaultTabs"; const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => { const theme = useTheme(); @@ -63,7 +64,15 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => const localID = uuid(); - // TODO: have student name and space title + const defaultSpaceTabs = [ + "Home", + "Lessons", + "Homeworks", + "Grades", + "News", + "Attendance" + ] as typeof defaultTabs[number]["tab"][]; + const linkedAccount: PapillonMultiServiceSpace = { isExternal: false, linkedExternalLocalIDs: [], @@ -76,7 +85,11 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => localID: localID, name: spaceName, personalization: { - profilePictureB64: selectedImage || undefined + profilePictureB64: selectedImage || undefined, + tabs: defaultTabs.filter(current => defaultSpaceTabs.includes(current.tab)).map((tab, index) => ({ + name: tab.tab, + enabled: index <= 4 + })) }, service: AccountService.PapillonMultiService, studentName: { // TODO @@ -94,7 +107,6 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => homeworks: undefined, attendance: undefined }, - authentication: {}, name: spaceName, image: selectedImage || undefined }; @@ -159,9 +171,9 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => <> - {multiServiceSpaces.map(space => ( + {multiServiceSpaces.map((space, index) => ( navigation.navigate("SettingsMultiServiceSpace", { space })} leading={ Date: Thu, 2 Jan 2025 23:17:43 +0100 Subject: [PATCH 046/102] fix: updated account type to support new property `associatedAccountsIds`, to store space's associated accounts --- src/stores/account/index.ts | 24 +++++++++++++++++++----- src/stores/account/types.ts | 28 ++++++++++++++++++---------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index b73ad49f6..dc388ec54 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -26,6 +26,8 @@ import { info, log } from "@/utils/logger/logger"; export const useCurrentAccount = create()((set, get) => ({ account: null, linkedAccounts: [], + // For multi service, to not mix Primary & External accounts + associatedAccounts: [], mutateProperty: (key: T, value: PrimaryAccount[T]) => { log(`mutate property ${key} in storage`, "current:update"); @@ -81,9 +83,11 @@ export const useCurrentAccount = create()((set, get) => ({ return store.persist.rehydrate(); })); + const accounts = useAccounts.getState().accounts; + // Special case for spaces if (account.service === AccountService.PapillonMultiService) { - log("switching to virtual space, skipping account reload...", "[switchTo]"); + log("switching to virtual space, reloading associated accounts...", "[switchTo]"); } else if (typeof account.instance === "undefined") { // Account is currently not authenticated, log("instance undefined, reloading...", "[switchTo]"); // Automatically reconnect the main instance. @@ -93,12 +97,15 @@ export const useCurrentAccount = create()((set, get) => ({ log("instance reload done !", "[switchTo]"); } - const accounts = useAccounts.getState().accounts; const linkedAccounts = account.linkedExternalLocalIDs.map((linkedID) => { return {...accounts.find((acc) => acc.localID === linkedID)}; }).filter(Boolean) as ExternalAccount[] ?? []; - info(`found ${linkedAccounts.length} external accounts`, "switchTo"); + const associatedAccounts = account.associatedAccountsLocalIDs?.map((associatedID) => { + return {...accounts.find((acc) => acc.localID === associatedID)}; + }).filter(Boolean) as PrimaryAccount[] ?? []; + + info(`found ${linkedAccounts.length} external accounts and ${associatedAccounts.length} associated accounts`, "switchTo"); for (const linkedAccount of linkedAccounts) { const { instance, authentication } = await reload(linkedAccount); @@ -107,9 +114,16 @@ export const useCurrentAccount = create()((set, get) => ({ log("reloaded external", "[switchTo]"); } - log("reloaded all external accounts", "[switchTo]"); + for (const associatedAccount of associatedAccounts) { + const { instance, authentication } = await reload(associatedAccount); + associatedAccount.instance = instance; + associatedAccount.authentication = authentication; + log("reloaded associated account", "[switchTo]"); + } + + log("reloaded all external and associated accounts", "[switchTo]"); - set({ linkedAccounts }); + set({ linkedAccounts, associatedAccounts }); log(`done reading ${account.name} and rehydrating stores.`, "[switchTo]"); }, diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 4af189660..1acdf5cbc 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -86,6 +86,7 @@ export interface CurrentAccountStore { /** Si un compte est en cours d'utilisation, on obtient l'ID, sinon `null`. */ account: PrimaryAccount | null linkedAccounts: ExternalAccount[] + associatedAccounts: PrimaryAccount[] mutateProperty: (key: T, value: PrimaryAccount[T]) => void linkExistingExternalAccount: (account: ExternalAccount) => void switchTo: (account: PrimaryAccount) => Promise @@ -146,6 +147,7 @@ export interface PronoteAccount extends BaseAccount { deviceUUID: string } identityProvider?: undefined + associatedAccountsLocalIDs?: undefined } export interface EcoleDirecteAccount extends BaseAccount { @@ -156,6 +158,7 @@ export interface EcoleDirecteAccount extends BaseAccount { account: PawdirecteAccount } identityProvider?: undefined + associatedAccountsLocalIDs?: undefined } export interface SkolengoAccount extends BaseAccount { @@ -164,6 +167,7 @@ export interface SkolengoAccount extends BaseAccount { authentication: SkolengoAuthConfig userInfo: ScolengoAPIUser identityProvider?: undefined + associatedAccountsLocalIDs?: undefined } export interface MultiAccount extends BaseAccount { @@ -174,6 +178,7 @@ export interface MultiAccount extends BaseAccount { refreshAuthToken: string } identityProvider?: undefined + associatedAccountsLocalIDs?: undefined } export interface LocalAccount extends BaseAccount { @@ -193,8 +198,21 @@ export interface LocalAccount extends BaseAccount { username: string password: string } + + associatedAccountsLocalIDs?: undefined +} + +export interface PapillonMultiServiceSpace extends BaseAccount { + service: AccountService.PapillonMultiService + instance: null + authentication: null + identityProvider: { + name: string + }, + associatedAccountsLocalIDs: string[] } + export interface TurboselfAccount extends BaseExternalAccount { service: AccountService.Turboself instance: undefined @@ -241,16 +259,6 @@ export interface IzlyAccount extends BaseExternalAccount { } } -export interface PapillonMultiServiceSpace extends BaseAccount { - service: AccountService.PapillonMultiService - instance: null - authentication: null - identityProvider: { - name: string - }, - linkedExternalLocalIDs: string[] -} - export type PrimaryAccount = ( | PronoteAccount | EcoleDirecteAccount From a011ba8cd0513938fbb01572af0b8bd5cfc81dd2 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 23:18:13 +0100 Subject: [PATCH 047/102] fix: updated getAccountFeature to dynamiclly add instance & authentication fields --- src/utils/multiservice/index.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/utils/multiservice/index.ts b/src/utils/multiservice/index.ts index d83150559..9be274fa2 100644 --- a/src/utils/multiservice/index.ts +++ b/src/utils/multiservice/index.ts @@ -1,17 +1,16 @@ import {MultiServiceFeature} from "@/stores/multiService/types"; -import {useAccounts} from "@/stores/account"; +import {useAccounts, useCurrentAccount} from "@/stores/account"; import {useMultiService} from "@/stores/multiService"; import {PrimaryAccount} from "@/stores/account/types"; export function getFeatureAccount (feature: MultiServiceFeature, spaceLocalID: string) { const accounts = useAccounts.getState().accounts; const accountId = useMultiService.getState().getFeatureAccountId(feature, spaceLocalID); - const space = useMultiService.getState().spaces.find(space => space.accountLocalID === spaceLocalID); - const featureAccount = accounts.find(account => account.localID === accountId) as PrimaryAccount; - - if (!space || !featureAccount || !accountId) return undefined; - - featureAccount.authentication = space.authentication[accountId]?.authentication; - featureAccount.instance = space.authentication[accountId]?.instance; + const featureAccount = accounts.find(account => account.localID === accountId) as PrimaryAccount | undefined; + if (featureAccount) { + const linkedAccount = useCurrentAccount.getState().associatedAccounts.find(account => account.localID === accountId) as PrimaryAccount; + featureAccount.instance = linkedAccount?.instance; + featureAccount.authentication = linkedAccount?.authentication; + } return featureAccount; } From ddd29d2ca0638212bebe4bc018e33e0d2535af57 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 23:18:28 +0100 Subject: [PATCH 048/102] fix: changes to support new types --- src/views/settings/SettingsMultiService.tsx | 3 ++- src/views/settings/SettingsMultiServiceSpace.tsx | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 375a6a4d2..559dcd051 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -76,6 +76,7 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => const linkedAccount: PapillonMultiServiceSpace = { isExternal: false, linkedExternalLocalIDs: [], + associatedAccountsLocalIDs: [], authentication: null, identity: {}, identityProvider: { @@ -92,7 +93,7 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => })) }, service: AccountService.PapillonMultiService, - studentName: { // TODO + studentName: { first: currentAccount.account?.studentName.first || "", last: currentAccount.account?.studentName.last || "" } diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index ccb23b3c9..33c704f73 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -95,7 +95,8 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga let linkedAccountsIds = [...(linkedAccount?.linkedExternalLocalIDs || []), account.localID]; linkedAccountsIds = linkedAccountsIds.filter((value, index) => linkedAccountsIds.indexOf(value) === index); // Remove duplicates // Putting the space's associated accounts ids in linkedExternalLocalIDs permits the reload of their instance / authentication fields (like externals accounts) - accounts.update(space.accountLocalID, "linkedExternalLocalIDs", linkedAccountsIds); + // @ts-expect-error + accounts.update(space.accountLocalID, "associatedAccountsLocalIDs", linkedAccountsIds); setAccountSelectorOpened(false); setSelectedAccount(null); }; @@ -149,6 +150,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga selectPicture()} leading={(selectedImage || space.image) && @@ -190,6 +192,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga spaceNameRef.current?.focus()} chevron={false} icon={} @@ -228,6 +231,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga firstNameRef.current?.focus()} chevron={false} icon={} @@ -257,6 +261,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga lastNameRef.current?.focus()} chevron={false} icon={} @@ -296,7 +301,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga {features.map((feature, index) => ( <> = ({ naviga > {feature.name} - {space.featuresServices[feature.feature] ? ( + {accounts.accounts.find(account => account.localID === space.featuresServices[feature.feature]) ? ( account.localID === space.featuresServices[feature.feature]) as PrimaryAccount} endCheckMark={false} additionalStyles={{ paddingStart: 10, borderBottomWidth: 1, @@ -344,6 +349,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga }}/> ): ( } separator={true} > From a2f740bb472126e1853cd768104a61601bbf7e55 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Thu, 2 Jan 2025 23:31:00 +0100 Subject: [PATCH 049/102] fix: wrong property --- src/views/settings/SettingsMultiServiceSpace.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index 33c704f73..a6e05fe1c 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -92,7 +92,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga const setAccountFeature = (account: PrimaryAccount, feature: MultiServiceFeature) => { setMultiServiceSpaceAccountFeature(space.accountLocalID, feature, account); - let linkedAccountsIds = [...(linkedAccount?.linkedExternalLocalIDs || []), account.localID]; + let linkedAccountsIds = [...(linkedAccount?.associatedAccountsLocalIDs || []), account.localID]; linkedAccountsIds = linkedAccountsIds.filter((value, index) => linkedAccountsIds.indexOf(value) === index); // Remove duplicates // Putting the space's associated accounts ids in linkedExternalLocalIDs permits the reload of their instance / authentication fields (like externals accounts) // @ts-expect-error From 680bae351673548892f20fa105b1d06fa2de4412 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 12:51:04 +0100 Subject: [PATCH 050/102] fix: removed TODO --- src/stores/multiService/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index 344afde40..311ca3816 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -12,7 +12,6 @@ export interface MultiServiceSpace { accountLocalID: string name: string image?: string - // TODO use account ids instead: less disk space + supports changes /* Each feature returns its linked account localID */ From 9b51668df3ad9e6cc67fba05a297c6b441a1b91c Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 12:56:49 +0100 Subject: [PATCH 051/102] feat: added more features --- src/stores/multiService/types.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index 311ca3816..e135b33b2 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -5,7 +5,9 @@ export enum MultiServiceFeature { Timetable = "timetable", Homeworks = "homeworks", Attendance = "attendance", - News = "news" + News = "news", + Evaluations = "evaluations", + Messages = "messages" } export interface MultiServiceSpace { From 7446453d9aeb8aada89ce4a8a1f762d572af1c8d Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 12:56:59 +0100 Subject: [PATCH 052/102] feat: features in settings --- src/views/settings/SettingsMultiServiceSpace.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index a6e05fe1c..5b45ef740 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -109,6 +109,11 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga feature: MultiServiceFeature.Grades, icon: require("@/../assets/lottie/tab_chart.json") }, + { + name: "Compétences", + feature: MultiServiceFeature.Evaluations, + icon: require("@/../assets/lottie/tab_evaluations.json") + }, { name: "Emploi du temps", feature: MultiServiceFeature.Timetable, @@ -128,6 +133,11 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga name: "Actualités", feature: MultiServiceFeature.News, icon: require("@/../assets/lottie/tab_news.json") + }, + { + name: "Messages", + feature: MultiServiceFeature.Messages, + icon: require("@/../assets/lottie/tab_chat.json") } ]; From c4c8af32cdf38750422e7ffc75e5fd97787c2130 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 12:58:20 +0100 Subject: [PATCH 053/102] feat: space support for evaluations --- src/services/evaluation.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/services/evaluation.ts b/src/services/evaluation.ts index 351881bd2..c15b99e16 100644 --- a/src/services/evaluation.ts +++ b/src/services/evaluation.ts @@ -3,6 +3,8 @@ import type { Period } from "./shared/Period"; import {useEvaluationStore} from "@/stores/evaluation"; import {Evaluation} from "@/services/shared/Evaluation"; import {error} from "@/utils/logger/logger"; +import {getFeatureAccount} from "@/utils/multiservice"; +import {MultiServiceFeature} from "@/stores/multiService/types"; const getDefaultPeriod = (periods: Period[]): string => { const now = Date.now(); @@ -24,6 +26,13 @@ export async function updateEvaluationPeriodsInCache (accoun break; } + case AccountService.PapillonMultiService: { + const service = getFeatureAccount(MultiServiceFeature.Evaluations, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return await updateEvaluationPeriodsInCache(service, periodName); + } default: throw new Error("Service not implemented"); } @@ -41,6 +50,13 @@ export async function updateEvaluationsInCache (account: T, evaluations = await getEvaluations(account, periodName); break; } + case AccountService.PapillonMultiService: { + const service = getFeatureAccount(MultiServiceFeature.Evaluations, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return await updateEvaluationsInCache(service, periodName); + } default: throw new Error(`Service (${AccountService[account.service]}) not implemented for this request`); } @@ -49,4 +65,4 @@ export async function updateEvaluationsInCache (account: T, catch (err) { error(`not updated, see:${err}`, "updateGradesAndAveragesInCache"); } -} \ No newline at end of file +} From 3254b96e53059050c88d0e7cad224e010ce08c6c Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 12:59:58 +0100 Subject: [PATCH 054/102] fix: changed feature name --- src/stores/multiService/types.ts | 2 +- src/views/settings/SettingsMultiServiceSpace.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stores/multiService/types.ts b/src/stores/multiService/types.ts index e135b33b2..42795b55a 100644 --- a/src/stores/multiService/types.ts +++ b/src/stores/multiService/types.ts @@ -7,7 +7,7 @@ export enum MultiServiceFeature { Attendance = "attendance", News = "news", Evaluations = "evaluations", - Messages = "messages" + Chats = "chats" } export interface MultiServiceSpace { diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index 5b45ef740..9d9a46a96 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -135,8 +135,8 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga icon: require("@/../assets/lottie/tab_news.json") }, { - name: "Messages", - feature: MultiServiceFeature.Messages, + name: "Discussions", + feature: MultiServiceFeature.Chats, icon: require("@/../assets/lottie/tab_chat.json") } ]; From 445901d1030c23739b38024f949bfd7969861b45 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 13:01:00 +0100 Subject: [PATCH 055/102] fix: too many parameters for `updateEvaluationPeriodsInCache` --- src/services/evaluation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/evaluation.ts b/src/services/evaluation.ts index c15b99e16..1656bd596 100644 --- a/src/services/evaluation.ts +++ b/src/services/evaluation.ts @@ -31,7 +31,7 @@ export async function updateEvaluationPeriodsInCache (accoun if (!service) { throw new Error("No service set in multi-service space"); } - return await updateEvaluationPeriodsInCache(service, periodName); + return await updateEvaluationPeriodsInCache(service); } default: throw new Error("Service not implemented"); From 772e3ce99b3bfd513624fa4c91a5956def4cc20d Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 13:54:33 +0100 Subject: [PATCH 056/102] fix: modified account types to resolve type errors --- src/stores/account/types.ts | 4 +++- src/views/settings/SettingsMultiService.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 1acdf5cbc..8a28d7422 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -207,7 +207,9 @@ export interface PapillonMultiServiceSpace extends BaseAccount { instance: null authentication: null identityProvider: { - name: string + name: string, + identifier: undefined, + rawData: undefined }, associatedAccountsLocalIDs: string[] } diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 559dcd051..c6598378e 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -80,7 +80,9 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => authentication: null, identity: {}, identityProvider: { - name: spaceName + name: spaceName, + identifier: undefined, + rawData: undefined }, instance: null, localID: localID, From da40057a0e5d5db01d720dae4ec6ffb3684ecb76 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 13:54:39 +0100 Subject: [PATCH 057/102] feat: multi-service support for chats --- src/services/chats.ts | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/services/chats.ts b/src/services/chats.ts index c6d581274..b3ac838df 100644 --- a/src/services/chats.ts +++ b/src/services/chats.ts @@ -1,6 +1,8 @@ import { type Account, AccountService } from "@/stores/account/types"; import type { Chat, ChatMessage, ChatRecipient } from "./shared/Chat"; import type { Recipient } from "./shared/Recipient"; +import {getFeatureAccount} from "@/utils/multiservice"; +import {MultiServiceFeature} from "@/stores/multiService/types"; export const getChats = async (account: T): Promise> => { switch (account.service) { @@ -12,6 +14,13 @@ export const getChats = async (account: T): Promise (account: T, chat: Ch // TODO return []; } + case AccountService.PapillonMultiService: { + const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return await getChatRecipients(service, chat); + } default: console.info(`[getChatRecipients]: returning empty since ${account.service} not implemented.`); return []; @@ -43,6 +59,13 @@ export const sendMessageInChat = async (account: T, chat: Ch case AccountService.EcoleDirecte: { // TODO } + case AccountService.PapillonMultiService: { + const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return await sendMessageInChat(service, chat, content); + } default: console.info("[sendMessageInChat]: Not Implementend."); } @@ -58,6 +81,13 @@ export const getChatMessages = async (account: T, chat: Chat const { getChatMessages } = await import("./ecoledirecte/chats"); return [await getChatMessages(account, chat)]; } + case AccountService.PapillonMultiService: { + const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return await getChatMessages(service, chat); + } default: console.info(`[getChatMessages]: returning empty since ${account.service} not implemented.`); return []; @@ -70,6 +100,13 @@ export const createDiscussionRecipients = async (account: T) const { createDiscussionRecipients } = await import("./pronote/chats"); return createDiscussionRecipients(account); } + case AccountService.PapillonMultiService: { + const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return await createDiscussionRecipients(service); + } default: console.info(`[createDiscussionRecipients]: returning empty since ${account.service} not implemented.`); return []; @@ -83,6 +120,13 @@ export const createDiscussion = async (account: T, subject: createDiscussion(account, subject, content, recipients); break; } + case AccountService.PapillonMultiService: { + const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); + if (!service) { + throw new Error("No service set in multi-service space"); + } + return await createDiscussion(service, subject, content, recipients); + } default: console.info(`[createDiscussion]: doing nothing since ${account.service} is not implemented.`); } From 75b44a20d9d1edb29ce4ec5aae9cebb1ee9dc15e Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 13:55:52 +0100 Subject: [PATCH 058/102] fix: linter --- src/services/homework.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/homework.ts b/src/services/homework.ts index 57b3beff3..a5d8d65a0 100644 --- a/src/services/homework.ts +++ b/src/services/homework.ts @@ -49,7 +49,7 @@ export async function updateHomeworkForWeekInCache (account: case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); if (!service) { - console.info(`[updateHomeworkForWeekInCache]: updating to empty since multi-service space has no account set for homeworks.`); + console.info("[updateHomeworkForWeekInCache]: updating to empty since multi-service space has no account set for homeworks."); break; } return updateHomeworkForWeekInCache(service, date); From e89f62a2d90693870887e44ceee46cbeb7280093 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 13:59:31 +0100 Subject: [PATCH 059/102] fix: better implementation in grades --- src/services/grades.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/grades.ts b/src/services/grades.ts index ebc25bbb8..5b04c4dfe 100644 --- a/src/services/grades.ts +++ b/src/services/grades.ts @@ -61,7 +61,7 @@ export async function updateGradesPeriodsInCache (account: T if (!service) { throw new Error("No service set in multi-service space"); } - return updateGradesPeriodsInCache(service); + return await updateGradesPeriodsInCache(service); } default: throw new Error("Service not implemented"); @@ -134,7 +134,7 @@ export async function updateGradesAndAveragesInCache (accoun if (!service) { throw new Error("No service set in multi-service space"); } - return updateGradesAndAveragesInCache(service, periodName); + return await updateGradesAndAveragesInCache(service, periodName); } default: throw new Error(`Service (${AccountService[account.service]}) not implemented for this request`); From 3519dde875ce90be35064fba4119133746d50aae Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 14:04:37 +0100 Subject: [PATCH 060/102] fix: prevent infinite loading and account interpreted as "disconnected" --- src/stores/account/index.ts | 3 ++- src/stores/account/types.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index dc388ec54..4a6c14b16 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -87,7 +87,8 @@ export const useCurrentAccount = create()((set, get) => ({ // Special case for spaces if (account.service === AccountService.PapillonMultiService) { - log("switching to virtual space, reloading associated accounts...", "[switchTo]"); + log("switching to virtual space, setting instance to a non-null value and reloading associated accounts...", "[switchTo]"); + account.instance = "PapillonPrime"; // Une chaine random, juste pour que l'instance ne soit pas "undefined" (ou null) et que l'espace multiservice soit interprété comme "déconnecté" } else if (typeof account.instance === "undefined") { // Account is currently not authenticated, log("instance undefined, reloading...", "[switchTo]"); // Automatically reconnect the main instance. diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 8a28d7422..514da8be5 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -204,7 +204,7 @@ export interface LocalAccount extends BaseAccount { export interface PapillonMultiServiceSpace extends BaseAccount { service: AccountService.PapillonMultiService - instance: null + instance: null | string authentication: null identityProvider: { name: string, From cf986f0895db8429f8eac3416569ce880db22641 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 14:55:25 +0100 Subject: [PATCH 061/102] fix: added warn to `reload-account.ts` --- src/services/reload-account.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/services/reload-account.ts b/src/services/reload-account.ts index 3370b84ab..ed8046bf6 100644 --- a/src/services/reload-account.ts +++ b/src/services/reload-account.ts @@ -61,6 +61,9 @@ export async function reload (account: T): Promise; } + case AccountService.PapillonMultiService: { + console.warn("PapillonMultiService space should never be reloaded."); + } default: { console.warn("Service not implemented"); return { instance: undefined, authentication: undefined }; From 05680135b176032228d0c062dfbb09a88756b7d9 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 23:27:16 +0100 Subject: [PATCH 062/102] fix: modified store to enable featuresServices value erasing --- src/stores/multiService/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index 30350ae9f..5e32018b5 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -59,7 +59,7 @@ export const useMultiService = create()( let spaceMutated: MultiServiceSpace; // Mutate only image and name properties. - if (key === "name" || key === "image") { + if (["name", "image", "featuresServices"].includes(key as string)) { spaceMutated = { ...space, [key]: value From b3eff7090d607ef60f1af3cd0111bef0332ec6aa Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 23:41:19 +0100 Subject: [PATCH 063/102] fix: added some logic to account deletion for PapillonMultiServiceSpace - Deleting an account now checks if it is associated to a space (and delete it from the space) - The space is deleted if no more accounts are associated to it --- src/stores/account/index.ts | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index 4a6c14b16..a42e0e249 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -18,6 +18,8 @@ import { useGradesStore } from "../grades"; import { useNewsStore } from "../news"; import { useAttendanceStore } from "../attendance"; import { info, log } from "@/utils/logger/logger"; +import {useMultiService} from "@/stores/multiService"; +import {MultiServiceFeature, MultiServiceSpace} from "@/stores/multiService/types"; /** * Store for the currently selected account. @@ -191,6 +193,44 @@ export const useAccounts = create()( ) })); + // On met à jour les espace multi-service, pour que : + // 1. Si le compte supprimé était lié à un espace: on le supprime de l'espace + // 2. Si il l'espace n'a donc plus aucun compté associé, on le supprime (car un espace est une sorte de groupement de comptes, sans comptes il cesse de fonctionner) + + // On récupère les comptes correspondant aux espaces + const spacesAccounts = get().accounts.filter(account => account.service === AccountService.PapillonMultiService); + for (const spaceAccount of spacesAccounts) { + + // Le compte que l'on a supprimé est lié à cet espace + if (spaceAccount.associatedAccountsLocalIDs.includes(localID)) { + log(`found ${localID} in PapillonMultiServiceSpace ${spaceAccount.name}`, "accounts:remove"); + + // On supprime la liaison du compte (ainsi que de chaque fonctionnalité à laquelle il est associé) + spaceAccount.associatedAccountsLocalIDs.splice(spaceAccount.associatedAccountsLocalIDs.indexOf(localID), 1); + const space = useMultiService.getState().spaces.find(space => space.accountLocalID === spaceAccount.localID) as MultiServiceSpace; + Object.entries(space.featuresServices).map(([key, value]) => { + if (value === localID) { + space.featuresServices[key as MultiServiceFeature] = undefined; + } + }); + useMultiService.getState().update(spaceAccount.localID, "featuresServices", space.featuresServices); + + log(`removed ${localID} from PapillonMultiServiceSpace ${spaceAccount.name}`, "accounts:remove"); + } + + // Si l'espace est vide, on le supprime + if (spaceAccount.associatedAccountsLocalIDs.length === 0) { + log(`PapillonMultiServiceSpace ${spaceAccount.name} is now empty, removing it`, "accounts:remove"); + useMultiService.getState().remove(spaceAccount.localID); + set((state) => ({ + accounts: state.accounts.filter( + (account) => account.localID !== spaceAccount.localID + ) + })); + log(`deleted PapillonMultiServiceSpace ${spaceAccount.name}`, "accounts:remove"); + } + } + log(`removed ${localID}`, "accounts:remove"); }, From 8f4253bcd22c0ab25ade1c8186f2a93ded2116a7 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Fri, 3 Jan 2025 23:46:16 +0100 Subject: [PATCH 064/102] fix: typo --- src/stores/account/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index a42e0e249..0e3057ae5 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -195,7 +195,7 @@ export const useAccounts = create()( // On met à jour les espace multi-service, pour que : // 1. Si le compte supprimé était lié à un espace: on le supprime de l'espace - // 2. Si il l'espace n'a donc plus aucun compté associé, on le supprime (car un espace est une sorte de groupement de comptes, sans comptes il cesse de fonctionner) + // 2. Si l'espace n'a donc plus aucun compté associé, on le supprime (car un espace est une sorte de groupement de comptes, sans comptes il cesse de fonctionner) // On récupère les comptes correspondant aux espaces const spacesAccounts = get().accounts.filter(account => account.service === AccountService.PapillonMultiService); From e27ad2a8871cb6c079343eee0fabfbb4dfa90b22 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 10:06:06 +0100 Subject: [PATCH 065/102] fix: using Papillon logger Co-authored-by: BORDIER-KERVRAN Gabriel --- src/services/attendance.ts | 8 +++++--- src/services/chats.ts | 19 +++++++++++++------ src/services/evaluation.ts | 8 +++++--- src/services/grades.ts | 8 +++++--- src/services/homework.ts | 7 ++++--- src/services/news.ts | 8 +++++--- src/services/reload-account.ts | 3 ++- src/services/timetable.ts | 5 +++-- 8 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/services/attendance.ts b/src/services/attendance.ts index 821f82047..2ae38a9d6 100644 --- a/src/services/attendance.ts +++ b/src/services/attendance.ts @@ -3,7 +3,7 @@ import type { Period } from "./shared/Period"; import { useAttendanceStore } from "@/stores/attendance"; import { Attendance } from "./shared/Attendance"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; -import { error } from "@/utils/logger/logger"; +import {error, log} from "@/utils/logger/logger"; import {MultiServiceFeature} from "@/stores/multiService/types"; import {getFeatureAccount} from "@/utils/multiservice"; @@ -66,7 +66,8 @@ export async function updateAttendancePeriodsInCache (accoun case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Attendance, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Attendance\"", "multiservice"); + return; } return updateAttendancePeriodsInCache(service); } @@ -128,7 +129,8 @@ export async function updateAttendanceInCache (account: T, p case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Attendance, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Attendance\"", "multiservice"); + break; } return updateAttendanceInCache(service, periodName); } diff --git a/src/services/chats.ts b/src/services/chats.ts index b3ac838df..51baa0760 100644 --- a/src/services/chats.ts +++ b/src/services/chats.ts @@ -3,6 +3,7 @@ import type { Chat, ChatMessage, ChatRecipient } from "./shared/Chat"; import type { Recipient } from "./shared/Recipient"; import {getFeatureAccount} from "@/utils/multiservice"; import {MultiServiceFeature} from "@/stores/multiService/types"; +import {log} from "@/utils/logger/logger"; export const getChats = async (account: T): Promise> => { switch (account.service) { @@ -17,7 +18,8 @@ export const getChats = async (account: T): Promise (account: T, chat: Ch case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Chats\"", "multiservice"); + return []; } return await getChatRecipients(service, chat); } @@ -62,7 +65,8 @@ export const sendMessageInChat = async (account: T, chat: Ch case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Chats\"", "multiservice"); + break; } return await sendMessageInChat(service, chat, content); } @@ -84,7 +88,8 @@ export const getChatMessages = async (account: T, chat: Chat case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Chats\"", "multiservice"); + return []; } return await getChatMessages(service, chat); } @@ -103,7 +108,8 @@ export const createDiscussionRecipients = async (account: T) case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Chats\"", "multiservice"); + return []; } return await createDiscussionRecipients(service); } @@ -123,7 +129,8 @@ export const createDiscussion = async (account: T, subject: case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Chats, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Chats\"", "multiservice"); + break; } return await createDiscussion(service, subject, content, recipients); } diff --git a/src/services/evaluation.ts b/src/services/evaluation.ts index 1656bd596..24f0c63ee 100644 --- a/src/services/evaluation.ts +++ b/src/services/evaluation.ts @@ -2,7 +2,7 @@ import { type Account, AccountService } from "@/stores/account/types"; import type { Period } from "./shared/Period"; import {useEvaluationStore} from "@/stores/evaluation"; import {Evaluation} from "@/services/shared/Evaluation"; -import {error} from "@/utils/logger/logger"; +import {error, log} from "@/utils/logger/logger"; import {getFeatureAccount} from "@/utils/multiservice"; import {MultiServiceFeature} from "@/stores/multiService/types"; @@ -29,7 +29,8 @@ export async function updateEvaluationPeriodsInCache (accoun case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Evaluations, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Evaluations\"", "multiservice"); + break; } return await updateEvaluationPeriodsInCache(service); } @@ -53,7 +54,8 @@ export async function updateEvaluationsInCache (account: T, case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Evaluations, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Evaluations\"", "multiservice"); + break; } return await updateEvaluationsInCache(service, periodName); } diff --git a/src/services/grades.ts b/src/services/grades.ts index 5b04c4dfe..011678052 100644 --- a/src/services/grades.ts +++ b/src/services/grades.ts @@ -2,7 +2,7 @@ import { type Account, AccountService } from "@/stores/account/types"; import { useGradesStore } from "@/stores/grades"; import type { Period } from "./shared/Period"; import type { AverageOverview, Grade } from "./shared/Grade"; -import {error } from "@/utils/logger/logger"; +import {error, log} from "@/utils/logger/logger"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; import {MultiServiceFeature} from "@/stores/multiService/types"; import {getFeatureAccount} from "@/utils/multiservice"; @@ -59,7 +59,8 @@ export async function updateGradesPeriodsInCache (account: T case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Grades, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Grades\"", "multiservice"); + break; } return await updateGradesPeriodsInCache(service); } @@ -132,7 +133,8 @@ export async function updateGradesAndAveragesInCache (accoun case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Grades, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Grades\"", "multiservice"); + break; } return await updateGradesAndAveragesInCache(service, periodName); } diff --git a/src/services/homework.ts b/src/services/homework.ts index a5d8d65a0..a383f084b 100644 --- a/src/services/homework.ts +++ b/src/services/homework.ts @@ -1,7 +1,7 @@ import { type Account, AccountService } from "@/stores/account/types"; import { useHomeworkStore } from "@/stores/homework"; import type { Homework } from "./shared/Homework"; -import { error } from "@/utils/logger/logger"; +import {error, log} from "@/utils/logger/logger"; import { translateToWeekNumber } from "pawnote"; import { pronoteFirstDate } from "./pronote/timetable"; import { dateToEpochWeekNumber, epochWNToPronoteWN } from "@/utils/epochWeekNumber"; @@ -49,7 +49,7 @@ export async function updateHomeworkForWeekInCache (account: case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); if (!service) { - console.info("[updateHomeworkForWeekInCache]: updating to empty since multi-service space has no account set for homeworks."); + log("No service set in multi-service space for feature \"Homeworks\"", "multiservice"); break; } return updateHomeworkForWeekInCache(service, date); @@ -83,7 +83,8 @@ export async function toggleHomeworkState (account: T, homew case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Homeworks, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Homeworks\"", "multiservice"); + break; } return toggleHomeworkState(service, homework); } diff --git a/src/services/news.ts b/src/services/news.ts index c05bcb538..f8fc32cb0 100644 --- a/src/services/news.ts +++ b/src/services/news.ts @@ -2,7 +2,7 @@ import { type Account, AccountService } from "@/stores/account/types"; import { useNewsStore } from "@/stores/news"; import type { Information } from "./shared/Information"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; -import { error } from "@/utils/logger/logger"; +import {error, log} from "@/utils/logger/logger"; import { newsRead } from "pawnote"; import { ca } from "date-fns/locale"; import {MultiServiceFeature} from "@/stores/multiService/types"; @@ -48,7 +48,8 @@ export async function updateNewsInCache (account: T): Promis case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.News, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"News\"", "multiservice"); + break; } return updateNewsInCache(service); } @@ -82,7 +83,8 @@ export async function setNewsRead (account: T, message: Info case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.News, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"News\"", "multiservice"); + break; } return setNewsRead(service, message, read); } diff --git a/src/services/reload-account.ts b/src/services/reload-account.ts index ed8046bf6..f10dfa744 100644 --- a/src/services/reload-account.ts +++ b/src/services/reload-account.ts @@ -1,4 +1,5 @@ import {type Account, AccountService} from "@/stores/account/types"; +import {warn} from "@/utils/logger/logger"; export interface Reconnected { instance: T["instance"] authentication: T["authentication"] @@ -62,7 +63,7 @@ export async function reload (account: T): Promise; } case AccountService.PapillonMultiService: { - console.warn("PapillonMultiService space should never be reloaded."); + warn("PapillonMultiService space should never be reloaded.", "multiservice"); } default: { console.warn("Service not implemented"); diff --git a/src/services/timetable.ts b/src/services/timetable.ts index 3db8f4793..9574b7397 100644 --- a/src/services/timetable.ts +++ b/src/services/timetable.ts @@ -2,7 +2,7 @@ import { type Account, AccountService } from "@/stores/account/types"; import { useTimetableStore } from "@/stores/timetable"; import { epochWNToPronoteWN, weekNumberToDateRange } from "@/utils/epochWeekNumber"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; -import { error } from "@/utils/logger/logger"; +import { error, log } from "@/utils/logger/logger"; import { fetchIcalData } from "./local/ical"; import {MultiServiceFeature} from "@/stores/multiService/types"; import {getFeatureAccount} from "@/utils/multiservice"; @@ -50,7 +50,8 @@ export async function updateTimetableForWeekInCache (account case AccountService.PapillonMultiService: { const service = getFeatureAccount(MultiServiceFeature.Timetable, account.localID); if (!service) { - throw new Error("No service set in multi-service space"); + log("No service set in multi-service space for feature \"Timetable\"", "multiservice"); + break; } return updateTimetableForWeekInCache(service, epochWeekNumber, force); } From 59c93dea718dc4af7a960f831fc04693de892330 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 10:18:47 +0100 Subject: [PATCH 066/102] fix: translated comments to english (I hope it's understandable :)) Co-authored-by: BORDIER-KERVRAN Gabriel --- src/stores/account/index.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index 0e3057ae5..0c1ff0cc9 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -90,7 +90,7 @@ export const useCurrentAccount = create()((set, get) => ({ // Special case for spaces if (account.service === AccountService.PapillonMultiService) { log("switching to virtual space, setting instance to a non-null value and reloading associated accounts...", "[switchTo]"); - account.instance = "PapillonPrime"; // Une chaine random, juste pour que l'instance ne soit pas "undefined" (ou null) et que l'espace multiservice soit interprété comme "déconnecté" + account.instance = "PapillonPrime"; // A random string, so the instance is not "undefined" or "null", to prevent creating infinite loading (an undefined instance is interpreted as a loading or disconnected account...) } else if (typeof account.instance === "undefined") { // Account is currently not authenticated, log("instance undefined, reloading...", "[switchTo]"); // Automatically reconnect the main instance. @@ -193,19 +193,19 @@ export const useAccounts = create()( ) })); - // On met à jour les espace multi-service, pour que : - // 1. Si le compte supprimé était lié à un espace: on le supprime de l'espace - // 2. Si l'espace n'a donc plus aucun compté associé, on le supprime (car un espace est une sorte de groupement de comptes, sans comptes il cesse de fonctionner) + // Update of multi-service environments to prevent : + // 1. If the deleted account was associated to a space : its reference need to be removed from this space + // 2. If a multi-service has no more associated accounts, it must be deleted (because a space is like a "group" of accounts, and without any associated accounts it does not work anymore⁾ - // On récupère les comptes correspondant aux espaces + // Fetching the accounts corresponding to spaces const spacesAccounts = get().accounts.filter(account => account.service === AccountService.PapillonMultiService); for (const spaceAccount of spacesAccounts) { - // Le compte que l'on a supprimé est lié à cet espace + // The account deleted above is associated to this space if (spaceAccount.associatedAccountsLocalIDs.includes(localID)) { log(`found ${localID} in PapillonMultiServiceSpace ${spaceAccount.name}`, "accounts:remove"); - // On supprime la liaison du compte (ainsi que de chaque fonctionnalité à laquelle il est associé) + // Remove the link to the account (and to every feature to which it is linked) spaceAccount.associatedAccountsLocalIDs.splice(spaceAccount.associatedAccountsLocalIDs.indexOf(localID), 1); const space = useMultiService.getState().spaces.find(space => space.accountLocalID === spaceAccount.localID) as MultiServiceSpace; Object.entries(space.featuresServices).map(([key, value]) => { @@ -218,7 +218,7 @@ export const useAccounts = create()( log(`removed ${localID} from PapillonMultiServiceSpace ${spaceAccount.name}`, "accounts:remove"); } - // Si l'espace est vide, on le supprime + // If the space is now empty; deleting it if (spaceAccount.associatedAccountsLocalIDs.length === 0) { log(`PapillonMultiServiceSpace ${spaceAccount.name} is now empty, removing it`, "accounts:remove"); useMultiService.getState().remove(spaceAccount.localID); From 04ac970798731bd012ec224dc8440404fee4fc8c Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 10:31:12 +0100 Subject: [PATCH 067/102] fix: simplified ternary condition Co-authored-by: BORDIER-KERVRAN Gabriel --- src/components/Global/AccountItem.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/Global/AccountItem.tsx b/src/components/Global/AccountItem.tsx index 9cc942ca7..8c847a355 100644 --- a/src/components/Global/AccountItem.tsx +++ b/src/components/Global/AccountItem.tsx @@ -19,14 +19,8 @@ const AccountItem: React.FC<{ account: PrimaryAccount, additionalStyles?: StyleP const theme = useTheme(); return ( Date: Sat, 4 Jan 2025 10:41:59 +0100 Subject: [PATCH 068/102] fix: repaired my enter key & indentation Co-authored-by: BORDIER-KERVRAN Gabriel --- src/components/Global/AccountItem.tsx | 33 +++---- src/views/settings/SettingsMultiService.tsx | 21 ++++- .../settings/SettingsMultiServiceSpace.tsx | 90 ++++++++++++------- 3 files changed, 92 insertions(+), 52 deletions(-) diff --git a/src/components/Global/AccountItem.tsx b/src/components/Global/AccountItem.tsx index 8c847a355..0173add2b 100644 --- a/src/components/Global/AccountItem.tsx +++ b/src/components/Global/AccountItem.tsx @@ -37,7 +37,10 @@ const AccountItem: React.FC<{ account: PrimaryAccount, additionalStyles?: StyleP }} > {endCheckMark && - - - + + + } ); diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index c6598378e..022abb690 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -144,10 +144,23 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => value={multiServiceEnabled ?? false} onValueChange={() => { if (multiServiceEnabled) { - Alert.alert("Attention", "La désactivation du multi-service entrainera la suppression de vos environnement multi-services créés.", [ { text: "Annuler", style: "cancel" }, { text: "Confirmer", style: "destructive", onPress: () => { - deleteAllSpaces(); - toggleMultiService(); - } } ]); + Alert.alert( + "Attention", + "La désactivation du multi-service entrainera la suppression de vos environnement multi-services créés.", + [ + { + text: "Annuler", + style: "cancel" + }, + { + text: "Confirmer", + style: "destructive", + onPress: () => { + deleteAllSpaces(); + toggleMultiService(); + } + } + ]); } else { toggleMultiService(); } diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index 9d9a46a96..d8281f949 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -77,11 +77,23 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga const [featureSelection, setFeatureSelection] = useState(MultiServiceFeature.Grades); const deleteSpace = () => { - Alert.alert("Êtes-vous sur ?", "Cette action entrainera la suppression de votre espace multi-service.", [ { text: "Annuler", style: "cancel" }, { text: "Confirmer", style: "destructive", onPress: () => { - accounts.remove(space.accountLocalID); - deleteMultiServiceSpace(space.accountLocalID); - navigation.goBack(); - }}]); + Alert.alert( + "Êtes-vous sur ?", + "Cette action entrainera la suppression de votre espace multi-service.", + [ + { + text: "Annuler", + style: "cancel" + }, + { text: "Confirmer", + style: "destructive", + onPress: () => { + accounts.remove(space.accountLocalID); + deleteMultiServiceSpace(space.accountLocalID); + navigation.goBack(); + } + } + ]); }; const openAccountSelector = (feature: MultiServiceFeature) => { @@ -164,16 +176,16 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga chevron={true} onPress={() => selectPicture()} leading={(selectedImage || space.image) && - + } icon={!(selectedImage || space.image) && } trailing={ @@ -300,8 +312,12 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga /> - Accède à plus d'options en sélectionnant l'espace virtuel, et en personnalisant ton profil dans les paramètres. - + + Accède à plus d'options en sélectionnant l'espace virtuel, et en personnalisant ton profil dans les paramètres. + = ({ naviga > {feature.name} - {accounts.accounts.find(account => account.localID === space.featuresServices[feature.feature]) ? ( - account.localID === space.featuresServices[feature.feature]) as PrimaryAccount} endCheckMark={false} additionalStyles={{ - paddingStart: 10, - borderBottomWidth: 1, - backgroundColor: theme.dark ? theme.colors.primary + "09" : theme.colors.primary + "11", - borderColor: theme.colors.text + "20" - }}/> - ): ( - } - separator={true} - > - Pas de service sélectionné - - )} + {accounts.accounts.find(account => + account.localID === space.featuresServices[feature.feature]) ? + ( + account.localID === space.featuresServices[feature.feature]) as PrimaryAccount} + endCheckMark={false} + additionalStyles={{ + paddingStart: 10, + borderBottomWidth: 1, + backgroundColor: theme.dark ? theme.colors.primary + "09" : theme.colors.primary + "11", + borderColor: theme.colors.text + "20" + }} + /> + ) : + ( + } + separator={true} + > + Pas de service sélectionné + + )} ))} From 999375b055873885eb7df5eeb83570e8218026ef Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 10:58:30 +0100 Subject: [PATCH 069/102] fix: more code property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 𝕂𝕪𝕝𝕚𝕒𝕟 --- src/components/Global/AccountItem.tsx | 13 ++++++++++-- src/views/settings/SettingsMultiService.tsx | 20 +++++++++++++------ .../settings/SettingsMultiServiceSpace.tsx | 10 +++++----- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/components/Global/AccountItem.tsx b/src/components/Global/AccountItem.tsx index 0173add2b..4cd7634d5 100644 --- a/src/components/Global/AccountItem.tsx +++ b/src/components/Global/AccountItem.tsx @@ -11,7 +11,11 @@ import {Check} from "lucide-react-native"; import React from "react"; import {useTheme} from "@react-navigation/native"; -const AccountItem: React.FC<{ account: PrimaryAccount, additionalStyles?: StyleProp, endCheckMark: boolean }> = ({ +const AccountItem: React.FC<{ + account: PrimaryAccount, + additionalStyles?: StyleProp, + endCheckMark: boolean +}> = ({ account, additionalStyles, endCheckMark @@ -55,7 +59,12 @@ const AccountItem: React.FC<{ account: PrimaryAccount, additionalStyles?: StyleP gap: 2, }} > - + = ({ navigation }) => name: spaceName, personalization: { profilePictureB64: selectedImage || undefined, - tabs: defaultTabs.filter(current => defaultSpaceTabs.includes(current.tab)).map((tab, index) => ({ - name: tab.tab, - enabled: index <= 4 - })) + tabs: defaultTabs + .filter(current => defaultSpaceTabs.includes(current.tab)) + .map((tab, index) => ({ + name: tab.tab, + enabled: index <= 4 + })) }, service: AccountService.PapillonMultiService, studentName: { @@ -193,7 +195,9 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => onPress={() => navigation.navigate("SettingsMultiServiceSpace", { space })} leading={ = ({ navigation }) => - opened} opened={spaceCreationSheetOpened} contentContainerStyle={{ paddingHorizontal: 16 }}> + setSpaceCreationSheetOpened(opened)} + opened={spaceCreationSheetOpened} + contentContainerStyle={{ paddingHorizontal: 16 }} + > = ({ naviga Accède à plus d'options en sélectionnant l'espace virtuel, et en personnalisant ton profil dans les paramètres. - + {features.map((feature, index) => ( <> Date: Sat, 4 Jan 2025 11:00:40 +0100 Subject: [PATCH 070/102] fix: simplified ternary condition Co-authored-by: BORDIER-KERVRAN Gabriel --- src/components/Global/AccountItem.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/Global/AccountItem.tsx b/src/components/Global/AccountItem.tsx index 4cd7634d5..06a027d4b 100644 --- a/src/components/Global/AccountItem.tsx +++ b/src/components/Global/AccountItem.tsx @@ -93,9 +93,7 @@ const AccountItem: React.FC<{ > {AccountService[account.service] !== "Local" ? AccountService[account.service] : - account.identityProvider ? - account.identityProvider?.name : - "Compte local" + account.identityProvider?.name ?? "Compte local" } From 3bd062e76c3041ed130a983392bd05e2545dc28b Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 11:41:42 +0100 Subject: [PATCH 071/102] fix: simplified function --- src/utils/multiservice/index.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/utils/multiservice/index.ts b/src/utils/multiservice/index.ts index 9be274fa2..71e2947b1 100644 --- a/src/utils/multiservice/index.ts +++ b/src/utils/multiservice/index.ts @@ -1,16 +1,9 @@ import {MultiServiceFeature} from "@/stores/multiService/types"; -import {useAccounts, useCurrentAccount} from "@/stores/account"; +import {useCurrentAccount} from "@/stores/account"; import {useMultiService} from "@/stores/multiService"; import {PrimaryAccount} from "@/stores/account/types"; export function getFeatureAccount (feature: MultiServiceFeature, spaceLocalID: string) { - const accounts = useAccounts.getState().accounts; const accountId = useMultiService.getState().getFeatureAccountId(feature, spaceLocalID); - const featureAccount = accounts.find(account => account.localID === accountId) as PrimaryAccount | undefined; - if (featureAccount) { - const linkedAccount = useCurrentAccount.getState().associatedAccounts.find(account => account.localID === accountId) as PrimaryAccount; - featureAccount.instance = linkedAccount?.instance; - featureAccount.authentication = linkedAccount?.authentication; - } - return featureAccount; + return useCurrentAccount.getState().associatedAccounts.find(account => account.localID === accountId) as PrimaryAccount; } From fad82e60506a47c94ab5ee34e5706929347bf830 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 11:51:35 +0100 Subject: [PATCH 072/102] fix: bug & enhancements in account store logic - fixed a bug in account deletion for spaces - added a catch statement to instance reloading (for associated accounts) - setting instance to a non-null value after associated accounts reload for space accounts --- src/stores/account/index.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index 0c1ff0cc9..91c9d8f9a 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -17,7 +17,7 @@ import { useHomeworkStore } from "../homework"; import { useGradesStore } from "../grades"; import { useNewsStore } from "../news"; import { useAttendanceStore } from "../attendance"; -import { info, log } from "@/utils/logger/logger"; +import {error, info, log} from "@/utils/logger/logger"; import {useMultiService} from "@/stores/multiService"; import {MultiServiceFeature, MultiServiceSpace} from "@/stores/multiService/types"; @@ -89,8 +89,7 @@ export const useCurrentAccount = create()((set, get) => ({ // Special case for spaces if (account.service === AccountService.PapillonMultiService) { - log("switching to virtual space, setting instance to a non-null value and reloading associated accounts...", "[switchTo]"); - account.instance = "PapillonPrime"; // A random string, so the instance is not "undefined" or "null", to prevent creating infinite loading (an undefined instance is interpreted as a loading or disconnected account...) + log("switching to virtual space, skipping main account reload and reloading associated accounts...", "[switchTo]"); } else if (typeof account.instance === "undefined") { // Account is currently not authenticated, log("instance undefined, reloading...", "[switchTo]"); // Automatically reconnect the main instance. @@ -118,12 +117,22 @@ export const useCurrentAccount = create()((set, get) => ({ } for (const associatedAccount of associatedAccounts) { - const { instance, authentication } = await reload(associatedAccount); + const { instance, authentication } = await reload(associatedAccount).catch(err => { + error(`failed to reload associated account: ${err} !`, "[switchTo]"); + return { + instance: associatedAccount.instance, + authentication: associatedAccount.authentication + }; + }); associatedAccount.instance = instance; associatedAccount.authentication = authentication; log("reloaded associated account", "[switchTo]"); } + // Setting instance to a non-null value after associated accounts reload, to keep the loading icon while instances are reloading... + if (account.service === AccountService.PapillonMultiService) + account.instance = "PapillonPrime"; // A random string, so the instance is not "undefined" or "null", to prevent creating infinite loading (an undefined instance is interpreted as a loading or disconnected account...) + log("reloaded all external and associated accounts", "[switchTo]"); set({ linkedAccounts, associatedAccounts }); @@ -214,7 +223,11 @@ export const useAccounts = create()( } }); useMultiService.getState().update(spaceAccount.localID, "featuresServices", space.featuresServices); - + set((state) => ({ + accounts: state.accounts.map(account => + account.localID === spaceAccount.localID ? spaceAccount : account + ) + })); log(`removed ${localID} from PapillonMultiServiceSpace ${spaceAccount.name}`, "accounts:remove"); } From 4d8837b071a6066bd853278bfd31fd09ab06510f Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 13:01:51 +0100 Subject: [PATCH 073/102] fix: reloading instances only if it is undefined (should fix pronote reconnection issue) --- src/stores/account/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index 91c9d8f9a..d8c978d4f 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -117,6 +117,8 @@ export const useCurrentAccount = create()((set, get) => ({ } for (const associatedAccount of associatedAccounts) { + if (!(typeof associatedAccount.instance === "undefined")) + continue; const { instance, authentication } = await reload(associatedAccount).catch(err => { error(`failed to reload associated account: ${err} !`, "[switchTo]"); return { From 1defd2c2ef90e7bf12715520a6c4ff8b9233ad95 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 14:03:33 +0100 Subject: [PATCH 074/102] fix(ts): wrong route name & missing arguments in `DevMenu.tsx` --- src/views/welcome/DevMenu.tsx | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/views/welcome/DevMenu.tsx b/src/views/welcome/DevMenu.tsx index 7cf7a8aa1..913170f53 100644 --- a/src/views/welcome/DevMenu.tsx +++ b/src/views/welcome/DevMenu.tsx @@ -101,7 +101,30 @@ const DevMenu: Screen<"DevMenu"> = ({ navigation }) => { navigation.navigate("NoteReaction")} + onPress={() => navigation.navigate("GradeReaction", { + grade: { + id: "mmmhm", + subjectName: "Cours de ts avec Armand", + description: "Note de test", + timestamp: 0, + average: { + value: 0.2 + }, + coefficient: 40, + min: { + value: 0 + }, + max: { + value: 20 + }, + student: { + value: 0 + }, + outOf: { + value: 20 + } + } + })} > NoteReaction @@ -205,4 +228,4 @@ const DevMenu: Screen<"DevMenu"> = ({ navigation }) => { ); }; -export default DevMenu; \ No newline at end of file +export default DevMenu; From d589162007b8f25be6cd7b405a29d0174f1846de Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 14:04:49 +0100 Subject: [PATCH 075/102] fix: lint --- src/views/settings/Settings.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/settings/Settings.tsx b/src/views/settings/Settings.tsx index 1ae6b5805..7d6655e14 100644 --- a/src/views/settings/Settings.tsx +++ b/src/views/settings/Settings.tsx @@ -28,8 +28,8 @@ import { Route, Scroll, Settings as SettingsLucide, - Sparkles, - SunMoon, + Sparkles, + SunMoon, Smile, SwatchBook, WandSparkles, From b18fab929cf3f5bc69f99dfa9238e6049bdab20b Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 14:10:48 +0100 Subject: [PATCH 076/102] fix: better joke in dev menu --- src/views/welcome/DevMenu.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/welcome/DevMenu.tsx b/src/views/welcome/DevMenu.tsx index 913170f53..748252963 100644 --- a/src/views/welcome/DevMenu.tsx +++ b/src/views/welcome/DevMenu.tsx @@ -104,9 +104,9 @@ const DevMenu: Screen<"DevMenu"> = ({ navigation }) => { onPress={() => navigation.navigate("GradeReaction", { grade: { id: "mmmhm", - subjectName: "Cours de ts avec Armand", + subjectName: "Éval ts avec Armand", description: "Note de test", - timestamp: 0, + timestamp: 1735996215, average: { value: 0.2 }, From 01a463103adde22a5bdf760609afc72ba6838d66 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 14:10:48 +0100 Subject: [PATCH 077/102] fix: better joke in dev menu --- src/views/welcome/DevMenu.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/welcome/DevMenu.tsx b/src/views/welcome/DevMenu.tsx index 913170f53..0d6fb07f9 100644 --- a/src/views/welcome/DevMenu.tsx +++ b/src/views/welcome/DevMenu.tsx @@ -104,9 +104,9 @@ const DevMenu: Screen<"DevMenu"> = ({ navigation }) => { onPress={() => navigation.navigate("GradeReaction", { grade: { id: "mmmhm", - subjectName: "Cours de ts avec Armand", + subjectName: "Éval TS avec Armand", description: "Note de test", - timestamp: 0, + timestamp: 1735996215000, average: { value: 0.2 }, From 3b3160fe8b06e7e016e33cff0b4a3805bf0e86cd Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 14:50:29 +0100 Subject: [PATCH 078/102] fix: PapillonSpace profile picture was changing randomly --- src/stores/account/index.ts | 7 ++++++- src/stores/account/types.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index d8c978d4f..f3d7d2551 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -31,9 +31,14 @@ export const useCurrentAccount = create()((set, get) => ({ // For multi service, to not mix Primary & External accounts associatedAccounts: [], - mutateProperty: (key: T, value: PrimaryAccount[T]) => { + mutateProperty: (key: T, value: PrimaryAccount[T], forceMutation = false) => { log(`mutate property ${key} in storage`, "current:update"); + // Special case to keep Papillon Space custom image + if (get().account?.service === AccountService.PapillonMultiService && key === "personalization" && !forceMutation) { + delete (value as PrimaryAccount["personalization"]).profilePictureB64; + } + // Since "instance" is a runtime only key, // we mutate the property only in this memory store and not in the persisted one. if (key === "instance") { diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 514da8be5..37eb1d0e6 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -87,7 +87,7 @@ export interface CurrentAccountStore { account: PrimaryAccount | null linkedAccounts: ExternalAccount[] associatedAccounts: PrimaryAccount[] - mutateProperty: (key: T, value: PrimaryAccount[T]) => void + mutateProperty: (key: T, value: PrimaryAccount[T], forceMutation?: boolean) => void linkExistingExternalAccount: (account: ExternalAccount) => void switchTo: (account: PrimaryAccount) => Promise logout: () => void From 2739c4097fc917ef9355ffb96442ca14fa8dbace Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 19:31:28 +0100 Subject: [PATCH 079/102] fix: forcing pfp change in `SettingsProfile.tsx` --- src/views/settings/SettingsProfile.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/settings/SettingsProfile.tsx b/src/views/settings/SettingsProfile.tsx index 453e2ea28..e7f6aa0c5 100644 --- a/src/views/settings/SettingsProfile.tsx +++ b/src/views/settings/SettingsProfile.tsx @@ -66,7 +66,7 @@ const SettingsProfile: Screen<"SettingsProfile"> = ({ navigation }) => { mutateProperty("personalization", { ...account.personalization, profilePictureB64: img, - }); + }, true); } setLoadingPic(false); @@ -322,4 +322,4 @@ const SettingsProfile: Screen<"SettingsProfile"> = ({ navigation }) => { ); }; -export default SettingsProfile; \ No newline at end of file +export default SettingsProfile; From 3880934e018e05fbc465d7f1f09ea955f733a372 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 4 Jan 2025 19:37:22 +0100 Subject: [PATCH 080/102] fix: lint & types --- src/components/Global/AnimatedNumber.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Global/AnimatedNumber.tsx b/src/components/Global/AnimatedNumber.tsx index f6aff6614..412d0282a 100644 --- a/src/components/Global/AnimatedNumber.tsx +++ b/src/components/Global/AnimatedNumber.tsx @@ -50,7 +50,7 @@ const AnimatedNumber: React.FC = ({ }, contentContainerStyle]} layout={animPapillon(LinearTransition)} > - {value.toString().split("").map((n, i) => ( + {value.toString().split("").map((n: string, i: number) => ( = ({ ); }; -export default AnimatedNumber; \ No newline at end of file +export default AnimatedNumber; From 23681f964b945d96e21341db7fd12595f0798c73 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sun, 5 Jan 2025 20:27:33 +0100 Subject: [PATCH 081/102] fix: better UI: using native buttons --- src/views/settings/SettingsMultiService.tsx | 63 ++++++++------------- 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 1ac8b9ef7..115553149 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -17,6 +17,7 @@ import {AccountService, PapillonMultiServiceSpace} from "@/stores/account/types" import uuid from "@/utils/uuid-v4"; import {defaultProfilePicture} from "@/utils/ui/default-profile-picture"; import {defaultTabs} from "@/consts/DefaultTabs"; +import ButtonCta from "@/components/FirstInstallation/ButtonCta"; const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => { const theme = useTheme(); @@ -53,12 +54,9 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => setLoadingImage(false); }; - const [loadingCreation, setLoading] = useState(false); const createSpace = () => { - setLoading(true); if (spaceName == "") { Alert.alert("Aucun titre défini", "Vous devez définir un titre à l'environnement multi service pour pouvoir le créer."); - setLoading(false); return; } @@ -118,7 +116,6 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => createMultiServiceSpace(space, linkedAccount); accounts.create(linkedAccount); setSpaceCreationSheetOpened(false); - setLoading(false); setSelectedImage(null); setSpaceName(""); }; @@ -300,42 +297,28 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => - - - - createSpace()} - trailing={loadingCreation && } - > - - Créer l'espace - - - setSpaceCreationSheetOpened(false)} - > - - Annuler - - - - - + + createSpace()} + value="Créer l'espace" + /> + setSpaceCreationSheetOpened(false)} + /> + )} From fa036043149c86af9faf2f891625d8e837e815ae Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sun, 5 Jan 2025 20:27:48 +0100 Subject: [PATCH 082/102] fix: UX improvement --- src/views/settings/SettingsMultiServiceSpace.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/views/settings/SettingsMultiServiceSpace.tsx b/src/views/settings/SettingsMultiServiceSpace.tsx index 53d3ef71f..da6f35678 100644 --- a/src/views/settings/SettingsMultiServiceSpace.tsx +++ b/src/views/settings/SettingsMultiServiceSpace.tsx @@ -75,6 +75,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga const [accountSelectorOpened, setAccountSelectorOpened] = useState(false); const [selectedAccount, setSelectedAccount] = useState(null); const [featureSelection, setFeatureSelection] = useState(MultiServiceFeature.Grades); + const [featureSelectionName, setFeatureSelectionName] = useState(""); const deleteSpace = () => { Alert.alert( @@ -96,9 +97,10 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga ]); }; - const openAccountSelector = (feature: MultiServiceFeature) => { + const openAccountSelector = (feature: MultiServiceFeature, name: string) => { setSelectedAccount(availableAccounts.find(account => account.localID === space.featuresServices[feature]) || null); setFeatureSelection(feature); + setFeatureSelectionName(name); setAccountSelectorOpened(true); }; @@ -360,7 +362,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga ]} /> } - onPress={() => openAccountSelector(feature.feature)} + onPress={() => openAccountSelector(feature.feature, feature.name)} trailing={} chevron={false} > @@ -400,7 +402,7 @@ const SettingsMultiServiceSpace: Screen<"SettingsMultiServiceSpace"> = ({ naviga paddingHorizontal: 10 }} > - + {availableAccounts.map((account, index) => ( Date: Sun, 12 Jan 2025 21:33:32 +0100 Subject: [PATCH 083/102] fix: make authentication value persistant for associated accounts --- src/stores/account/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index f3d7d2551..11eb6482c 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -133,6 +133,8 @@ export const useCurrentAccount = create()((set, get) => ({ }); associatedAccount.instance = instance; associatedAccount.authentication = authentication; + // Persist authentification value (f.e if token was renewed, it's important to make it persistant) + useAccounts.getState().update(associatedAccount.localID, "authentication", authentication); log("reloaded associated account", "[switchTo]"); } From 6eb589c84d702b36d3cd09db9f17f1d1376e8851 Mon Sep 17 00:00:00 2001 From: Armand Camponovo Date: Wed, 29 Jan 2025 21:44:54 +0100 Subject: [PATCH 084/102] fix: imports --- src/services/evaluation.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/evaluation.ts b/src/services/evaluation.ts index c8949d99a..669a48907 100644 --- a/src/services/evaluation.ts +++ b/src/services/evaluation.ts @@ -1,8 +1,10 @@ import { type Account, AccountService } from "@/stores/account/types"; import type { Period } from "./shared/Period"; +import {getFeatureAccount} from "@/utils/multiservice"; +import {MultiServiceFeature} from "@/stores/multiService/types"; import { useEvaluationStore } from "@/stores/evaluation"; import { Evaluation } from "@/services/shared/Evaluation"; -import { error } from "@/utils/logger/logger"; +import { error, log } from "@/utils/logger/logger"; const getDefaultPeriod = (periods: Period[]): string => { const now = Date.now(); From 118d6acca2d1328d653071d240ce368eb119f5eb Mon Sep 17 00:00:00 2001 From: Armand Camponovo Date: Wed, 29 Jan 2025 21:45:25 +0100 Subject: [PATCH 085/102] fix: imports --- src/services/grades.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/grades.ts b/src/services/grades.ts index 80539564c..602bcb677 100644 --- a/src/services/grades.ts +++ b/src/services/grades.ts @@ -2,7 +2,7 @@ import { type Account, AccountService } from "@/stores/account/types"; import { useGradesStore } from "@/stores/grades"; import type { Period } from "./shared/Period"; import type { AverageOverview, Grade } from "./shared/Grade"; -import { error } from "@/utils/logger/logger"; +import { error, log } from "@/utils/logger/logger"; import { checkIfSkoSupported } from "./skolengo/default-personalization"; import {MultiServiceFeature} from "@/stores/multiService/types"; import {getFeatureAccount} from "@/utils/multiservice"; From f1e48a3bdbc51a4b51779586715014c9c6a53020 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 10:54:11 +0100 Subject: [PATCH 086/102] fix(ts): added ts ignore comments for weird options in `views/index.ts` --- src/router/screens/views/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/router/screens/views/index.ts b/src/router/screens/views/index.ts index ffb39c703..d902a4f5a 100644 --- a/src/router/screens/views/index.ts +++ b/src/router/screens/views/index.ts @@ -65,6 +65,7 @@ export default [ animation: "slide_from_bottom", sheetGrabberVisible: false, sheetInitialDetentIndex: 0, + // @ts-expect-error IDK why it is a list of number, it should be SheetDetentTypes sheetAllowedDetents: [0.5, 1.0], headerShown: false, }), @@ -75,6 +76,7 @@ export default [ animation: "slide_from_bottom", sheetGrabberVisible: false, sheetInitialDetentIndex: 0, + // @ts-expect-error IDK why it is a list of number, it should be SheetDetentTypes sheetAllowedDetents: [0.5, 1.0], headerShown: false, }), @@ -85,6 +87,7 @@ export default [ animation: "slide_from_bottom", sheetGrabberVisible: true, sheetInitialDetentIndex: 0, + // @ts-expect-error IDK why it is a list of number, it should be SheetDetentTypes sheetAllowedDetents: [0.5, 1.0], }), createScreen("GradeDocument", GradeDocument, { @@ -94,6 +97,7 @@ export default [ animation: "slide_from_bottom", sheetGrabberVisible: false, sheetInitialDetentIndex: 0, + // @ts-expect-error IDK why it is a list of number, it should be SheetDetentTypes sheetAllowedDetents: [0.5, 1.0], headerShown: Platform.OS !== "ios", }), From 28beadf0609e09a3e98f976eee649b117c73fc62 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 10:56:32 +0100 Subject: [PATCH 087/102] fix(ts): any type cast in `iutlan/grades.ts` --- src/services/iutlan/grades.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/iutlan/grades.ts b/src/services/iutlan/grades.ts index 0a26590e3..9987e6c4b 100644 --- a/src/services/iutlan/grades.ts +++ b/src/services/iutlan/grades.ts @@ -13,7 +13,8 @@ export const saveIUTLanGrades = async (account: LocalAccount, periodName: string // console.log(periodName); // Il faudrait peut-être penser à typer cette partie, tous les types sont any :( - const scodocData = account.serviceData.semestres[periodName]; + const data = account.serviceData.semestres as any; + const scodocData = data[periodName] as any; if (!scodocData) { return { From 7e535d2a326d09dce104809824d14117f764cd81 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 10:58:07 +0100 Subject: [PATCH 088/102] fix(ts): missing members for account in `skolengo-account.ts` --- src/services/skolengo/skolengo-account.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/skolengo/skolengo-account.ts b/src/services/skolengo/skolengo-account.ts index 339469a85..6d73da973 100644 --- a/src/services/skolengo/skolengo-account.ts +++ b/src/services/skolengo/skolengo-account.ts @@ -107,7 +107,9 @@ export const getSkolengoAccount = async (authConfig: SkolengoAuthConfig, userInf className: userInfo?.className, personalization: await defaultSkolengoPersonalization(skolengoAccount), userInfo, - identity: {} + identity: {}, + providers: [], + serviceData: {} }; return account; }; From b813b9938c778d841c49491544da27212058ec2c Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 11:01:34 +0100 Subject: [PATCH 089/102] fix(ts): missing members for PapillonMultiServiceSpace account type --- src/stores/account/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stores/account/types.ts b/src/stores/account/types.ts index 22f9457ba..9d85e494e 100644 --- a/src/stores/account/types.ts +++ b/src/stores/account/types.ts @@ -223,6 +223,8 @@ export interface PapillonMultiServiceSpace extends BaseAccount { rawData: undefined }, associatedAccountsLocalIDs: string[] + providers: string[] + serviceData: Record } From a25df469c049d0c7e4e1b85840853dd8c9dfbc6b Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 11:01:42 +0100 Subject: [PATCH 090/102] fix(ts): any type cast --- src/views/account/Grades/Atoms/GradesScodocUE.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/views/account/Grades/Atoms/GradesScodocUE.tsx b/src/views/account/Grades/Atoms/GradesScodocUE.tsx index 897c546b0..2ad4f5381 100644 --- a/src/views/account/Grades/Atoms/GradesScodocUE.tsx +++ b/src/views/account/Grades/Atoms/GradesScodocUE.tsx @@ -18,9 +18,9 @@ const GradesScodocUE = ({ account, navigation, selectedPeriod }: { account: Prim const { colors } = useTheme(); const { showAlert } = useAlert(); - const grades = account.serviceData.semestres[selectedPeriod]; + const data = account.serviceData.semestres as any; + const grades = data[selectedPeriod]; - // @ts-expect-error const ues = grades["relevé"]["ues"]; const uekeys = Object.keys(ues); @@ -28,9 +28,7 @@ const GradesScodocUE = ({ account, navigation, selectedPeriod }: { account: Prim return null; } - // @ts-expect-error const ressources = grades["relevé"]["ressources"]; - // @ts-expect-error const saes = grades["relevé"]["saes"]; const finalUes = uekeys.map((ue) => { @@ -305,4 +303,4 @@ const GradesScodocUE = ({ account, navigation, selectedPeriod }: { account: Prim } }; -export default memo(GradesScodocUE); \ No newline at end of file +export default memo(GradesScodocUE); From e0a132280a99ab217b257ae58627451a265ce29f Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 11:02:44 +0100 Subject: [PATCH 091/102] fix(ts): missing react import --- src/views/account/Grades/Document.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/account/Grades/Document.tsx b/src/views/account/Grades/Document.tsx index 2bd25c1ab..845d01c45 100644 --- a/src/views/account/Grades/Document.tsx +++ b/src/views/account/Grades/Document.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import { NativeItem, NativeList, NativeListHeader, NativeText, } from "@/components/Global/NativeComponents"; import { getSubjectData } from "@/services/shared/Subject"; import { useTheme } from "@react-navigation/native"; From a82754470a2bc805f2c5c073f839356e16f523b1 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 11:04:29 +0100 Subject: [PATCH 092/102] fix(ts): `SubjectList.tsx` --- src/views/account/Grades/Subject/SubjectList.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/account/Grades/Subject/SubjectList.tsx b/src/views/account/Grades/Subject/SubjectList.tsx index 6e2cb5e69..aba7add94 100644 --- a/src/views/account/Grades/Subject/SubjectList.tsx +++ b/src/views/account/Grades/Subject/SubjectList.tsx @@ -45,6 +45,8 @@ const SubjectItem: React.FC = ({ return null; } + index = index || 0; + return ( Date: Sat, 1 Feb 2025 11:06:22 +0100 Subject: [PATCH 093/102] fix(ts): types in `BackgroundIUTLannion.tsx` --- .../login/IdentityProvider/actions/BackgroundIUTLannion.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/views/login/IdentityProvider/actions/BackgroundIUTLannion.tsx b/src/views/login/IdentityProvider/actions/BackgroundIUTLannion.tsx index 259f81191..b41782a66 100644 --- a/src/views/login/IdentityProvider/actions/BackgroundIUTLannion.tsx +++ b/src/views/login/IdentityProvider/actions/BackgroundIUTLannion.tsx @@ -126,7 +126,7 @@ const BackgroundIUTLannion: Screen<"BackgroundIUTLannion"> = ({ route, navigatio const processSemestre = async (data: any) => { // ajouter le semestre ici - const newServiceData = account?.serviceData || {}; + const newServiceData = account?.serviceData || {} as any; if (!newServiceData["semestres"]) { newServiceData["semestres"] = {}; @@ -197,7 +197,8 @@ const BackgroundIUTLannion: Screen<"BackgroundIUTLannion"> = ({ route, navigatio className: data["relevé"].etudiant.dept_acronym, schoolName: "IUT de Lannion - Université de Rennes", - personalization: await defaultPersonalization() + personalization: await defaultPersonalization(), + serviceData: {} }; createStoredAccount(local_account); From 087ddff9c36e45f855dd220d2d95a239bafe37bb Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 11:08:05 +0100 Subject: [PATCH 094/102] fix(ts): account types in `Multi.tsx`, `UnivLimoges.tsx`, `UnivRennes1.tsx`, `UnivRennes2.tsx` & `UnivSorbonneParisNord.tsx` --- src/views/login/IdentityProvider/providers/Multi.tsx | 2 ++ src/views/login/IdentityProvider/providers/UnivLimoges.tsx | 4 +++- src/views/login/IdentityProvider/providers/UnivRennes1.tsx | 6 ++++-- src/views/login/IdentityProvider/providers/UnivRennes2.tsx | 4 +++- .../IdentityProvider/providers/UnivSorbonneParisNord.tsx | 6 ++++-- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/views/login/IdentityProvider/providers/Multi.tsx b/src/views/login/IdentityProvider/providers/Multi.tsx index 87ba88016..5ed4953e0 100644 --- a/src/views/login/IdentityProvider/providers/Multi.tsx +++ b/src/views/login/IdentityProvider/providers/Multi.tsx @@ -53,6 +53,8 @@ const Muli_Login: Screen<"Multi_Login"> = ({ route, navigation }) => { refreshAuthToken: account.userData.refreshAuthToken || "", }, personalization: await defaultPersonalization(account), + serviceData: {}, + providers: [] }; createStoredAccount(local_account); diff --git a/src/views/login/IdentityProvider/providers/UnivLimoges.tsx b/src/views/login/IdentityProvider/providers/UnivLimoges.tsx index fdf85edb7..da79aacc1 100644 --- a/src/views/login/IdentityProvider/providers/UnivLimoges.tsx +++ b/src/views/login/IdentityProvider/providers/UnivLimoges.tsx @@ -65,7 +65,9 @@ const UnivLimoges_Login: Screen<"UnivLimoges_Login"> = ({ navigation }) => { personalization: await defaultPersonalization({ profilePictureB64: user.avatar }), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; createStoredAccount(local_account); diff --git a/src/views/login/IdentityProvider/providers/UnivRennes1.tsx b/src/views/login/IdentityProvider/providers/UnivRennes1.tsx index 85d7f2a69..3dd0b620c 100644 --- a/src/views/login/IdentityProvider/providers/UnivRennes1.tsx +++ b/src/views/login/IdentityProvider/providers/UnivRennes1.tsx @@ -52,7 +52,9 @@ const UnivRennes1_Login: Screen<"UnivRennes1_Login"> = ({ navigation }) => { schoolName: data.caccount.data.attachmentDpt.name.replace("Institut Universitaire de Technologie", "IUT") + " - Université de Rennes", personalization: await defaultPersonalization(), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; createStoredAccount(local_account); @@ -154,4 +156,4 @@ const UnivRennes1_Login: Screen<"UnivRennes1_Login"> = ({ navigation }) => { ); }; -export default UnivRennes1_Login; \ No newline at end of file +export default UnivRennes1_Login; diff --git a/src/views/login/IdentityProvider/providers/UnivRennes2.tsx b/src/views/login/IdentityProvider/providers/UnivRennes2.tsx index a0014dfee..7ca6bc9af 100644 --- a/src/views/login/IdentityProvider/providers/UnivRennes2.tsx +++ b/src/views/login/IdentityProvider/providers/UnivRennes2.tsx @@ -94,7 +94,9 @@ const UnivRennes2_Login: Screen<"UnivRennes2_Login"> = ({ navigation }) => { personalization: await defaultPersonalization(), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; createStoredAccount(local_account); diff --git a/src/views/login/IdentityProvider/providers/UnivSorbonneParisNord.tsx b/src/views/login/IdentityProvider/providers/UnivSorbonneParisNord.tsx index a1136e6a7..604b633eb 100644 --- a/src/views/login/IdentityProvider/providers/UnivSorbonneParisNord.tsx +++ b/src/views/login/IdentityProvider/providers/UnivSorbonneParisNord.tsx @@ -83,7 +83,9 @@ const UnivSorbonneParisNord_login: Screen<"UnivSorbonneParisNord_login"> = ({ na className: "", schoolName: "Université Sorbonne Paris Nord", personalization: await defaultPersonalization(), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; createStoredAccount(localAccount); @@ -139,4 +141,4 @@ const UnivSorbonneParisNord_login: Screen<"UnivSorbonneParisNord_login"> = ({ na ); }; -export default UnivSorbonneParisNord_login; \ No newline at end of file +export default UnivSorbonneParisNord_login; From cda92253dc5172c40bd73e41382f2a22611f9a79 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 11:09:43 +0100 Subject: [PATCH 095/102] fix(ts): account types in all files --- src/views/login/ecoledirecte/EcoleDirecteCredentials.tsx | 3 +++ src/views/login/pronote/Pronote2FA_Auth.tsx | 4 +++- src/views/login/pronote/PronoteCredentials.tsx | 4 +++- src/views/login/pronote/PronoteQRCode.tsx | 4 +++- src/views/login/pronote/PronoteV6Import.tsx | 4 +++- src/views/login/pronote/PronoteWebview.tsx | 4 +++- 6 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/views/login/ecoledirecte/EcoleDirecteCredentials.tsx b/src/views/login/ecoledirecte/EcoleDirecteCredentials.tsx index cb9495c7f..105b3bc9a 100644 --- a/src/views/login/ecoledirecte/EcoleDirecteCredentials.tsx +++ b/src/views/login/ecoledirecte/EcoleDirecteCredentials.tsx @@ -91,6 +91,9 @@ const EcoleDirecteCredentials: Screen<"EcoleDirecteCredentials"> = ({ navigation account }, personalization: await defaultPersonalization(account), + + serviceData: {}, + providers: [] }; diff --git a/src/views/login/pronote/Pronote2FA_Auth.tsx b/src/views/login/pronote/Pronote2FA_Auth.tsx index 83bff4fef..c38449178 100644 --- a/src/views/login/pronote/Pronote2FA_Auth.tsx +++ b/src/views/login/pronote/Pronote2FA_Auth.tsx @@ -152,7 +152,9 @@ export const Pronote2FA_Auth: Screen<"Pronote2FA_Auth"> = ({ authentication: { ...refresh, deviceUUID: accountID }, personalization: await defaultPersonalization(session), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; pronote.startPresenceInterval(session); diff --git a/src/views/login/pronote/PronoteCredentials.tsx b/src/views/login/pronote/PronoteCredentials.tsx index 6c0e55c37..f7d37fc2f 100644 --- a/src/views/login/pronote/PronoteCredentials.tsx +++ b/src/views/login/pronote/PronoteCredentials.tsx @@ -69,7 +69,9 @@ const PronoteCredentials: Screen<"PronoteCredentials"> = ({ route, navigation }) authentication: { ...refresh, deviceUUID: accountID }, personalization: await defaultPersonalization(session), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; pronote.startPresenceInterval(session); diff --git a/src/views/login/pronote/PronoteQRCode.tsx b/src/views/login/pronote/PronoteQRCode.tsx index 8ec03c4ce..37ef05fd2 100644 --- a/src/views/login/pronote/PronoteQRCode.tsx +++ b/src/views/login/pronote/PronoteQRCode.tsx @@ -117,7 +117,9 @@ const PronoteQRCode: Screen<"PronoteQRCode"> = ({ navigation }) => { authentication: { ...refresh, deviceUUID: accountID }, personalization: await defaultPersonalization(session), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; pronote.startPresenceInterval(session); diff --git a/src/views/login/pronote/PronoteV6Import.tsx b/src/views/login/pronote/PronoteV6Import.tsx index 477419976..95f5b01b4 100644 --- a/src/views/login/pronote/PronoteV6Import.tsx +++ b/src/views/login/pronote/PronoteV6Import.tsx @@ -72,7 +72,9 @@ const PronoteV6Import: Screen<"PronoteV6Import"> = ({ route, navigation }) => { authentication: { ...refresh, deviceUUID: data.deviceUUID }, personalization: await defaultPersonalization(session), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; pronote.startPresenceInterval(session); diff --git a/src/views/login/pronote/PronoteWebview.tsx b/src/views/login/pronote/PronoteWebview.tsx index bfc3b5091..738b1c4fa 100644 --- a/src/views/login/pronote/PronoteWebview.tsx +++ b/src/views/login/pronote/PronoteWebview.tsx @@ -345,7 +345,9 @@ const PronoteWebview: Screen<"PronoteWebview"> = ({ route, navigation }) => { authentication: { ...refresh, deviceUUID }, personalization: await defaultPersonalization(session), - identity: {} + identity: {}, + serviceData: {}, + providers: [] }; pronote.startPresenceInterval(session); From 204a1c65a9b36703b414de8de5368e1ec65b1f2f Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 18:14:04 +0100 Subject: [PATCH 096/102] fix(ts): account types in `SettingsMultiService.tsx` --- src/views/settings/SettingsMultiService.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 115553149..20fb96827 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -98,7 +98,10 @@ const SettingsMultiService: Screen<"SettingsMultiService"> = ({ navigation }) => studentName: { first: currentAccount.account?.studentName.first || "", last: currentAccount.account?.studentName.last || "" - } + }, + + serviceData: {}, + providers: [] }; const space: MultiServiceSpace = { From 7ccb495cfb859a13bc8ec62c7997b8e721d5ed1e Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sat, 1 Feb 2025 18:29:41 +0100 Subject: [PATCH 097/102] fix(lint): linter fixes --- src/components/Settings/MultiServiceContainerCard.tsx | 5 ++--- src/stores/multiService/index.ts | 1 - src/views/account/Grades/Document.tsx | 2 +- src/views/login/pronote/PronoteCredentials.tsx | 1 - src/views/login/pronote/PronoteInstanceSelector.tsx | 1 - src/views/settings/SettingsMultiService.tsx | 2 +- 6 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/Settings/MultiServiceContainerCard.tsx b/src/components/Settings/MultiServiceContainerCard.tsx index 38ac18c0d..1fb04e5b4 100644 --- a/src/components/Settings/MultiServiceContainerCard.tsx +++ b/src/components/Settings/MultiServiceContainerCard.tsx @@ -1,7 +1,6 @@ -import React, { useState, useEffect } from "react"; -import type { Screen } from "@/router/helpers/types"; +import React, { useEffect } from "react"; -import { ScrollView, Image, Text, View } from "react-native"; +import { View } from "react-native"; import LottieView from "lottie-react-native"; import { NativeItem, NativeList, NativeText } from "../Global/NativeComponents"; import { LinearGradient } from "expo-linear-gradient"; diff --git a/src/stores/multiService/index.ts b/src/stores/multiService/index.ts index 5e32018b5..95792e78e 100644 --- a/src/stores/multiService/index.ts +++ b/src/stores/multiService/index.ts @@ -3,7 +3,6 @@ import { createJSONStorage, persist } from "zustand/middleware"; import { create } from "zustand"; import { log } from "@/utils/logger/logger"; import {MultiServiceSpace, MultiServiceStore} from "@/stores/multiService/types"; -import {useAccounts} from "@/stores/account"; /** diff --git a/src/views/account/Grades/Document.tsx b/src/views/account/Grades/Document.tsx index 845d01c45..2a6eaec4f 100644 --- a/src/views/account/Grades/Document.tsx +++ b/src/views/account/Grades/Document.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from "react"; import { NativeItem, NativeList, NativeListHeader, NativeText, } from "@/components/Global/NativeComponents"; import { getSubjectData } from "@/services/shared/Subject"; import { useTheme } from "@react-navigation/native"; diff --git a/src/views/login/pronote/PronoteCredentials.tsx b/src/views/login/pronote/PronoteCredentials.tsx index f7d37fc2f..da635022f 100644 --- a/src/views/login/pronote/PronoteCredentials.tsx +++ b/src/views/login/pronote/PronoteCredentials.tsx @@ -1,6 +1,5 @@ import React, { useState } from "react"; import type { Screen } from "@/router/helpers/types"; -import { StyleSheet } from "react-native"; import pronote from "pawnote"; import uuid from "@/utils/uuid-v4"; diff --git a/src/views/login/pronote/PronoteInstanceSelector.tsx b/src/views/login/pronote/PronoteInstanceSelector.tsx index 263031aa8..3f5af6d1f 100644 --- a/src/views/login/pronote/PronoteInstanceSelector.tsx +++ b/src/views/login/pronote/PronoteInstanceSelector.tsx @@ -32,7 +32,6 @@ import {Search, X, GraduationCap, SearchX} from "lucide-react-native"; import { useAlert } from "@/providers/AlertProvider"; import { Audio } from "expo-av"; import getInstancesFromDataset from "@/services/pronote/dataset_geolocation"; -import {openURL} from "expo-linking"; import * as WebBrowser from "expo-web-browser"; const PronoteInstanceSelector: Screen<"PronoteInstanceSelector"> = ({ diff --git a/src/views/settings/SettingsMultiService.tsx b/src/views/settings/SettingsMultiService.tsx index 20fb96827..fbb58c8b5 100644 --- a/src/views/settings/SettingsMultiService.tsx +++ b/src/views/settings/SettingsMultiService.tsx @@ -4,7 +4,7 @@ import {useTheme} from "@react-navigation/native"; import type {Screen} from "@/router/helpers/types"; import MultiServiceContainerCard from "@/components/Settings/MultiServiceContainerCard"; import {NativeIcon, NativeItem, NativeList, NativeListHeader, NativeText} from "@/components/Global/NativeComponents"; -import {ImageIcon, PlugZap, Plus, Type, Trash2} from "lucide-react-native"; +import {ImageIcon, PlugZap, Plus, Type} from "lucide-react-native"; import {useAccounts, useCurrentAccount} from "@/stores/account"; import {useMultiService} from "@/stores/multiService"; import BottomSheet from "@/components/Modals/PapillonBottomSheet"; From 1805a24fc6541ff11e9d62471df530f06a8d619a Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sun, 2 Feb 2025 18:24:50 +0100 Subject: [PATCH 098/102] fix(ts): fixed types in account store --- src/stores/account/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stores/account/index.ts b/src/stores/account/index.ts index 11eb6482c..b63f7f366 100644 --- a/src/stores/account/index.ts +++ b/src/stores/account/index.ts @@ -9,7 +9,7 @@ import { Account, AccountService, ExternalAccount, - PrimaryAccount + PrimaryAccount, PapillonMultiServiceSpace } from "@/stores/account/types"; import { reload } from "@/services/reload-account"; import { useTimetableStore } from "../timetable"; @@ -216,7 +216,7 @@ export const useAccounts = create()( // 2. If a multi-service has no more associated accounts, it must be deleted (because a space is like a "group" of accounts, and without any associated accounts it does not work anymore⁾ // Fetching the accounts corresponding to spaces - const spacesAccounts = get().accounts.filter(account => account.service === AccountService.PapillonMultiService); + const spacesAccounts: PapillonMultiServiceSpace[] = get().accounts.filter(account => account.service === AccountService.PapillonMultiService) as PapillonMultiServiceSpace[]; for (const spaceAccount of spacesAccounts) { // The account deleted above is associated to this space From 24445343557217aabeba0a84dcfc67ab61acaa60 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sun, 2 Feb 2025 18:33:08 +0100 Subject: [PATCH 099/102] fix: updates package-lock.json --- package-lock.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index a18f60629..09a1c1801 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,7 +71,7 @@ "openid-client": "^5.7.0", "pawdirecte": "^1.7.1", "pawnilim": "^0.2.0", - "pawnote": "^1.3.4", + "pawnote": "^1.4.1", "pawrd": "^0.6.1", "react": "18.2.0", "react-native": "^0.74.3", @@ -13939,10 +13939,9 @@ } }, "node_modules/pawnote": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/pawnote/-/pawnote-1.3.4.tgz", - "integrity": "sha512-8VMb3vA09z9kM9V2oMCJDNMBOK71gn9p5r2QqoGy/IE5g5Pn2vYR9gaVBmpEgahETz7mGw1mUMzXZeSm212s9w==", - "license": "GPL-3.0-or-later", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/pawnote/-/pawnote-1.4.1.tgz", + "integrity": "sha512-jdFHfyZ7tIRJ03etegs/ExgW2F2KZDPbOq6atjs6Fi1DINl893QLfVIxLwADb+tGQbYifYwwOurv4QZQ1OJZ8Q==", "dependencies": { "@literate.ink/utilities": "1.0.0-10641118381.1", "html-entities": "^2.5.2", From c5412d270e1a2546acead131715df9cab2fc1b70 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sun, 2 Feb 2025 18:46:23 +0100 Subject: [PATCH 100/102] fix: switching the typecheck workflow to npm (which is the project's package manager) --- .github/workflows/checks.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 30d27a45c..34849576d 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -18,13 +18,13 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Pnpm setup - uses: pnpm/action-setup@v2 + - name: NPM setup + uses: actions/setup-node@v2 with: - version: latest + version: 20 - name: Environnement setup - run: pnpm install + run: npm install - name: Typescript and Eslint scanning - run: pnpm lint + run: npm run lint From da3823c77458614932e98a2394f3823cd13a28b6 Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sun, 2 Feb 2025 18:55:21 +0100 Subject: [PATCH 101/102] fix(deps): updated `react-native-gesture-handler` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 68c198693..a40545cc7 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "react-native-barcode-svg": "^0.0.15", "react-native-draggable-flatlist": "^4.0.1", "react-native-draglist": "^3.6.1", - "react-native-gesture-handler": "^2.21.2", + "react-native-gesture-handler": "^2.22.1", "react-native-htmlview": "^0.17.0", "react-native-infinite-pager": "^0.3.16", "react-native-pager-view": "6.3.0", From d4c7e08d517a6fdded2b286a8ed85237ab803bca Mon Sep 17 00:00:00 2001 From: camarm-dev Date: Sun, 2 Feb 2025 19:15:13 +0100 Subject: [PATCH 102/102] fix(deps): updated `react-native-gesture-handler` maybe it will resolve ts --- package-lock.json | 16 +++++++--------- package.json | 4 ++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0999a01e8..b7d569d74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "papillonvex", - "version": "7.8.2", + "version": "7.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "papillonvex", - "version": "7.8.2", + "version": "7.9.0", "dependencies": { "@birdwingo/react-native-reanimated-graph": "^1.1.3", "@candlefinance/app-icon": "^0.4.5", @@ -78,7 +78,7 @@ "react-native-barcode-svg": "^0.0.15", "react-native-draggable-flatlist": "^4.0.1", "react-native-draglist": "^3.6.1", - "react-native-gesture-handler": "~2.16.1", + "react-native-gesture-handler": "^2.22.1", "react-native-htmlview": "^0.17.0", "react-native-infinite-pager": "^0.3.16", "react-native-pager-view": "6.3.0", @@ -14720,15 +14720,13 @@ } }, "node_modules/react-native-gesture-handler": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.16.2.tgz", - "integrity": "sha512-vGFlrDKlmyI+BT+FemqVxmvO7nqxU33cgXVsn6IKAFishvlG3oV2Ds67D5nPkHMea8T+s1IcuMm0bF8ntZtAyg==", + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.22.1.tgz", + "integrity": "sha512-E0C9D+Ia2UZYevoSV9rTKjhFWEVdR/3l4Z3TUoQrI/wewgzDlmJOrYvGW5aMlPUuQF2vHQOdFfAWhVEqFu4tWw==", "dependencies": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", - "invariant": "^2.2.4", - "lodash": "^4.17.21", - "prop-types": "^15.7.2" + "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", diff --git a/package.json b/package.json index 2b2295f29..a40545cc7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "papillonvex", - "version": "7.8.2", + "version": "7.9.0", "main": "node_modules/expo/AppEntry.js", "scripts": { "start": "expo start", @@ -80,7 +80,7 @@ "react-native-barcode-svg": "^0.0.15", "react-native-draggable-flatlist": "^4.0.1", "react-native-draglist": "^3.6.1", - "react-native-gesture-handler": "~2.16.1", + "react-native-gesture-handler": "^2.22.1", "react-native-htmlview": "^0.17.0", "react-native-infinite-pager": "^0.3.16", "react-native-pager-view": "6.3.0",