Skip to content

Commit 9adcfa9

Browse files
CrisTofanidmnplb
andauthored
feat: [IOPLT-1291] Enable the theme switch on global app preferences (#7290)
> [!note] > This PR depends on pagopa/io-app-design-system#488 ## Short description This PR enables the in-app preference to pick the preferred color mode: - `system` the app theme follows the system theme - `light` app has the light theme - `dark` app has the dark theme ## List of changes proposed in this pull request - information is memorized in the AsyncStorage with specific key to load on any app start - information affects the DS theme configuration - an hook handles the app startup configuration and system theme updates - Preferences screen overrides DS theme and AsyncStorage saving. ## How to test Change theme preference on Settings > Appearance Preferences and switch between themes. https://github.com/user-attachments/assets/b7b6173e-22ec-49ff-9114-deabf75138b0 --------- Co-authored-by: Damiano Plebani <[email protected]>
1 parent 8cedabc commit 9adcfa9

File tree

19 files changed

+375
-289
lines changed

19 files changed

+375
-289
lines changed

ios/ItaliaApp/Info.plist

Lines changed: 89 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -70,96 +70,94 @@
7070
<string>The app needs NSAppleMusicUsageDescription permission</string>
7171
<key>NSBluetoothAlwaysUsageDescription</key>
7272
<string>IO richiede l'accesso al Bluetooth per completare la verifica dei documenti</string>
73-
<key>NSBluetoothPeripheralUsageDescription</key>
73+
<key>NSBluetoothPeripheralUsageDescription</key>
7474
<string>IO richiede l'accesso al Bluetooth per completare la verifica dei documenti</string>
75-
<key>NSCalendarsUsageDescription</key>
76-
<string>So that you’ll be able to add deadlines to your calendar and set a reminder.</string>
77-
<key>NSCameraUsageDescription</key>
78-
<string>You’ll be able to read QR codes and pay pagoPA notices.</string>
79-
<key>NSContactsUsageDescription</key>
80-
<string>IO needs access to your contacts to let you add them in calendar events</string>
81-
<key>NSFaceIDUsageDescription</key>
75+
<key>NSCalendarsUsageDescription</key>
76+
<string>So that you’ll be able to add deadlines to your calendar and set a reminder.</string>
77+
<key>NSCameraUsageDescription</key>
78+
<string>You’ll be able to read QR codes and pay pagoPA notices.</string>
79+
<key>NSContactsUsageDescription</key>
80+
<string>IO needs access to your contacts to let you add them in calendar events</string>
81+
<key>NSFaceIDUsageDescription</key>
8282
<string>You'll be able to access the app more easily without having to enter the unlock code.</string>
83-
<key>NSLocationAlwaysUsageDescription</key>
84-
<string>The app needs NSLocationAlwaysUsageDescription permission</string>
85-
<key>NSLocationUsageDescription</key>
86-
<string>The app needs NSLocationUsageDescription permission</string>
87-
<key>NSLocationWhenInUseUsageDescription</key>
88-
<string>The app needs NSLocationWhenInUseUsageDescription permission</string>
89-
<key>NSMicrophoneUsageDescription</key>
90-
<string>IO needs access to the microphone in case you want to leave a voice note</string>
91-
<key>NSMotionUsageDescription</key>
92-
<string>The app needs NSMotionUsageDescription permission</string>
93-
<key>NSPhotoLibraryAddUsageDescription</key>
94-
<string>You will be able to save pictures from the app to your device.</string>
95-
<key>NSPhotoLibraryUsageDescription</key>
96-
<string>You’ll be able to save bonuses, certificates and upload screenshots or payment notices.</string>
97-
<key>NSSpeechRecognitionUsageDescription</key>
98-
<string>The app needs NSSpeechRecognitionUsageDescription permission</string>
99-
<key>UIAppFonts</key>
100-
<array>
101-
<string>DMMono-Medium.ttf</string>
102-
<string>TitilliumSansPro-Black.otf</string>
103-
<string>TitilliumSansPro-Bold.otf</string>
104-
<string>TitilliumSansPro-Light.otf</string>
105-
<string>TitilliumSansPro-Regular.otf</string>
106-
<string>TitilliumSansPro-Semibold.otf</string>
107-
<string>TitilliumSansPro-Thin.otf</string>
108-
<string>TitilliumSansPro-BlackItalic.otf</string>
109-
<string>TitilliumSansPro-BoldItalic.otf</string>
110-
<string>TitilliumSansPro-Italic.otf</string>
111-
<string>TitilliumSansPro-LightItalic.otf</string>
112-
<string>TitilliumSansPro-SemiboldItalic.otf</string>
113-
<string>TitilliumSansPro-ThinItalic.otf</string>
114-
<string>Titillio-Black.otf</string>
115-
<string>Titillio-BlackItalic.otf</string>
116-
<string>Titillio-Bold.otf</string>
117-
<string>Titillio-BoldItalic.otf</string>
118-
<string>Titillio-Extrablack.otf</string>
119-
<string>Titillio-ExtrablackItalic.otf</string>
120-
<string>Titillio-Extrabold.otf</string>
121-
<string>Titillio-ExtraboldItalic.otf</string>
122-
<string>Titillio-Light.otf</string>
123-
<string>Titillio-LightItalic.otf</string>
124-
<string>Titillio-Regular.otf</string>
125-
<string>Titillio-RegularItalic.otf</string>
126-
<string>Titillio-Semibold.otf</string>
127-
<string>Titillio-SemiboldItalic.otf</string>
128-
<string>Titillio-Thin.otf</string>
129-
<string>Titillio-ThinItalic.otf</string>
130-
</array>
131-
<key>UIBackgroundModes</key>
132-
<array>
133-
<string>remote-notification</string>
134-
</array>
135-
<key>UIFileSharingEnabled</key>
136-
<true/>
137-
<key>UILaunchStoryboardName</key>
138-
<string>LaunchScreen</string>
139-
<key>UIRequiredDeviceCapabilities</key>
140-
<array>
141-
<string>arm64</string>
142-
</array>
143-
<key>UISupportedInterfaceOrientations</key>
144-
<array>
145-
<string>UIInterfaceOrientationPortrait</string>
146-
</array>
147-
<key>UIViewControllerBasedStatusBarAppearance</key>
148-
<false/>
149-
<key>CADisableMinimumFrameDurationOnPhone</key>
150-
<true/>
151-
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
152-
<array>
153-
<string>A0000000308000000009816001</string>
154-
<string>A00000000039</string>
155-
<string>A0000002471001</string>
156-
<string>00000000000000</string>
157-
</array>
158-
<key>method</key>
159-
<string>app-store</string>
160-
<key>UIStatusBarStyle</key>
161-
<string>UIStatusBarStyleLightContent</string>
162-
<key>UIUserInterfaceStyle</key>
163-
<string>Light</string>
164-
</dict>
165-
</plist>
83+
<key>NSLocationAlwaysUsageDescription</key>
84+
<string>The app needs NSLocationAlwaysUsageDescription permission</string>
85+
<key>NSLocationUsageDescription</key>
86+
<string>The app needs NSLocationUsageDescription permission</string>
87+
<key>NSLocationWhenInUseUsageDescription</key>
88+
<string>The app needs NSLocationWhenInUseUsageDescription permission</string>
89+
<key>NSMicrophoneUsageDescription</key>
90+
<string>IO needs access to the microphone in case you want to leave a voice note</string>
91+
<key>NSMotionUsageDescription</key>
92+
<string>The app needs NSMotionUsageDescription permission</string>
93+
<key>NSPhotoLibraryAddUsageDescription</key>
94+
<string>You will be able to save pictures from the app to your device.</string>
95+
<key>NSPhotoLibraryUsageDescription</key>
96+
<string>You’ll be able to save bonuses, certificates and upload screenshots or payment notices.</string>
97+
<key>NSSpeechRecognitionUsageDescription</key>
98+
<string>The app needs NSSpeechRecognitionUsageDescription permission</string>
99+
<key>UIAppFonts</key>
100+
<array>
101+
<string>DMMono-Medium.ttf</string>
102+
<string>TitilliumSansPro-Black.otf</string>
103+
<string>TitilliumSansPro-Bold.otf</string>
104+
<string>TitilliumSansPro-Light.otf</string>
105+
<string>TitilliumSansPro-Regular.otf</string>
106+
<string>TitilliumSansPro-Semibold.otf</string>
107+
<string>TitilliumSansPro-Thin.otf</string>
108+
<string>TitilliumSansPro-BlackItalic.otf</string>
109+
<string>TitilliumSansPro-BoldItalic.otf</string>
110+
<string>TitilliumSansPro-Italic.otf</string>
111+
<string>TitilliumSansPro-LightItalic.otf</string>
112+
<string>TitilliumSansPro-SemiboldItalic.otf</string>
113+
<string>TitilliumSansPro-ThinItalic.otf</string>
114+
<string>Titillio-Black.otf</string>
115+
<string>Titillio-BlackItalic.otf</string>
116+
<string>Titillio-Bold.otf</string>
117+
<string>Titillio-BoldItalic.otf</string>
118+
<string>Titillio-Extrablack.otf</string>
119+
<string>Titillio-ExtrablackItalic.otf</string>
120+
<string>Titillio-Extrabold.otf</string>
121+
<string>Titillio-ExtraboldItalic.otf</string>
122+
<string>Titillio-Light.otf</string>
123+
<string>Titillio-LightItalic.otf</string>
124+
<string>Titillio-Regular.otf</string>
125+
<string>Titillio-RegularItalic.otf</string>
126+
<string>Titillio-Semibold.otf</string>
127+
<string>Titillio-SemiboldItalic.otf</string>
128+
<string>Titillio-Thin.otf</string>
129+
<string>Titillio-ThinItalic.otf</string>
130+
</array>
131+
<key>UIBackgroundModes</key>
132+
<array>
133+
<string>remote-notification</string>
134+
</array>
135+
<key>UIFileSharingEnabled</key>
136+
<true/>
137+
<key>UILaunchStoryboardName</key>
138+
<string>LaunchScreen</string>
139+
<key>UIRequiredDeviceCapabilities</key>
140+
<array>
141+
<string>arm64</string>
142+
</array>
143+
<key>UISupportedInterfaceOrientations</key>
144+
<array>
145+
<string>UIInterfaceOrientationPortrait</string>
146+
</array>
147+
<key>UIViewControllerBasedStatusBarAppearance</key>
148+
<false/>
149+
<key>CADisableMinimumFrameDurationOnPhone</key>
150+
<true/>
151+
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
152+
<array>
153+
<string>A0000000308000000009816001</string>
154+
<string>A00000000039</string>
155+
<string>A0000002471001</string>
156+
<string>00000000000000</string>
157+
</array>
158+
<key>method</key>
159+
<string>app-store</string>
160+
<key>UIStatusBarStyle</key>
161+
<string>UIStatusBarStyleLightContent</string>
162+
</dict>
163+
</plist>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
"@babel/plugin-transform-react-jsx": "^7.25.9",
5959
"@babel/plugin-transform-regenerator": "^7.18.6",
6060
"@gorhom/bottom-sheet": "^5.1.2",
61-
"@pagopa/io-app-design-system": "5.9.0",
61+
"@pagopa/io-app-design-system": "5.10.1",
6262
"@pagopa/io-pagopa-commons": "^3.1.0",
6363
"@pagopa/io-react-native-cie": "^1.1.0",
6464
"@pagopa/io-react-native-cieid": "^0.3.5",

ts/RootContainer.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
} from "./store/reducers/persistedPreferences";
2828
import { GlobalState } from "./store/reducers/types";
2929
import { Store } from "./store/actions/types";
30+
import { useAppThemeConfiguration } from "./hooks/useAppThemeConfiguration";
3031
import { setLocale } from "./i18n";
3132

