diff --git a/src/components/Overrides/CustomHeaderButton.tsx b/src/components/Overrides/CustomHeaderButton.tsx
index ded22b4..c6c4efc 100644
--- a/src/components/Overrides/CustomHeaderButton.tsx
+++ b/src/components/Overrides/CustomHeaderButton.tsx
@@ -39,7 +39,9 @@ const MaterialHeaderButton = (props: HeaderButtonProps) => {
);
};
-const MaterialHeaderButtons = (props: HeaderButtonsProps) => {
+const MaterialHeaderButtons = (
+ props: HeaderButtonsProps & {children?: React.ReactNode},
+) => {
return (
);
diff --git a/src/components/Screens/WebSectionList.js b/src/components/Screens/WebSectionList.tsx
similarity index 73%
rename from src/components/Screens/WebSectionList.js
rename to src/components/Screens/WebSectionList.tsx
index efb18dc..cee31c3 100644
--- a/src/components/Screens/WebSectionList.js
+++ b/src/components/Screens/WebSectionList.tsx
@@ -17,12 +17,15 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import * as React from 'react';
import i18n from 'i18n-js';
import {Snackbar} from 'react-native-paper';
-import {RefreshControl, View} from 'react-native';
+import {
+ NativeSyntheticEvent,
+ RefreshControl,
+ SectionListData,
+ View,
+} from 'react-native';
import * as Animatable from 'react-native-animatable';
import {Collapsible} from 'react-navigation-collapsible';
import {StackNavigationProp} from '@react-navigation/stack';
@@ -32,42 +35,43 @@ import withCollapsible from '../../utils/withCollapsible';
import CustomTabBar from '../Tabbar/CustomTabBar';
import {ERROR_TYPE, readData} from '../../utils/WebData';
import CollapsibleSectionList from '../Collapsible/CollapsibleSectionList';
-import type {ApiGenericDataType} from '../../utils/WebData';
-export type SectionListDataType = Array<{
- title: string,
- data: Array,
- keyExtractor?: (T) => string,
+export type SectionListDataType = Array<{
+ title: string;
+ data: Array;
+ keyExtractor?: (data: ItemT) => string;
}>;
-type PropsType = {
- navigation: StackNavigationProp,
- fetchUrl: string,
- autoRefreshTime: number,
- refreshOnFocus: boolean,
- renderItem: (data: {item: T}) => React.Node,
+type PropsType = {
+ navigation: StackNavigationProp;
+ fetchUrl: string;
+ autoRefreshTime: number;
+ refreshOnFocus: boolean;
+ renderItem: (data: {item: ItemT}) => React.ReactNode;
createDataset: (
- data: ApiGenericDataType | null,
+ data: RawData | null,
isLoading?: boolean,
- ) => SectionListDataType,
- onScroll: (event: SyntheticEvent) => void,
- collapsibleStack: Collapsible,
+ ) => SectionListDataType;
+ onScroll: (event: NativeSyntheticEvent) => void;
+ collapsibleStack: Collapsible;
- showError?: boolean,
- itemHeight?: number | null,
- updateData?: number,
- renderListHeaderComponent?: (data: ApiGenericDataType | null) => React.Node,
+ showError?: boolean;
+ itemHeight?: number | null;
+ updateData?: number;
+ renderListHeaderComponent?: (
+ data: RawData | null,
+ ) => React.ComponentType | React.ReactElement | null;
renderSectionHeader?: (
- data: {section: {title: string}},
+ data: {section: SectionListData},
isLoading?: boolean,
- ) => React.Node,
- stickyHeader?: boolean,
+ ) => React.ReactElement | null;
+ stickyHeader?: boolean;
};
-type StateType = {
- refreshing: boolean,
- fetchedData: ApiGenericDataType | null,
- snackbarVisible: boolean,
+type StateType = {
+ refreshing: boolean;
+ fetchedData: RawData | null;
+ snackbarVisible: boolean;
};
const MIN_REFRESH_TIME = 5 * 1000;
@@ -78,22 +82,25 @@ const MIN_REFRESH_TIME = 5 * 1000;
* This is a pure component, meaning it will only update if a shallow comparison of state and props is different.
* To force the component to update, change the value of updateData.
*/
-class WebSectionList extends React.PureComponent, StateType> {
+class WebSectionList extends React.PureComponent<
+ PropsType,
+ StateType
+> {
static defaultProps = {
showError: true,
itemHeight: null,
updateData: 0,
- renderListHeaderComponent: (): React.Node => null,
- renderSectionHeader: (): React.Node => null,
+ renderListHeaderComponent: () => null,
+ renderSectionHeader: () => null,
stickyHeader: false,
};
- refreshInterval: IntervalID;
+ refreshInterval: NodeJS.Timeout | undefined;
- lastRefresh: Date | null;
+ lastRefresh: Date | undefined;
- constructor() {
- super();
+ constructor(props: PropsType) {
+ super(props);
this.state = {
refreshing: false,
fetchedData: null,
@@ -109,7 +116,7 @@ class WebSectionList extends React.PureComponent, StateType> {
const {navigation} = this.props;
navigation.addListener('focus', this.onScreenFocus);
navigation.addListener('blur', this.onScreenBlur);
- this.lastRefresh = null;
+ this.lastRefresh = undefined;
this.onRefresh();
}
@@ -121,15 +128,18 @@ class WebSectionList extends React.PureComponent, StateType> {
if (props.refreshOnFocus && this.lastRefresh) {
setTimeout(this.onRefresh, 200);
}
- if (props.autoRefreshTime > 0)
+ if (props.autoRefreshTime > 0) {
this.refreshInterval = setInterval(this.onRefresh, props.autoRefreshTime);
+ }
};
/**
* Removes any interval on un-focus
*/
onScreenBlur = () => {
- clearInterval(this.refreshInterval);
+ if (this.refreshInterval) {
+ clearInterval(this.refreshInterval);
+ }
};
/**
@@ -138,7 +148,7 @@ class WebSectionList extends React.PureComponent, StateType> {
*
* @param fetchedData The newly fetched data
*/
- onFetchSuccess = (fetchedData: ApiGenericDataType) => {
+ onFetchSuccess = (fetchedData: RawData) => {
this.setState({
fetchedData,
refreshing: false,
@@ -167,7 +177,9 @@ class WebSectionList extends React.PureComponent, StateType> {
if (this.lastRefresh != null) {
const last = this.lastRefresh;
canRefresh = new Date().getTime() - last.getTime() > MIN_REFRESH_TIME;
- } else canRefresh = true;
+ } else {
+ canRefresh = true;
+ }
if (canRefresh) {
this.setState({refreshing: true});
readData(fetchUrl).then(this.onFetchSuccess).catch(this.onFetchError);
@@ -189,19 +201,18 @@ class WebSectionList extends React.PureComponent, StateType> {
};
getItemLayout = (
- data: T,
+ height: number,
+ data: Array> | null,
index: number,
- ): {length: number, offset: number, index: number} | null => {
- const {itemHeight} = this.props;
- if (itemHeight == null) return null;
+ ): {length: number; offset: number; index: number} => {
return {
- length: itemHeight,
- offset: itemHeight * index,
+ length: height,
+ offset: height * index,
index,
};
};
- getRenderSectionHeader = (data: {section: {title: string}}): React.Node => {
+ getRenderSectionHeader = (data: {section: SectionListData}) => {
const {renderSectionHeader} = this.props;
const {refreshing} = this.state;
if (renderSectionHeader != null) {
@@ -214,7 +225,7 @@ class WebSectionList extends React.PureComponent, StateType> {
return null;
};
- getRenderItem = (data: {item: T}): React.Node => {
+ getRenderItem = (data: {item: ItemT}) => {
const {renderItem} = this.props;
return (
@@ -223,19 +234,23 @@ class WebSectionList extends React.PureComponent, StateType> {
);
};
- onScroll = (event: SyntheticEvent) => {
+ onScroll = (event: NativeSyntheticEvent) => {
const {onScroll} = this.props;
- if (onScroll != null) onScroll(event);
+ if (onScroll != null) {
+ onScroll(event);
+ }
};
- render(): React.Node {
+ render() {
const {props, state} = this;
- let dataset = [];
+ const {itemHeight} = props;
+ let dataset: SectionListDataType = [];
if (
state.fetchedData != null ||
(state.fetchedData == null && !props.showError)
- )
+ ) {
dataset = props.createDataset(state.fetchedData, state.refreshing);
+ }
const {containerPaddingTop} = props.collapsibleStack;
return (
@@ -270,7 +285,11 @@ class WebSectionList extends React.PureComponent, StateType> {
/>
)
}
- getItemLayout={props.itemHeight != null ? this.getItemLayout : null}
+ getItemLayout={
+ itemHeight
+ ? (data, index) => this.getItemLayout(itemHeight, data, index)
+ : undefined
+ }
onScroll={this.onScroll}
hasTab
/>
diff --git a/src/components/Screens/WebViewScreen.js b/src/components/Screens/WebViewScreen.tsx
similarity index 84%
rename from src/components/Screens/WebViewScreen.js
rename to src/components/Screens/WebViewScreen.tsx
index 941b223..7a2feed 100644
--- a/src/components/Screens/WebViewScreen.js
+++ b/src/components/Screens/WebViewScreen.tsx
@@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see .
*/
-// @flow
-
import * as React from 'react';
import WebView from 'react-native-webview';
import {
@@ -27,12 +25,17 @@ import {
OverflowMenu,
} from 'react-navigation-header-buttons';
import i18n from 'i18n-js';
-import {Animated, BackHandler, Linking} from 'react-native';
+import {
+ Animated,
+ BackHandler,
+ Linking,
+ NativeScrollEvent,
+ NativeSyntheticEvent,
+} from 'react-native';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import {withTheme} from 'react-native-paper';
import {StackNavigationProp} from '@react-navigation/stack';
import {Collapsible} from 'react-navigation-collapsible';
-import type {CustomThemeType} from '../../managers/ThemeManager';
import withCollapsible from '../../utils/withCollapsible';
import MaterialHeaderButtons, {Item} from '../Overrides/CustomHeaderButton';
import {ERROR_TYPE} from '../../utils/WebData';
@@ -40,15 +43,15 @@ import ErrorView from './ErrorView';
import BasicLoadingScreen from './BasicLoadingScreen';
type PropsType = {
- navigation: StackNavigationProp,
- theme: CustomThemeType,
- url: string,
- collapsibleStack: Collapsible,
- onMessage: (event: {nativeEvent: {data: string}}) => void,
- onScroll: (event: SyntheticEvent) => void,
- customJS?: string,
- customPaddingFunction?: null | ((padding: number) => string),
- showAdvancedControls?: boolean,
+ navigation: StackNavigationProp;
+ theme: ReactNativePaper.Theme;
+ url: string;
+ collapsibleStack: Collapsible;
+ onMessage: (event: {nativeEvent: {data: string}}) => void;
+ onScroll: (event: NativeSyntheticEvent) => void;
+ customJS?: string;
+ customPaddingFunction?: null | ((padding: number) => string);
+ showAdvancedControls?: boolean;
};
const AnimatedWebView = Animated.createAnimatedComponent(WebView);
@@ -67,8 +70,8 @@ class WebViewScreen extends React.PureComponent {
canGoBack: boolean;
- constructor() {
- super();
+ constructor(props: PropsType) {
+ super(props);
this.webviewRef = React.createRef();
this.canGoBack = false;
}
@@ -115,7 +118,7 @@ class WebViewScreen extends React.PureComponent {
*
* @return {*}
*/
- getBasicButton = (): React.Node => {
+ getBasicButton = () => {
return (
- {
*
* @returns {*}
*/
- getAdvancedButtons = (): React.Node => {
+ getAdvancedButtons = () => {
const {props} = this;
return (
@@ -179,7 +182,7 @@ class WebViewScreen extends React.PureComponent {
*
* @return {*}
*/
- getRenderLoading = (): React.Node => ;
+ getRenderLoading = () => ;
/**
* Gets the javascript needed to generate a padding on top of the page
@@ -201,15 +204,21 @@ class WebViewScreen extends React.PureComponent {
* Callback to use when refresh button is clicked. Reloads the webview.
*/
onRefreshClicked = () => {
- if (this.webviewRef.current != null) this.webviewRef.current.reload();
+ if (this.webviewRef.current != null) {
+ this.webviewRef.current.reload();
+ }
};
onGoBackClicked = () => {
- if (this.webviewRef.current != null) this.webviewRef.current.goBack();
+ if (this.webviewRef.current != null) {
+ this.webviewRef.current.goBack();
+ }
};
onGoForwardClicked = () => {
- if (this.webviewRef.current != null) this.webviewRef.current.goForward();
+ if (this.webviewRef.current != null) {
+ this.webviewRef.current.goForward();
+ }
};
onOpenClicked = () => {
@@ -217,9 +226,11 @@ class WebViewScreen extends React.PureComponent {
Linking.openURL(url);
};
- onScroll = (event: SyntheticEvent) => {
+ onScroll = (event: NativeSyntheticEvent) => {
const {onScroll} = this.props;
- if (onScroll) onScroll(event);
+ if (onScroll) {
+ onScroll(event);
+ }
};
/**
@@ -228,11 +239,12 @@ class WebViewScreen extends React.PureComponent {
* @param script The script to inject
*/
injectJavaScript = (script: string) => {
- if (this.webviewRef.current != null)
+ if (this.webviewRef.current != null) {
this.webviewRef.current.injectJavaScript(script);
+ }
};
- render(): React.Node {
+ render() {
const {props} = this;
const {containerPaddingTop, onScrollWithListener} = props.collapsibleStack;
return (
@@ -243,7 +255,7 @@ class WebViewScreen extends React.PureComponent {
injectedJavaScript={props.customJS}
javaScriptEnabled
renderLoading={this.getRenderLoading}
- renderError={(): React.Node => (
+ renderError={() => (
{
this.injectJavaScript(this.getJavascriptPadding(containerPaddingTop));
}}
// Animations
- onScroll={onScrollWithListener(this.onScroll)}
+ onScroll={(event) => onScrollWithListener(this.onScroll)(event)}
/>
);
}