diff --git a/app/(tabs)/settings.tsx b/app/(tabs)/settings.tsx
index 45faac2..8859a40 100644
--- a/app/(tabs)/settings.tsx
+++ b/app/(tabs)/settings.tsx
@@ -7,6 +7,7 @@ import { ScrollContent } from '../../components/base/scroll-content';
import { Header } from '../../components/common/header';
import { Setting } from '../../components/common/settings/setting';
import { Title } from '../../components/common/title';
+import { AppDetails } from '../../components/settings/app-details';
import i18n from '../../services/i18-next';
import { SettingsStorageService } from '../../services/settings-storage.service';
import { SettingsType } from '../../types/settings.type';
@@ -89,6 +90,7 @@ export default function SettingsPage() {
{/* currentValue={settings?.notifications ?? false}*/}
{/* onChange={toggleNotifications}*/}
{/*/>*/}
+
);
diff --git a/components/common/error-boundary.tsx b/components/common/error-boundary.tsx
index 45fa8c7..3a7162a 100644
--- a/components/common/error-boundary.tsx
+++ b/components/common/error-boundary.tsx
@@ -14,7 +14,7 @@ export function ErrorBoundary(props: ErrorBoundaryProps) {
usePageView('error');
return (
{props.error.message}
{t('errBoundary.sub')}
-
+
{t('errBoundary.retry')}
diff --git a/components/map/resource-sheet.tsx b/components/map/resource-sheet.tsx
index 8ee78dc..50b937c 100644
--- a/components/map/resource-sheet.tsx
+++ b/components/map/resource-sheet.tsx
@@ -6,6 +6,8 @@ import { useAnimated } from '../../utils/animation.utils';
import { cn } from '../../utils/common.utils';
import { StyledText } from '../base/text';
+const DISPLAY_ID = false;
+
interface ResourceSheetProps extends ViewProps {
resource: MapResource | undefined;
}
@@ -34,7 +36,8 @@ export function ResourceSheet({ resource, className, ...props }: ResourceSheetPr
{...props}
>
- {savedResource?.title} ({savedResource?.id})
+ {savedResource?.title}
+ {DISPLAY_ID && ` (${savedResource?.id})`}
{savedResource?.description.hu}
diff --git a/components/schedule/layouts/home-presentation-list.tsx b/components/schedule/layouts/home-presentation-list.tsx
index 804b00f..a492834 100644
--- a/components/schedule/layouts/home-presentation-list.tsx
+++ b/components/schedule/layouts/home-presentation-list.tsx
@@ -1,4 +1,5 @@
-import { useMemo } from 'react';
+import { useFocusEffect } from 'expo-router';
+import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { PresentationDto } from '../../../types/conference-api.type';
@@ -11,12 +12,26 @@ interface HomePresentationListProps {
}
export function HomePresentationList({ presentations }: HomePresentationListProps) {
+ const [date, setDate] = useState(new Date());
const filteredPresentations = useMemo(
() => presentations.filter((event) => isPresentationUpcoming(event) || isPresentationCurrent(event)),
- [presentations]
+ [presentations, date]
);
const { t } = useTranslation();
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setDate(new Date());
+ }, 1000 * 15);
+ return () => clearInterval(interval);
+ }, []);
+
+ useFocusEffect(
+ useCallback(() => {
+ setDate(new Date());
+ }, [])
+ );
+
if (filteredPresentations.length === 0) {
return {t('home.empty')};
}
diff --git a/components/schedule/layouts/presentation-list.tsx b/components/schedule/layouts/presentation-list.tsx
index 7e241ed..22cb980 100644
--- a/components/schedule/layouts/presentation-list.tsx
+++ b/components/schedule/layouts/presentation-list.tsx
@@ -1,7 +1,10 @@
+import { useFocusEffect } from 'expo-router';
+import { useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FlatList } from 'react-native';
import { PresentationDto } from '../../../types/conference-api.type';
+import { isPresentationPast } from '../../../utils/presentation.utils';
import { StyledText } from '../../base/text';
import { PresentationItem } from '../elements/presentation-item';
@@ -10,12 +13,42 @@ interface PresentationListProps {
}
export function PresentationList({ presentations }: PresentationListProps) {
+ const [date, setDate] = useState(new Date());
+ const ref = useRef(null);
const { t } = useTranslation();
+
+ useEffect(() => {
+ if (ref.current && presentations.length > 0) {
+ const firstUpcomingIndex = presentations.findIndex((presentation) => !isPresentationPast(presentation));
+ if (firstUpcomingIndex !== -1) ref.current.scrollToIndex({ index: firstUpcomingIndex, animated: true });
+ }
+ }, [ref.current, presentations, date]);
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setDate(new Date());
+ }, 1000 * 15);
+ return () => clearInterval(interval);
+ }, []);
+
+ useFocusEffect(
+ useCallback(() => {
+ setDate(new Date());
+ }, [])
+ );
+
if (presentations.length === 0) {
return {t('presentations.empty')};
}
+
return (
{
+ setTimeout(() => {
+ ref.current?.scrollToIndex({ index: info.index, animated: true });
+ }, 100);
+ }}
contentContainerStyle={{ paddingBottom: 130 }}
data={presentations}
className='px-5 pt-5'
diff --git a/components/settings/app-details.tsx b/components/settings/app-details.tsx
new file mode 100644
index 0000000..b6a6b21
--- /dev/null
+++ b/components/settings/app-details.tsx
@@ -0,0 +1,37 @@
+import Constants from 'expo-constants';
+import * as Updates from 'expo-updates';
+import React, { useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Platform, View } from 'react-native';
+
+import { MessagingService } from '../../services/messaging.service';
+import { StyledText } from '../base/text';
+
+export function AppDetails() {
+ const [userId, setUserId] = useState(null);
+ const appVersion = useMemo(() => {
+ const update = Updates.updateId ?? '?';
+ const appVersion = Constants.expoConfig?.version ?? '?';
+ const versionCode =
+ Platform.OS === 'android' ? Constants.expoConfig?.android?.versionCode : Constants.expoConfig?.ios?.buildNumber;
+ return `${appVersion} (${versionCode ?? '?'}) - ${update}`;
+ }, []);
+
+ const appName = Constants.expoConfig?.name ?? 'App';
+
+ const { t } = useTranslation();
+
+ useEffect(() => {
+ MessagingService.getUserId().then(setUserId);
+ }, []);
+
+ return (
+
+ {appName}
+ {appVersion}
+ UID: {userId}
+ {t('settings.author')}
+ {new Date().getFullYear()}.
+
+ );
+}
diff --git a/services/i18n_data.ts b/services/i18n_data.ts
index 8cc730a..2f1db1c 100644
--- a/services/i18n_data.ts
+++ b/services/i18n_data.ts
@@ -37,6 +37,8 @@ export const resources = {
default: 'System',
language: 'Language',
notifications: 'Notifications',
+ userIdLabel: 'Anonymous user ID',
+ author: 'Made with ❤ by\nKir-Dev & Simonyi Károly College for Advanced Studies',
},
unmatched: {
main: 'You have reached an unmatched route',
@@ -93,6 +95,8 @@ export const resources = {
default: 'Rendszer alapján',
language: 'Nyelv',
notifications: 'Értesítések',
+ userIdLabel: 'Anonim felhasználói azonosító',
+ author: 'Készítette ❤-ből\na️ Kir-Dev és a Simonyi Károly Szakkollégium',
},
unmatched: {
main: 'Ismeretlen képernyőre jutottál',
diff --git a/services/messaging.service.ts b/services/messaging.service.ts
index 5f6e6a4..8122979 100644
--- a/services/messaging.service.ts
+++ b/services/messaging.service.ts
@@ -32,7 +32,7 @@ export class MessagingService {
});
}
- private static async getUserId(): Promise {
+ static async getUserId(): Promise {
if (this.userId) return this.userId;
let userIdFromStorage = await AsyncStorage.getItem('userId');
if (!userIdFromStorage) {
diff --git a/types/i18next.d.ts b/types/i18next.d.ts
new file mode 100644
index 0000000..7961781
--- /dev/null
+++ b/types/i18next.d.ts
@@ -0,0 +1,11 @@
+import { resources } from '../services/i18n_data';
+
+declare module 'i18next' {
+ interface CustomTypeOptions {
+ fallbackLng: 'hu';
+ defaultNS: 'ns1';
+ resources: {
+ ns1: typeof resources.hu.translation;
+ };
+ }
+}
diff --git a/utils/presentation.utils.ts b/utils/presentation.utils.ts
index a27c643..0bfd077 100644
--- a/utils/presentation.utils.ts
+++ b/utils/presentation.utils.ts
@@ -2,23 +2,25 @@ import { differenceInMinutes, isAfter, isBefore } from 'date-fns';
import { PresentationDto } from '../types/conference-api.type';
-const currentDate = new Date();
+function getCurrentDate() {
+ return new Date();
+}
export function isPresentationPast(presentation: PresentationDto) {
- const now = currentDate;
+ const now = getCurrentDate();
const end = new Date(presentation.endTime);
return isBefore(end, now);
}
export function isPresentationCurrent(presentation: PresentationDto) {
- const now = currentDate;
+ const now = getCurrentDate();
const start = new Date(presentation.startTime);
const end = new Date(presentation.endTime);
return isBefore(start, now) && isAfter(end, now);
}
export function isPresentationUpcoming(presentation: PresentationDto) {
- const now = currentDate;
+ const now = getCurrentDate();
const start = new Date(presentation.startTime);
return isAfter(start, now) && differenceInMinutes(start, now) < 15;
}