Skip to content

Commit

Permalink
fix(booking-hooks): accessibility
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandropremoli committed Dec 18, 2024
2 parents b703c8a + d47c047 commit dcfc7c0
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 6 deletions.
1 change: 1 addition & 0 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
"hour": "Hour",
"hours": "Hour",
"icon": "Icon",
"image": "Image",
"inYourAgenda": "in your agenda",
"it": "Italian",
"language": "Language",
Expand Down
1 change: 1 addition & 0 deletions assets/translations/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
"hour": "Orario",
"hours": "Ore",
"icon": "Icona",
"image": "Immagine",
"inYourAgenda": "nella tua agenda",
"it": "Italiano",
"language": "Lingua",
Expand Down
4 changes: 2 additions & 2 deletions src/core/components/TextWithLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PropsWithChildren } from 'react';
import { TextProps } from 'react-native';
import { MixedStyleDeclaration } from 'react-native-render-html';

import { linkUrls } from '../../utils/html';
import { linkUrls, replaceImgWithAnchorTags } from '../../utils/html';
import { HtmlView } from './HtmlView';

type Props = {
Expand All @@ -11,7 +11,7 @@ type Props = {

export const TextWithLinks = ({ baseStyle, children, style }: Props) => {
if (!children || typeof children !== 'string') return null;
const html = linkUrls(children);
const html = linkUrls(replaceImgWithAnchorTags(children));
return (
<HtmlView
source={{ html }}
Expand Down
20 changes: 19 additions & 1 deletion src/features/courses/screens/CourseDirectoryScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { CourseDirectory, CourseFileOverview } from '@polito/api-client';
import { useFocusEffect } from '@react-navigation/native';
import { NativeStackScreenProps } from '@react-navigation/native-stack';

import { DateTime } from 'luxon';

import { BottomBarSpacer } from '../../../core/components/BottomBarSpacer';
import { useSafeAreaSpacing } from '../../../core/hooks/useSafeAreaSpacing';
import {
Expand Down Expand Up @@ -59,6 +61,20 @@ export const CourseDirectoryScreen = ({ route, navigation }: Props) => {
});
}, [directoryName, navigation, t]);

directoryQuery.data?.sort((a, b) => {
if (a.type !== 'directory' && b.type !== 'directory') {
const dateA = DateTime.fromJSDate(a.createdAt).startOf('minute');
const dateB = DateTime.fromJSDate(b.createdAt).startOf('minute');

if (dateA.equals(dateB)) {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
}

return dateA > dateB ? -1 : 1;
}
return 0;
});

return (
<CourseContext.Provider value={courseId}>
<CourseFilesCacheProvider>
Expand Down Expand Up @@ -119,7 +135,9 @@ const CourseFileSearchFlatList = ({ courseId, searchFilter }: SearchProps) => {
useEffect(() => {
if (!recentFilesQuery.data) return;
setSearchResults(
recentFilesQuery.data.filter(file => file.name.includes(searchFilter)),
recentFilesQuery.data.filter(file =>
file.name.toLowerCase().includes(searchFilter.toLowerCase()),
),
);
}, [recentFilesQuery.data, searchFilter]);

Expand Down
4 changes: 2 additions & 2 deletions src/features/tickets/components/TextMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useStylesheet } from '@lib/ui/hooks/useStylesheet';
import { Theme } from '@lib/ui/types/Theme';

import { TextWithLinks } from '../../../core/components/TextWithLinks';
import { getHtmlTextContent } from '../../../utils/html';
import { sanitizeHtml } from '../../../utils/html';

export interface TextMessageProps {
message: string;
Expand All @@ -15,7 +15,7 @@ export const TextMessage = ({ message }: TextMessageProps) => {
const styles = useStylesheet(createStyles);

const textMessage = useMemo(() => {
return getHtmlTextContent(message);
return sanitizeHtml(message ?? '');
}, [message]);

return <TextWithLinks style={styles.text}>{textMessage}</TextWithLinks>;
Expand Down
10 changes: 9 additions & 1 deletion src/utils/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Document } from 'react-native-render-html';

import { innerText } from 'domutils';
import { parseDocument } from 'htmlparser2';
import i18next from 'i18next';

export const sanitizeHtml = (html: string) =>
html.replace(/\r/g, '').replace(/\\r/g, '').replace(/\\"/g, '"').trim();
Expand All @@ -11,9 +12,16 @@ export const getHtmlTextContent = (text: string) => {
return innerText(dom.children as any[]);
};

export const replaceImgWithAnchorTags = (html: string) => {
const imgRegex = /<img[^>]*src="([^">]*)"[^>]*>/gi;
return html.replace(imgRegex, (_, src) => {
return `<a href="${src}">${i18next.t('common.image')}</a>`;
});
};

export const linkUrls = (html: string) => {
const regex =
/(?!<a[^>]*>[^<])(?:https?:\/\/|www\.)(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[A-Z0-9+&@#/%=~_|$])(?![^<]*<\/a>)/gi;
/(?!<a[^>]*>[^<])(?:https?:\/\/(?:www\.)?|www\.)?(?:[A-Z0-9-]+(?:[-.][A-Z0-9]+)*\.[A-Z]{2,5})(?::[0-9]{1,5})?(?:\/[A-Z0-9\-._~:/?#[\]@!$&'()*+,;=]*)?(?:\?[A-Z0-9\-._~:/?#[\]@!$&'()*+,;=%]*)?(?:#[A-Z0-9\-._~:/?#[\]@!$&'()*+,;=%]*)?(?![^<]*<\/a>)(?<!\.)/gi;
return html.replace(regex, match => {
if (!match.startsWith('http')) match = `https://${match}`;
return `<a href="${match}">${match}</a>`;
Expand Down

0 comments on commit dcfc7c0

Please sign in to comment.