diff --git a/assets/translations/en.json b/assets/translations/en.json
index a4e19efc..f06db48c 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -1,4 +1,15 @@
{
+ "accessibilitySettingsScreen": {
+ "title": "Accessibility settings",
+ "customFontTitle": "Custom font",
+ "customFontAction": "Pick a font",
+ "customFontPlacement": "Use it for",
+ "themeCustomizationTitle": "Theme customization",
+ "customFontSectionTitle": "Accessible font",
+ "customThemeSectionTitle": "Accessible theme",
+ "highContrastTitle": "High contrast",
+ "greyscaleTitle": "Greyscale"
+ },
"agendaScreen": {
"backToToday": "Back to today",
"dailyLayout": "Daily layout",
@@ -73,6 +84,7 @@
"yellow": "Yellow"
},
"common": {
+ "accessibility": "Accessibility",
"actionPotentiallyNotUndoable": "This action may not be undoable",
"activeStatus": {
"false": "Non active",
diff --git a/assets/translations/it.json b/assets/translations/it.json
index 44fff0f8..9bc4003b 100644
--- a/assets/translations/it.json
+++ b/assets/translations/it.json
@@ -1,4 +1,15 @@
{
+ "accessibilitySettingsScreen": {
+ "title": "Impostazioni di accessibilità ",
+ "customFontTitle": "Font personalizzato",
+ "customFontDefault": "No custom font",
+ "customFontAction": "Seleziona un font",
+ "customFontPlacement": "Usalo per",
+ "customFontSectionTitle": "Font accessibile",
+ "customThemeSectionTitle": "Tema accessibile",
+ "highContrastTitle": "Alto contrasto",
+ "greyscaleTitle": "Scala di grigi"
+ },
"agendaScreen": {
"backToToday": "Torna a oggi",
"dailyLayout": "Layout giornaliero",
@@ -73,6 +84,7 @@
"yellow": "Giallo"
},
"common": {
+ "accessibility": "Accessibilità ",
"actionPotentiallyNotUndoable": "Questa azione potrebbe non essere annullabile",
"activeStatus": {
"false": "Non attiva",
diff --git a/lib/ui/components/ListItem.tsx b/lib/ui/components/ListItem.tsx
index c552c119..2df08fcd 100644
--- a/lib/ui/components/ListItem.tsx
+++ b/lib/ui/components/ListItem.tsx
@@ -1,6 +1,5 @@
import {
StyleProp,
- TextProps,
TextStyle,
TouchableHighlight,
TouchableHighlightProps,
@@ -20,7 +19,7 @@ import { GlobalStyles } from '../../../src/core/styles/GlobalStyles';
import { resolveLinkTo } from '../../../src/utils/resolveLinkTo';
import { useTheme } from '../hooks/useTheme';
import { DisclosureIndicator } from './DisclosureIndicator';
-import { Text } from './Text';
+import { Text, TextProps } from './Text';
export interface ListItemProps extends TouchableHighlightProps {
title: string | JSX.Element;
diff --git a/lib/ui/components/Metric.tsx b/lib/ui/components/Metric.tsx
index 07bb4e38..6113418f 100644
--- a/lib/ui/components/Metric.tsx
+++ b/lib/ui/components/Metric.tsx
@@ -2,7 +2,7 @@ import { View, ViewProps } from 'react-native';
import { useTheme } from '../hooks/useTheme';
import { CardProps } from './Card';
-import { Text, Props as TextProps } from './Text';
+import { Text, TextProps } from './Text';
type Props = ViewProps & {
title: string;
diff --git a/lib/ui/components/Text.tsx b/lib/ui/components/Text.tsx
index 906643bd..73f14ff3 100644
--- a/lib/ui/components/Text.tsx
+++ b/lib/ui/components/Text.tsx
@@ -1,10 +1,14 @@
-import { Text as RNText, StyleSheet, TextProps } from 'react-native';
+import {
+ Text as RNText,
+ TextProps as RNTextProps,
+ StyleSheet,
+} from 'react-native';
import { useStylesheet } from '../hooks/useStylesheet';
import { useTheme } from '../hooks/useTheme';
import { Theme } from '../types/Theme';
-export interface Props extends TextProps {
+export interface TextProps extends RNTextProps {
variant?:
| 'heading'
| 'subHeading'
@@ -45,7 +49,7 @@ export const Text = ({
uppercase,
children,
...rest
-}: Props) => {
+}: TextProps) => {
const { colors, fontFamilies, fontWeights } = useTheme();
const styles = useStylesheet(createStyles);
const fontFamilyName =
diff --git a/src/core/contexts/PreferencesContext.ts b/src/core/contexts/PreferencesContext.ts
index 76ca597a..fa3b141d 100644
--- a/src/core/contexts/PreferencesContext.ts
+++ b/src/core/contexts/PreferencesContext.ts
@@ -7,35 +7,37 @@ import { AgendaTypesFilterState } from '../../features/agenda/types/AgendaTypesF
import { UnreadNotifications } from '../types/notifications';
export const editablePreferenceKeys = [
- 'lastInstalledVersion',
- 'username',
+ 'accessibility',
+ 'agendaScreen',
'campusId',
'colorScheme',
'courses',
+ 'emailGuideRead',
+ 'favoriteServices',
'language',
+ 'lastInstalledVersion',
'notifications',
- 'favoriteServices',
- 'peopleSearched',
- 'unreadNotifications',
'onboardingStep',
- 'emailGuideRead',
+ 'peopleSearched',
'placesSearched',
- 'agendaScreen',
+ 'unreadNotifications',
+ 'username',
] as const;
export type PreferenceKey = typeof editablePreferenceKeys[number];
// Specify here complex keys, that require serialization/deserialization
export const objectPreferenceKeys = [
+ 'accessibility',
+ 'agendaScreen',
'courses',
- 'notifications',
+ 'emailGuideRead',
'favoriteServices',
- 'peopleSearched',
- 'unreadNotifications',
+ 'notifications',
'onboardingStep',
- 'emailGuideRead',
+ 'peopleSearched',
'placesSearched',
- 'agendaScreen',
+ 'unreadNotifications',
];
export type CoursesPreferences = {
@@ -74,6 +76,12 @@ export interface PreferencesContextBase {
layout: 'weekly' | 'daily';
filters: AgendaTypesFilterState;
};
+ accessibility?: {
+ fontFamily?: 'default' | 'open-dyslexic';
+ fontPlacement?: 'default' | 'bottom';
+ highContrast?: boolean;
+ grayscale?: boolean;
+ };
}
export interface PreferencesContextProps extends PreferencesContextBase {
diff --git a/src/features/user/components/UserNavigator.tsx b/src/features/user/components/UserNavigator.tsx
index 120198cf..d4823438 100644
--- a/src/features/user/components/UserNavigator.tsx
+++ b/src/features/user/components/UserNavigator.tsx
@@ -9,6 +9,7 @@ import { useTitlesStyles } from '../../../core/hooks/useTitlesStyles';
import { SharedScreens } from '../../../shared/navigation/SharedScreens';
import { DegreeTopTabsNavigator } from '../../offering/navigation/DegreeTopTabsNavigator';
import { OfferingStackParamList } from '../../services/components/ServicesNavigator';
+import { AccessibilitySettingsScreen } from '../screens/AccessibilitySettingsScreen';
import { MessageScreen } from '../screens/MessageScreen';
import { MessagesScreen } from '../screens/MessagesScreen';
import { ProfileScreen } from '../screens/ProfileScreen';
@@ -17,6 +18,7 @@ import { SettingsScreen } from '../screens/SettingsScreen';
export type UserStackParamList = OfferingStackParamList & {
Profile: undefined;
Settings: undefined;
+ AccessibilitySettings: undefined;
Messages: undefined;
Message: {
id: number;
@@ -59,6 +61,14 @@ export const UserNavigator = () => {
headerTitle: t('settingsScreen.title'),
}}
/>
+
void;
+}
+
+export const AccessibilitySettingsScreen = () => {
+ const { t } = useTranslation();
+ const { accessibility } = usePreferencesContext();
+
+ return (
+
+
+
+
+
+
+
+ {
+ // TODO
+ }}
+ />
+ {
+ // TODO
+ }}
+ />
+
+
+
+
+
+
+ );
+};
+
+const CustomFontListItem = ({ t, value }: AccessibilityItemProps) => {
+ const choices = useMemo(() => {
+ return [
+ 'Montserrat (default)',
+ 'Open Dyslexic',
+ 'Dyslexie',
+ 'EasyReading',
+ 'Sylexiad',
+ ];
+ }, []);
+
+ const effectiveValue = useMemo(() => {
+ return value || 'default';
+ }, [value]);
+
+ const actions: MenuAction[] = useMemo(() => {
+ return choices.map(cc => {
+ const actionValue = cc.endsWith('(default)') ? 'default' : cc;
+ return {
+ id: actionValue,
+ title: cc,
+ state: actionValue === effectiveValue ? 'on' : undefined,
+ };
+ });
+ }, [effectiveValue, choices]);
+
+ return (
+ {
+ // onUpdate(effectiveValue);
+ }}
+ >
+
+
+ );
+};
+
+const CustomFontPlacementListItem = ({ t, value }: AccessibilityItemProps) => {
+ const choices = useMemo(() => {
+ // places in which to use the custom font for accessibility
+ return ['None', 'Long text', 'All text'];
+ }, []);
+
+ const effectiveValue = useMemo(() => {
+ return value || 'none';
+ }, [value]);
+
+ const effectiveLabel = useMemo(() => {
+ return effectiveValue.replace('-', ' ');
+ }, [effectiveValue]);
+
+ const actions: MenuAction[] = useMemo(() => {
+ return choices.map(cc => {
+ const choiceId = cc.toLowerCase().replace(' ', '-');
+ return {
+ id: choiceId,
+ title: cc,
+ state: choiceId === effectiveValue ? 'on' : undefined,
+ };
+ });
+ }, [effectiveValue, choices]);
+
+ return (
+ {
+ // onUpdate(effectiveValue);
+ }}
+ >
+
+
+ );
+};
diff --git a/src/features/user/screens/SettingsScreen.tsx b/src/features/user/screens/SettingsScreen.tsx
index b3827ed3..e2929322 100644
--- a/src/features/user/screens/SettingsScreen.tsx
+++ b/src/features/user/screens/SettingsScreen.tsx
@@ -327,6 +327,17 @@ export const SettingsScreen = () => {
+
{t('settingsScreen.appVersion', { version })}