forked from vergnet/application-amicale
Update home screens to use TypeScript
This commit is contained in:
parent
38afbf02a3
commit
c198a40148
4 changed files with 102 additions and 128 deletions
|
@ -23,9 +23,9 @@ import {Dimensions, Image, View} from 'react-native';
|
||||||
import * as Animatable from 'react-native-animatable';
|
import * as Animatable from 'react-native-animatable';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
image: string | null;
|
image?: string | number;
|
||||||
onPress: () => void | null;
|
onPress?: () => void;
|
||||||
badgeCount: number | null;
|
badgeCount?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -50,7 +50,7 @@ function SmallDashboardItem(props: PropsType) {
|
||||||
}}>
|
}}>
|
||||||
{image ? (
|
{image ? (
|
||||||
<Image
|
<Image
|
||||||
source={{uri: image}}
|
source={typeof image === 'string' ? {uri: image} : image}
|
||||||
style={{
|
style={{
|
||||||
width: '80%',
|
width: '80%',
|
||||||
height: '80%',
|
height: '80%',
|
||||||
|
|
|
@ -17,11 +17,9 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Linking, Image} from 'react-native';
|
import {Linking, Image} from 'react-native';
|
||||||
import {Card, Text, withTheme} from 'react-native-paper';
|
import {Card, Text} from 'react-native-paper';
|
||||||
import Autolink from 'react-native-autolink';
|
import Autolink from 'react-native-autolink';
|
||||||
import {StackNavigationProp} from '@react-navigation/stack';
|
import {StackNavigationProp} from '@react-navigation/stack';
|
||||||
import MaterialHeaderButtons, {
|
import MaterialHeaderButtons, {
|
||||||
|
@ -31,12 +29,14 @@ import CustomTabBar from '../../components/Tabbar/CustomTabBar';
|
||||||
import type {FeedItemType} from './HomeScreen';
|
import type {FeedItemType} from './HomeScreen';
|
||||||
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
|
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
|
||||||
import ImageGalleryButton from '../../components/Media/ImageGalleryButton';
|
import ImageGalleryButton from '../../components/Media/ImageGalleryButton';
|
||||||
import NewsSourcesConstants from '../../constants/NewsSourcesConstants';
|
import NewsSourcesConstants, {
|
||||||
|
AvailablePages,
|
||||||
|
} from '../../constants/NewsSourcesConstants';
|
||||||
import type {NewsSourceType} from '../../constants/NewsSourcesConstants';
|
import type {NewsSourceType} from '../../constants/NewsSourcesConstants';
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
navigation: StackNavigationProp,
|
navigation: StackNavigationProp<any>;
|
||||||
route: {params: {data: FeedItemType, date: string}},
|
route: {params: {data: FeedItemType; date: string}};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,7 +72,7 @@ class FeedItemScreen extends React.Component<PropsType> {
|
||||||
*
|
*
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
getHeaderButton = (): React.Node => {
|
getHeaderButton = () => {
|
||||||
return (
|
return (
|
||||||
<MaterialHeaderButtons>
|
<MaterialHeaderButtons>
|
||||||
<Item
|
<Item
|
||||||
|
@ -85,20 +85,16 @@ class FeedItemScreen extends React.Component<PropsType> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {navigation} = this.props;
|
|
||||||
const hasImage =
|
|
||||||
this.displayData.image !== '' && this.displayData.image != null;
|
|
||||||
const pageSource: NewsSourceType =
|
const pageSource: NewsSourceType =
|
||||||
NewsSourcesConstants[this.displayData.page_id];
|
NewsSourcesConstants[this.displayData.page_id as AvailablePages];
|
||||||
return (
|
return (
|
||||||
<CollapsibleScrollView style={{margin: 5}} hasTab>
|
<CollapsibleScrollView style={{margin: 5}} hasTab>
|
||||||
<Card.Title
|
<Card.Title
|
||||||
title={pageSource.name}
|
title={pageSource.name}
|
||||||
subtitle={this.date}
|
subtitle={this.date}
|
||||||
left={(): React.Node => (
|
left={() => (
|
||||||
<Image
|
<Image
|
||||||
size={48}
|
|
||||||
source={pageSource.icon}
|
source={pageSource.icon}
|
||||||
style={{
|
style={{
|
||||||
width: 48,
|
width: 48,
|
||||||
|
@ -107,9 +103,8 @@ class FeedItemScreen extends React.Component<PropsType> {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{hasImage ? (
|
{this.displayData.image ? (
|
||||||
<ImageGalleryButton
|
<ImageGalleryButton
|
||||||
navigation={navigation}
|
|
||||||
images={[{url: this.displayData.image}]}
|
images={[{url: this.displayData.image}]}
|
||||||
style={{
|
style={{
|
||||||
width: 250,
|
width: 250,
|
||||||
|
@ -124,6 +119,7 @@ class FeedItemScreen extends React.Component<PropsType> {
|
||||||
<Autolink
|
<Autolink
|
||||||
text={this.displayData.message}
|
text={this.displayData.message}
|
||||||
hashtag="facebook"
|
hashtag="facebook"
|
||||||
|
// @ts-ignore
|
||||||
component={Text}
|
component={Text}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -133,4 +129,4 @@ class FeedItemScreen extends React.Component<PropsType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withTheme(FeedItemScreen);
|
export default FeedItemScreen;
|
|
@ -17,10 +17,8 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {FlatList} from 'react-native';
|
import {FlatList, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
import {ActivityIndicator, Headline, withTheme} from 'react-native-paper';
|
import {ActivityIndicator, Headline, withTheme} from 'react-native-paper';
|
||||||
import {CommonActions} from '@react-navigation/native';
|
import {CommonActions} from '@react-navigation/native';
|
||||||
|
@ -38,7 +36,6 @@ import MaterialHeaderButtons, {
|
||||||
Item,
|
Item,
|
||||||
} from '../../components/Overrides/CustomHeaderButton';
|
} from '../../components/Overrides/CustomHeaderButton';
|
||||||
import AnimatedFAB from '../../components/Animations/AnimatedFAB';
|
import AnimatedFAB from '../../components/Animations/AnimatedFAB';
|
||||||
import type {CustomThemeType} from '../../managers/ThemeManager';
|
|
||||||
import ConnectionManager from '../../managers/ConnectionManager';
|
import ConnectionManager from '../../managers/ConnectionManager';
|
||||||
import LogoutDialog from '../../components/Amicale/LogoutDialog';
|
import LogoutDialog from '../../components/Amicale/LogoutDialog';
|
||||||
import AsyncStorageManager from '../../managers/AsyncStorageManager';
|
import AsyncStorageManager from '../../managers/AsyncStorageManager';
|
||||||
|
@ -59,40 +56,40 @@ const SECTIONS_ID = ['dashboard', 'news_feed'];
|
||||||
const REFRESH_TIME = 1000 * 20; // Refresh every 20 seconds
|
const REFRESH_TIME = 1000 * 20; // Refresh every 20 seconds
|
||||||
|
|
||||||
export type FeedItemType = {
|
export type FeedItemType = {
|
||||||
id: string,
|
id: string;
|
||||||
message: string,
|
message: string;
|
||||||
url: string,
|
url: string;
|
||||||
image: string | null,
|
image: string | null;
|
||||||
video: string | null,
|
video: string | null;
|
||||||
link: string | null,
|
link: string | null;
|
||||||
time: number,
|
time: number;
|
||||||
page_id: string,
|
page_id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FullDashboardType = {
|
export type FullDashboardType = {
|
||||||
today_menu: Array<{[key: string]: {...}}>,
|
today_menu: Array<{[key: string]: object}>;
|
||||||
proximo_articles: number,
|
proximo_articles: number;
|
||||||
available_dryers: number,
|
available_dryers: number;
|
||||||
available_washers: number,
|
available_washers: number;
|
||||||
today_events: Array<PlanningEventType>,
|
today_events: Array<PlanningEventType>;
|
||||||
available_tutorials: number,
|
available_tutorials: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type RawNewsFeedType = {[key: string]: Array<FeedItemType>};
|
type RawNewsFeedType = {[key: string]: Array<FeedItemType>};
|
||||||
|
|
||||||
type RawDashboardType = {
|
type RawDashboardType = {
|
||||||
news_feed: RawNewsFeedType,
|
news_feed: RawNewsFeedType;
|
||||||
dashboard: FullDashboardType,
|
dashboard: FullDashboardType;
|
||||||
};
|
};
|
||||||
|
|
||||||
type PropsType = {
|
type PropsType = {
|
||||||
navigation: StackNavigationProp,
|
navigation: StackNavigationProp<any>;
|
||||||
route: {params: {nextScreen: string, data: {...}}},
|
route: {params: {nextScreen: string; data: object}};
|
||||||
theme: CustomThemeType,
|
theme: ReactNativePaper.Theme;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
dialogVisible: boolean,
|
dialogVisible: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,10 +100,12 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
b.time - a.time;
|
b.time - a.time;
|
||||||
|
|
||||||
static generateNewsFeed(rawFeed: RawNewsFeedType): Array<FeedItemType> {
|
static generateNewsFeed(rawFeed: RawNewsFeedType): Array<FeedItemType> {
|
||||||
const finalFeed = [];
|
const finalFeed: Array<FeedItemType> = [];
|
||||||
Object.keys(rawFeed).forEach((key: string) => {
|
Object.keys(rawFeed).forEach((key: string) => {
|
||||||
const category: Array<FeedItemType> | null = rawFeed[key];
|
const category: Array<FeedItemType> | null = rawFeed[key];
|
||||||
if (category != null && category.length > 0) finalFeed.push(...category);
|
if (category != null && category.length > 0) {
|
||||||
|
finalFeed.push(...category);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
finalFeed.sort(HomeScreen.sortFeedTime);
|
finalFeed.sort(HomeScreen.sortFeedTime);
|
||||||
return finalFeed;
|
return finalFeed;
|
||||||
|
@ -164,7 +163,7 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
*
|
*
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
getHeaderButton = (): React.Node => {
|
getHeaderButton = () => {
|
||||||
const {props} = this;
|
const {props} = this;
|
||||||
let onPressLog = (): void =>
|
let onPressLog = (): void =>
|
||||||
props.navigation.navigate('login', {nextScreen: 'profile'});
|
props.navigation.navigate('login', {nextScreen: 'profile'});
|
||||||
|
@ -201,7 +200,7 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
* @param content
|
* @param content
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
getDashboardEvent(content: Array<PlanningEventType>): React.Node {
|
getDashboardEvent(content: Array<PlanningEventType>) {
|
||||||
const futureEvents = getFutureEvents(content);
|
const futureEvents = getFutureEvents(content);
|
||||||
const displayEvent = getDisplayEvent(futureEvents);
|
const displayEvent = getDisplayEvent(futureEvents);
|
||||||
// const clickPreviewAction = () =>
|
// const clickPreviewAction = () =>
|
||||||
|
@ -221,30 +220,14 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a dashboard item with action buttons
|
|
||||||
*
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
getDashboardActions(): React.Node {
|
|
||||||
const {props} = this;
|
|
||||||
return (
|
|
||||||
<ActionsDashBoardItem
|
|
||||||
navigation={props.navigation}
|
|
||||||
isLoggedIn={this.isLoggedIn}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a dashboard item with a row of shortcut buttons.
|
* Gets a dashboard item with a row of shortcut buttons.
|
||||||
*
|
*
|
||||||
* @param content
|
* @param content
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
getDashboardRow(content: Array<ServiceItemType | null>): React.Node {
|
getDashboardRow(content: Array<ServiceItemType | null>) {
|
||||||
return (
|
return (
|
||||||
// $FlowFixMe
|
|
||||||
<FlatList
|
<FlatList
|
||||||
data={content}
|
data={content}
|
||||||
renderItem={this.getDashboardRowRenderItem}
|
renderItem={this.getDashboardRowRenderItem}
|
||||||
|
@ -265,12 +248,8 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
* @param item
|
* @param item
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
getDashboardRowRenderItem = ({
|
getDashboardRowRenderItem = ({item}: {item: ServiceItemType | null}) => {
|
||||||
item,
|
if (item != null) {
|
||||||
}: {
|
|
||||||
item: ServiceItemType | null,
|
|
||||||
}): React.Node => {
|
|
||||||
if (item != null)
|
|
||||||
return (
|
return (
|
||||||
<SmallDashboardItem
|
<SmallDashboardItem
|
||||||
image={item.image}
|
image={item.image}
|
||||||
|
@ -278,11 +257,12 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
badgeCount={
|
badgeCount={
|
||||||
this.currentDashboard != null && item.badgeFunction != null
|
this.currentDashboard != null && item.badgeFunction != null
|
||||||
? item.badgeFunction(this.currentDashboard)
|
? item.badgeFunction(this.currentDashboard)
|
||||||
: null
|
: undefined
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
return <SmallDashboardItem image={null} onPress={null} badgeCount={null} />;
|
}
|
||||||
|
return <SmallDashboardItem />;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -291,15 +271,8 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
* @param item The feed item to display
|
* @param item The feed item to display
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
getFeedItem(item: FeedItemType): React.Node {
|
getFeedItem(item: FeedItemType) {
|
||||||
const {props} = this;
|
return <FeedItem item={item} height={FEED_ITEM_HEIGHT} />;
|
||||||
return (
|
|
||||||
<FeedItem
|
|
||||||
navigation={props.navigation}
|
|
||||||
item={item}
|
|
||||||
height={FEED_ITEM_HEIGHT}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -309,20 +282,19 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
* @param section The current section
|
* @param section The current section
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
getRenderItem = ({item}: {item: FeedItemType}): React.Node =>
|
getRenderItem = ({item}: {item: FeedItemType}) => this.getFeedItem(item);
|
||||||
this.getFeedItem(item);
|
|
||||||
|
|
||||||
getRenderSectionHeader = (
|
getRenderSectionHeader = (
|
||||||
data: {
|
data: {
|
||||||
section: {
|
section: {
|
||||||
data: Array<{...}>,
|
data: Array<object>;
|
||||||
title: string,
|
title: string;
|
||||||
},
|
};
|
||||||
},
|
},
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
): React.Node => {
|
) => {
|
||||||
const {props} = this;
|
const {props} = this;
|
||||||
if (data.section.data.length > 0)
|
if (data.section.data.length > 0) {
|
||||||
return (
|
return (
|
||||||
<Headline
|
<Headline
|
||||||
style={{
|
style={{
|
||||||
|
@ -333,6 +305,7 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
{data.section.title}
|
{data.section.title}
|
||||||
</Headline>
|
</Headline>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<View>
|
<View>
|
||||||
<Headline
|
<Headline
|
||||||
|
@ -367,12 +340,14 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
getListHeader = (fetchedData: RawDashboardType): React.Node => {
|
getListHeader = (fetchedData: RawDashboardType) => {
|
||||||
let dashboard = null;
|
let dashboard = null;
|
||||||
if (fetchedData != null) dashboard = fetchedData.dashboard;
|
if (fetchedData != null) {
|
||||||
|
dashboard = fetchedData.dashboard;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Animatable.View animation="fadeInDown" duration={500} useNativeDriver>
|
<Animatable.View animation="fadeInDown" duration={500} useNativeDriver>
|
||||||
{this.getDashboardActions()}
|
<ActionsDashBoardItem />
|
||||||
{this.getDashboardRow(this.dashboardManager.getCurrentDashboard())}
|
{this.getDashboardRow(this.dashboardManager.getCurrentDashboard())}
|
||||||
{this.getDashboardEvent(
|
{this.getDashboardEvent(
|
||||||
dashboard == null ? [] : dashboard.today_events,
|
dashboard == null ? [] : dashboard.today_events,
|
||||||
|
@ -418,20 +393,22 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
fetchedData: RawDashboardType | null,
|
fetchedData: RawDashboardType | null,
|
||||||
isLoading: boolean,
|
isLoading: boolean,
|
||||||
): Array<{
|
): Array<{
|
||||||
title: string,
|
title: string;
|
||||||
data: [] | Array<FeedItemType>,
|
data: [] | Array<FeedItemType>;
|
||||||
id: string,
|
id: string;
|
||||||
}> => {
|
}> => {
|
||||||
// fetchedData = DATA;
|
// fetchedData = DATA;
|
||||||
if (fetchedData != null) {
|
if (fetchedData != null) {
|
||||||
if (fetchedData.news_feed != null)
|
if (fetchedData.news_feed != null) {
|
||||||
this.currentNewFeed = HomeScreen.generateNewsFeed(
|
this.currentNewFeed = HomeScreen.generateNewsFeed(
|
||||||
fetchedData.news_feed,
|
fetchedData.news_feed,
|
||||||
);
|
);
|
||||||
if (fetchedData.dashboard != null)
|
}
|
||||||
|
if (fetchedData.dashboard != null) {
|
||||||
this.currentDashboard = fetchedData.dashboard;
|
this.currentDashboard = fetchedData.dashboard;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.currentNewFeed.length > 0)
|
if (this.currentNewFeed.length > 0) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: i18n.t('screens.home.feedTitle'),
|
title: i18n.t('screens.home.feedTitle'),
|
||||||
|
@ -439,6 +416,7 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
id: SECTIONS_ID[1],
|
id: SECTIONS_ID[1],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
title: isLoading
|
title: isLoading
|
||||||
|
@ -455,8 +433,10 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
props.navigation.navigate('planning');
|
props.navigation.navigate('planning');
|
||||||
};
|
};
|
||||||
|
|
||||||
onScroll = (event: SyntheticEvent<EventTarget>) => {
|
onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||||
if (this.fabRef.current != null) this.fabRef.current.onScroll(event);
|
if (this.fabRef.current) {
|
||||||
|
this.fabRef.current.onScroll(event);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,7 +450,7 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {props, state} = this;
|
const {props, state} = this;
|
||||||
return (
|
return (
|
||||||
<View style={{flex: 1}}>
|
<View style={{flex: 1}}>
|
||||||
|
@ -521,7 +501,6 @@ class HomeScreen extends React.Component<PropsType, StateType> {
|
||||||
onPress={this.openScanner}
|
onPress={this.openScanner}
|
||||||
/>
|
/>
|
||||||
<LogoutDialog
|
<LogoutDialog
|
||||||
navigation={props.navigation}
|
|
||||||
visible={state.dialogVisible}
|
visible={state.dialogVisible}
|
||||||
onDismiss={this.hideDisconnectDialog}
|
onDismiss={this.hideDisconnectDialog}
|
||||||
/>
|
/>
|
|
@ -17,11 +17,9 @@
|
||||||
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// @flow
|
|
||||||
|
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {Linking, Platform, StyleSheet, View} from 'react-native';
|
import {Linking, Platform, StyleSheet, View} from 'react-native';
|
||||||
import {Button, Text, withTheme} from 'react-native-paper';
|
import {Button, Text} from 'react-native-paper';
|
||||||
import {RNCamera} from 'react-native-camera';
|
import {RNCamera} from 'react-native-camera';
|
||||||
import {BarcodeMask} from '@nartc/react-native-barcode-mask';
|
import {BarcodeMask} from '@nartc/react-native-barcode-mask';
|
||||||
import i18n from 'i18n-js';
|
import i18n from 'i18n-js';
|
||||||
|
@ -34,11 +32,11 @@ import {MASCOT_STYLE} from '../../components/Mascot/Mascot';
|
||||||
import MascotPopup from '../../components/Mascot/MascotPopup';
|
import MascotPopup from '../../components/Mascot/MascotPopup';
|
||||||
|
|
||||||
type StateType = {
|
type StateType = {
|
||||||
hasPermission: boolean,
|
hasPermission: boolean;
|
||||||
scanned: boolean,
|
scanned: boolean;
|
||||||
dialogVisible: boolean,
|
dialogVisible: boolean;
|
||||||
mascotDialogVisible: boolean,
|
mascotDialogVisible: boolean;
|
||||||
loading: boolean,
|
loading: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
@ -54,9 +52,11 @@ const styles = StyleSheet.create({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
class ScannerScreen extends React.Component<null, StateType> {
|
type PermissionResults = 'unavailable' | 'denied' | 'blocked' | 'granted';
|
||||||
|
|
||||||
|
class ScannerScreen extends React.Component<{}, StateType> {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super({});
|
||||||
this.state = {
|
this.state = {
|
||||||
hasPermission: false,
|
hasPermission: false,
|
||||||
scanned: false,
|
scanned: false,
|
||||||
|
@ -75,7 +75,7 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
*
|
*
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
getPermissionScreen(): React.Node {
|
getPermissionScreen() {
|
||||||
return (
|
return (
|
||||||
<View style={{marginLeft: 10, marginRight: 10}}>
|
<View style={{marginLeft: 10, marginRight: 10}}>
|
||||||
<Text>{i18n.t('screens.scanner.permissions.error')}</Text>
|
<Text>{i18n.t('screens.scanner.permissions.error')}</Text>
|
||||||
|
@ -101,15 +101,13 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
*
|
*
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
getScanner(): React.Node {
|
getScanner() {
|
||||||
const {state} = this;
|
const {state} = this;
|
||||||
return (
|
return (
|
||||||
<RNCamera
|
<RNCamera
|
||||||
onBarCodeRead={state.scanned ? null : this.onCodeScanned}
|
onBarCodeRead={state.scanned ? undefined : this.onCodeScanned}
|
||||||
type={RNCamera.Constants.Type.back}
|
type={RNCamera.Constants.Type.back}
|
||||||
barCodeScannerSettings={{
|
barCodeTypes={['qr']}
|
||||||
barCodeTypes: [RNCamera.Constants.BarCodeType.qr],
|
|
||||||
}}
|
|
||||||
style={StyleSheet.absoluteFill}
|
style={StyleSheet.absoluteFill}
|
||||||
captureAudio={false}>
|
captureAudio={false}>
|
||||||
<BarcodeMask
|
<BarcodeMask
|
||||||
|
@ -128,9 +126,11 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
* Requests permission to use the camera
|
* Requests permission to use the camera
|
||||||
*/
|
*/
|
||||||
requestPermissions = () => {
|
requestPermissions = () => {
|
||||||
if (Platform.OS === 'android')
|
if (Platform.OS === 'android') {
|
||||||
request(PERMISSIONS.ANDROID.CAMERA).then(this.updatePermissionStatus);
|
request(PERMISSIONS.ANDROID.CAMERA).then(this.updatePermissionStatus);
|
||||||
else request(PERMISSIONS.IOS.CAMERA).then(this.updatePermissionStatus);
|
} else {
|
||||||
|
request(PERMISSIONS.IOS.CAMERA).then(this.updatePermissionStatus);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,7 +138,7 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
*
|
*
|
||||||
* @param result
|
* @param result
|
||||||
*/
|
*/
|
||||||
updatePermissionStatus = (result: RESULTS) => {
|
updatePermissionStatus = (result: PermissionResults) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
hasPermission: result === RESULTS.GRANTED,
|
hasPermission: result === RESULTS.GRANTED,
|
||||||
});
|
});
|
||||||
|
@ -147,7 +147,6 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
/**
|
/**
|
||||||
* Shows a dialog indicating the user the scanned code was invalid
|
* Shows a dialog indicating the user the scanned code was invalid
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line react/sort-comp
|
|
||||||
showErrorDialog() {
|
showErrorDialog() {
|
||||||
this.setState({
|
this.setState({
|
||||||
dialogVisible: true,
|
dialogVisible: true,
|
||||||
|
@ -199,14 +198,15 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
* @param data The scanned value
|
* @param data The scanned value
|
||||||
*/
|
*/
|
||||||
onCodeScanned = ({data}: {data: string}) => {
|
onCodeScanned = ({data}: {data: string}) => {
|
||||||
if (!URLHandler.isUrlValid(data)) this.showErrorDialog();
|
if (!URLHandler.isUrlValid(data)) {
|
||||||
else {
|
this.showErrorDialog();
|
||||||
|
} else {
|
||||||
this.showOpeningDialog();
|
this.showOpeningDialog();
|
||||||
Linking.openURL(data);
|
Linking.openURL(data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render(): React.Node {
|
render() {
|
||||||
const {state} = this;
|
const {state} = this;
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
@ -228,7 +228,6 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
message={i18n.t('screens.scanner.mascotDialog.message')}
|
message={i18n.t('screens.scanner.mascotDialog.message')}
|
||||||
icon="camera-iris"
|
icon="camera-iris"
|
||||||
buttons={{
|
buttons={{
|
||||||
action: null,
|
|
||||||
cancel: {
|
cancel: {
|
||||||
message: i18n.t('screens.scanner.mascotDialog.button'),
|
message: i18n.t('screens.scanner.mascotDialog.button'),
|
||||||
icon: 'check',
|
icon: 'check',
|
||||||
|
@ -253,4 +252,4 @@ class ScannerScreen extends React.Component<null, StateType> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withTheme(ScannerScreen);
|
export default ScannerScreen;
|
Loading…
Reference in a new issue