3233
type Props = ReturnType<typeof mapStateToProps> &
@@ -145,4 +146,15 @@ const mapDispatchToProps = {
145146
setScreenReaderEnabled
146147
};
147148

148-
export default connect(mapStateToProps, mapDispatchToProps)(RootContainer);
149+
const RootContainerClass = connect(
150+
mapStateToProps,
151+
mapDispatchToProps
152+
)(RootContainer);
153+
154+
const RootContainerFC = ({ store }: { store: Store }) => {
155+
useAppThemeConfiguration();
156+
157+
return <RootContainerClass store={store} />;
158+
};
159+
160+
export default RootContainerFC;

ts/boot/__tests__/__snapshots__/persistedStore.test.ts.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ exports[`Check the addition for new fields to the persisted store. If one of thi
9292
"isPnTestEnabled": false,
9393
"preferredCalendar": undefined,
9494
"preferredLanguage": undefined,
95+
"themePreference": "light",
9596
"wasServiceAlertDisplayedOnce": false,
9697
}
9798
`;

ts/boot/__tests__/configureStoreAndPersistor.test.ts

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe("configureStoreAndPersistor", () => {
2626
describe("CURRENT_REDUX_STORE_VERSION", () => {
2727
it("should match expected value", () => {
2828
const version = testable!.CURRENT_REDUX_STORE_VERSION;
29-
expect(version).toBe(47);
29+
expect(version).toBe(48);
3030
});
3131
});
3232
describe("migrations", () => {
@@ -513,5 +513,70 @@ describe("configureStoreAndPersistor", () => {
513513
}
514514
});
515515
});
516+
// Test for 47 to 48
517+
it("should migrate from 47 to 48", () => {
518+
const persistedStateAt47 = {
519+
content: {
520+
idps: remoteUndefined,
521+
municipality: {
522+
codiceCatastale: pot.none,
523+
data: pot.none
524+
},
525+
contextualHelp: pot.none
526+
},
527+
crossSessions: {
528+
hashedFiscalCode:
529+
"6494e783ad296f016b2105f8fe7dc2979551a37d3a5c40624e2ee8eee64e8017"
530+
},
531+
installation: {
532+
isFirstRunAfterInstall: false,
533+
appVersionHistory: [
534+
"3.3.0.8",
535+
"3.4.0.5",
536+
"3.5.0.8",
537+
"3.6.0.9",
538+
"3.7.0.7",
539+
"3.8.0.9",
540+
"3.9.0.6",
541+
"3.10.0.6",
542+
"3.11.0.4",
543+
"3.12.0.7"
544+
]
545+
},
546+
onboarding: {
547+
isFingerprintAcknowledged: false
548+
},
549+
persistedPreferences: {
550+
isFingerprintEnabled: undefined,
551+
preferredCalendar: undefined,
552+
preferredLanguage: undefined,
553+
wasServiceAlertDisplayedOnce: false,
554+
isPagoPATestEnabled: false,
555+
isCustomEmailChannelEnabled: pot.none,
556+
continueWithRootOrJailbreak: false,
557+
isMixpanelEnabled: null,
558+
isPnTestEnabled: false,
559+
isIdPayTestEnabled: false,
560+
fontPreference: "comfortable",
561+
isExperimentalDesignEnabled: false,
562+
isAarFeatureEnabled: false
563+
},
564+
profile: pot.none,
565+
_persist: {
566+
version: 47,
567+
rehydrated: false
568+
}
569+
};
570+
const from47To48Migration = testable!.migrations[48];
571+
expect(from47To48Migration).toBeDefined();
572+
const globalStateAt48 = from47To48Migration(persistedStateAt47);
573+
expect(globalStateAt48).toEqual({
574+
...persistedStateAt47,
575+
persistedPreferences: {
576+
...persistedStateAt47.persistedPreferences,
577+
themePreference: "light"
578+
}
579+
});
580+
});
516581
});
517582
});

ts/boot/configureStoreAndPersistor.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ import { configureReactotron } from "./configureRectotron";
6262
/**
6363
* Redux persist will migrate the store to the current version
6464
*/
65-
const CURRENT_REDUX_STORE_VERSION = 47;
65+
const CURRENT_REDUX_STORE_VERSION = 48;
6666

6767
// see redux-persist documentation:
6868
// https://github.com/rt2zz/redux-persist/blob/master/docs/migrations.md
@@ -598,6 +598,17 @@ const migrations: MigrationManifest = {
598598
isAarFeatureEnabled: false
599599
}
600600
};
601+
},
602+
// Add 'themePreference' to 'persistedPreferences'
603+
"48": (state: PersistedState) => {
604+
const typedState = state as GlobalState;
605+
return {
606+
...state,
607+
persistedPreferences: {
608+
...typedState.persistedPreferences,
609+
themePreference: "light"
610+
}
611+
};
601612
}
602613
};
603614

0 commit comments

Comments
 (0)