forked from vergnet/application-amicale
Improved doc
This commit is contained in:
parent
56ab0e562f
commit
401c7d85ef
8 changed files with 228 additions and 42 deletions
|
@ -4,6 +4,9 @@ import * as React from 'react';
|
||||||
|
|
||||||
const speedOffset = 5;
|
const speedOffset = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class used to detect when to show or hide a component based on scrolling
|
||||||
|
*/
|
||||||
export default class AutoHideHandler {
|
export default class AutoHideHandler {
|
||||||
|
|
||||||
lastOffset: number;
|
lastOffset: number;
|
||||||
|
@ -16,16 +19,42 @@ export default class AutoHideHandler {
|
||||||
this.isHidden = startHidden;
|
this.isHidden = startHidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a listener to the hide event
|
||||||
|
*
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
addListener(listener: Function) {
|
addListener(listener: Function) {
|
||||||
this.listeners.push(listener);
|
this.listeners.push(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies every listener whether they should hide or show.
|
||||||
|
*
|
||||||
|
* @param shouldHide
|
||||||
|
*/
|
||||||
notifyListeners(shouldHide: boolean) {
|
notifyListeners(shouldHide: boolean) {
|
||||||
for (let i = 0; i < this.listeners.length; i++) {
|
for (let i = 0; i < this.listeners.length; i++) {
|
||||||
this.listeners[i](shouldHide);
|
this.listeners[i](shouldHide);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to be used on the onScroll animated component event.
|
||||||
|
*
|
||||||
|
* Detects if the current speed exceeds a threshold and notifies listeners to hide or show.
|
||||||
|
*
|
||||||
|
* The hide even is triggered when the user scrolls down, and the show event on scroll up.
|
||||||
|
* This does not take into account the speed when the y coordinate is negative, to prevent hiding on over scroll.
|
||||||
|
* (When scrolling up and hitting the top on ios for example)
|
||||||
|
*
|
||||||
|
* //TODO Known issue:
|
||||||
|
* When refreshing a list with the pull down gesture on ios,
|
||||||
|
* this can trigger the hide event as it scrolls down the list to show the refresh indicator.
|
||||||
|
* Android shows the refresh indicator on top of the list so this is not an issue.
|
||||||
|
*
|
||||||
|
* @param nativeEvent The scroll event generated by the animated component onScroll prop
|
||||||
|
*/
|
||||||
onScroll({nativeEvent}: Object) {
|
onScroll({nativeEvent}: Object) {
|
||||||
const speed = nativeEvent.contentOffset.y < 0 ? 0 : this.lastOffset - nativeEvent.contentOffset.y;
|
const speed = nativeEvent.contentOffset.y < 0 ? 0 : this.lastOffset - nativeEvent.contentOffset.y;
|
||||||
if (speed < -speedOffset && !this.isHidden) { // Go down
|
if (speed < -speedOffset && !this.isHidden) { // Go down
|
||||||
|
|
|
@ -5,6 +5,21 @@ import {useTheme} from "react-native-paper";
|
||||||
import {createCollapsibleStack} from "react-navigation-collapsible";
|
import {createCollapsibleStack} from "react-navigation-collapsible";
|
||||||
import StackNavigator, {StackNavigationOptions} from "@react-navigation/stack";
|
import StackNavigator, {StackNavigationOptions} from "@react-navigation/stack";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll.
|
||||||
|
*
|
||||||
|
* Please use the getWebsiteStack function if your screen uses a webview as their main component as it needs special parameters.
|
||||||
|
*
|
||||||
|
* @param name The screen name in the navigation stack
|
||||||
|
* @param Stack The stack component
|
||||||
|
* @param component The screen component
|
||||||
|
* @param title The screen title shown in the header (needs to be translated)
|
||||||
|
* @param useNativeDriver Whether to use the native driver for animations.
|
||||||
|
* Set to false if the screen uses a webview as this component does not support native driver.
|
||||||
|
* In all other cases, set it to true for increase performance.
|
||||||
|
* @param options Screen options to use, or null if no options are necessary.
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
export function createScreenCollapsibleStack(
|
export function createScreenCollapsibleStack(
|
||||||
name: string,
|
name: string,
|
||||||
Stack: StackNavigator,
|
Stack: StackNavigator,
|
||||||
|
@ -33,6 +48,18 @@ export function createScreenCollapsibleStack(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a navigation stack with the collapsible library, allowing the header to collapse on scroll.
|
||||||
|
*
|
||||||
|
* This is a preset for screens using a webview as their main component, as it uses special parameters to work.
|
||||||
|
* (aka a dirty workaround)
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @param Stack
|
||||||
|
* @param component
|
||||||
|
* @param title
|
||||||
|
* @returns {JSX.Element}
|
||||||
|
*/
|
||||||
export function getWebsiteStack(name: string, Stack: any, component: any, title: string) {
|
export function getWebsiteStack(name: string, Stack: any, component: any, title: string) {
|
||||||
return createScreenCollapsibleStack(name, Stack, component, title, false);
|
return createScreenCollapsibleStack(name, Stack, component, title, false);
|
||||||
}
|
}
|
|
@ -6,10 +6,12 @@ import i18n from "i18n-js";
|
||||||
|
|
||||||
const PushNotification = require("react-native-push-notification");
|
const PushNotification = require("react-native-push-notification");
|
||||||
|
|
||||||
const reminderIdMultiplicator = 100;
|
// Used to multiply the normal notification id to create the reminder one. It allows to find it back easily
|
||||||
|
const reminderIdFactor = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async function asking permission to send notifications to the user
|
* Async function asking permission to send notifications to the user.
|
||||||
|
* Used on ios.
|
||||||
*
|
*
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
|
@ -32,10 +34,18 @@ export async function askPermissions() {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a notification for the given machine id at the given date.
|
||||||
|
*
|
||||||
|
* This creates 2 notifications. One at the exact date, and one a few minutes before, according to user preference.
|
||||||
|
*
|
||||||
|
* @param machineID The machine id to schedule notifications for. This is used as id and in the notification string.
|
||||||
|
* @param date The date to trigger the notification at
|
||||||
|
*/
|
||||||
function createNotifications(machineID: string, date: Date) {
|
function createNotifications(machineID: string, date: Date) {
|
||||||
let reminder = parseInt(AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current);
|
let reminder = parseInt(AsyncStorageManager.getInstance().preferences.proxiwashNotifications.current);
|
||||||
if (!isNaN(reminder)) {
|
if (!isNaN(reminder) && reminder > 0) {
|
||||||
let id = reminderIdMultiplicator * parseInt(machineID);
|
let id = reminderIdFactor * parseInt(machineID);
|
||||||
let reminderDate = new Date(date);
|
let reminderDate = new Date(date);
|
||||||
reminderDate.setMinutes(reminderDate.getMinutes() - reminder);
|
reminderDate.setMinutes(reminderDate.getMinutes() - reminder);
|
||||||
PushNotification.localNotificationSchedule({
|
PushNotification.localNotificationSchedule({
|
||||||
|
@ -57,11 +67,14 @@ function createNotifications(machineID: string, date: Date) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the server to enable/disable notifications for the specified machine
|
* Enables or disables notifications for the given machine.
|
||||||
*
|
*
|
||||||
* @param machineID The machine ID
|
* The function is async as we need to ask user permissions.
|
||||||
|
* If user denies, the promise will be rejected, otherwise it will succeed.
|
||||||
|
*
|
||||||
|
* @param machineID The machine ID to setup notifications for
|
||||||
* @param isEnabled True to enable notifications, false to disable
|
* @param isEnabled True to enable notifications, false to disable
|
||||||
* @param endDate
|
* @param endDate The trigger date, or null if disabling notifications
|
||||||
*/
|
*/
|
||||||
export async function setupMachineNotification(machineID: string, isEnabled: boolean, endDate: Date | null) {
|
export async function setupMachineNotification(machineID: string, isEnabled: boolean, endDate: Date | null) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -76,7 +89,7 @@ export async function setupMachineNotification(machineID: string, isEnabled: boo
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
PushNotification.cancelLocalNotifications({id: machineID});
|
PushNotification.cancelLocalNotifications({id: machineID});
|
||||||
let reminderId = reminderIdMultiplicator * parseInt(machineID);
|
let reminderId = reminderIdFactor * parseInt(machineID);
|
||||||
PushNotification.cancelLocalNotifications({id: reminderId.toString()});
|
PushNotification.cancelLocalNotifications({id: reminderId.toString()});
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ const dateRegExp = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/;
|
||||||
* @return {string} The string representation
|
* @return {string} The string representation
|
||||||
*/
|
*/
|
||||||
export function getCurrentDateString(): string {
|
export function getCurrentDateString(): string {
|
||||||
return dateToString(new Date(Date.now()));
|
return dateToString(new Date(Date.now()), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,6 +117,7 @@ export function stringToDate(dateString: string): Date | null {
|
||||||
* YYYY-MM-DD HH-MM-SS
|
* YYYY-MM-DD HH-MM-SS
|
||||||
*
|
*
|
||||||
* @param date The date object to convert
|
* @param date The date object to convert
|
||||||
|
* @param isUTC Whether to treat the date as UTC
|
||||||
* @return {string} The converted string
|
* @return {string} The converted string
|
||||||
*/
|
*/
|
||||||
export function dateToString(date: Date, isUTC: boolean): string {
|
export function dateToString(date: Date, isUTC: boolean): string {
|
||||||
|
@ -198,7 +199,7 @@ export function generateEmptyCalendar(numberOfMonths: number): Object {
|
||||||
let daysOfYear = {};
|
let daysOfYear = {};
|
||||||
for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
|
for (let d = new Date(Date.now()); d <= end; d.setDate(d.getDate() + 1)) {
|
||||||
const dateString = getDateOnlyString(
|
const dateString = getDateOnlyString(
|
||||||
dateToString(new Date(d)));
|
dateToString(new Date(d), false));
|
||||||
if (dateString !== null)
|
if (dateString !== null)
|
||||||
daysOfYear[dateString] = []
|
daysOfYear[dateString] = []
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitizes the given string to improve search performance
|
* Sanitizes the given string to improve search performance.
|
||||||
|
*
|
||||||
|
* This removes the case, accents, spaces and underscores.
|
||||||
*
|
*
|
||||||
* @param str The string to sanitize
|
* @param str The string to sanitize
|
||||||
* @return {string} The sanitized string
|
* @return {string} The sanitized string
|
||||||
|
@ -15,10 +17,24 @@ export function sanitizeString(str: string): string {
|
||||||
.replace(/_/g, "");
|
.replace(/_/g, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given string matches the query.
|
||||||
|
*
|
||||||
|
* @param str The string to check
|
||||||
|
* @param query The query string used to find a match
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
export function stringMatchQuery(str: string, query: string) {
|
export function stringMatchQuery(str: string, query: string) {
|
||||||
return sanitizeString(str).includes(sanitizeString(query));
|
return sanitizeString(str).includes(sanitizeString(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given arrays have an item in common
|
||||||
|
*
|
||||||
|
* @param filter The filter array
|
||||||
|
* @param categories The item's categories array
|
||||||
|
* @returns {boolean} True if at least one entry is in both arrays
|
||||||
|
*/
|
||||||
export function isItemInCategoryFilter(filter: Array<string>, categories: Array<string>) {
|
export function isItemInCategoryFilter(filter: Array<string>, categories: Array<string>) {
|
||||||
for (const category of categories) {
|
for (const category of categories) {
|
||||||
if (filter.indexOf(category) !== -1)
|
if (filter.indexOf(category) !== -1)
|
||||||
|
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
import {Linking} from 'react-native';
|
import {Linking} from 'react-native';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class use to handle depp links scanned or clicked.
|
||||||
|
*/
|
||||||
export default class URLHandler {
|
export default class URLHandler {
|
||||||
|
|
||||||
static SCHEME = "campus-insat://";
|
static SCHEME = "campus-insat://"; // Urls beginning with this string will be opened in the app
|
||||||
|
|
||||||
static CLUB_INFO_URL_PATH = "club";
|
static CLUB_INFO_URL_PATH = "club";
|
||||||
static EVENT_INFO_URL_PATH = "event";
|
static EVENT_INFO_URL_PATH = "event";
|
||||||
|
@ -20,27 +23,12 @@ export default class URLHandler {
|
||||||
this.onDetectURL = onDetectURL;
|
this.onDetectURL = onDetectURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
listen() {
|
/**
|
||||||
Linking.addEventListener('url', this.onUrl);
|
* Parses the given url to retrieve the corresponding app path and associated arguments.
|
||||||
Linking.getInitialURL().then(this.onInitialUrl);
|
*
|
||||||
}
|
* @param url The url to parse
|
||||||
|
* @returns {{path: string, queryParams: {}}}
|
||||||
onUrl = ({url}: { url: string }) => {
|
*/
|
||||||
if (url != null) {
|
|
||||||
let data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
|
||||||
if (data !== null)
|
|
||||||
this.onDetectURL(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onInitialUrl = (url: ?string) => {
|
|
||||||
if (url != null) {
|
|
||||||
let data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
|
||||||
if (data !== null)
|
|
||||||
this.onInitialURLParsed(data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static parseUrl(url: string) {
|
static parseUrl(url: string) {
|
||||||
let params = {};
|
let params = {};
|
||||||
let path = "";
|
let path = "";
|
||||||
|
@ -63,7 +51,15 @@ export default class URLHandler {
|
||||||
return {path: path, queryParams: params};
|
return {path: path, queryParams: params};
|
||||||
}
|
}
|
||||||
|
|
||||||
static getUrlData({path, queryParams}: Object) {
|
/**
|
||||||
|
* Gets routing data corresponding to the given url.
|
||||||
|
* If the url does not match any existing route, null will be returned.
|
||||||
|
*
|
||||||
|
* @param path Url path
|
||||||
|
* @param queryParams Url parameters
|
||||||
|
* @returns {null}
|
||||||
|
*/
|
||||||
|
static getUrlData({path, queryParams}: { path: string, queryParams: { [key: string]: string } }) {
|
||||||
let data = null;
|
let data = null;
|
||||||
if (path !== null) {
|
if (path !== null) {
|
||||||
if (URLHandler.isClubInformationLink(path))
|
if (URLHandler.isClubInformationLink(path))
|
||||||
|
@ -74,18 +70,42 @@ export default class URLHandler {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given url is in a valid format
|
||||||
|
*
|
||||||
|
* @param url The url to check
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
static isUrlValid(url: string) {
|
static isUrlValid(url: string) {
|
||||||
return this.getUrlData(URLHandler.parseUrl(url)) !== null;
|
return this.getUrlData(URLHandler.parseUrl(url)) !== null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given path links to the club information screen
|
||||||
|
*
|
||||||
|
* @param path The url to check
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
static isClubInformationLink(path: string) {
|
static isClubInformationLink(path: string) {
|
||||||
return path === URLHandler.CLUB_INFO_URL_PATH;
|
return path === URLHandler.CLUB_INFO_URL_PATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given path links to the planning information screen
|
||||||
|
*
|
||||||
|
* @param path The url to check
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
static isPlanningInformationLink(path: string) {
|
static isPlanningInformationLink(path: string) {
|
||||||
return path === URLHandler.EVENT_INFO_URL_PATH;
|
return path === URLHandler.EVENT_INFO_URL_PATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates data formatted for the club information screen from the url parameters.
|
||||||
|
*
|
||||||
|
* @param params Url parameters to convert
|
||||||
|
* @returns {null|{route: string, data: {clubId: number}}}
|
||||||
|
*/
|
||||||
static generateClubInformationData(params: Object): Object | null {
|
static generateClubInformationData(params: Object): Object | null {
|
||||||
if (params !== undefined && params.id !== undefined) {
|
if (params !== undefined && params.id !== undefined) {
|
||||||
let id = parseInt(params.id);
|
let id = parseInt(params.id);
|
||||||
|
@ -96,6 +116,12 @@ export default class URLHandler {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates data formatted for the planning information screen from the url parameters.
|
||||||
|
*
|
||||||
|
* @param params Url parameters to convert
|
||||||
|
* @returns {null|{route: string, data: {clubId: number}}}
|
||||||
|
*/
|
||||||
static generatePlanningInformationData(params: Object): Object | null {
|
static generatePlanningInformationData(params: Object): Object | null {
|
||||||
if (params !== undefined && params.id !== undefined) {
|
if (params !== undefined && params.id !== undefined) {
|
||||||
let id = parseInt(params.id);
|
let id = parseInt(params.id);
|
||||||
|
@ -106,4 +132,44 @@ export default class URLHandler {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts listening to events.
|
||||||
|
*
|
||||||
|
* There are 2 types of event.
|
||||||
|
*
|
||||||
|
* A classic event, triggered while the app is active.
|
||||||
|
* An initial event, called when the app was opened by clicking on a link
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
listen() {
|
||||||
|
Linking.addEventListener('url', this.onUrl);
|
||||||
|
Linking.getInitialURL().then(this.onInitialUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets data from the given url and calls the classic callback with it.
|
||||||
|
*
|
||||||
|
* @param url The url detected
|
||||||
|
*/
|
||||||
|
onUrl = ({url}: { url: string }) => {
|
||||||
|
if (url != null) {
|
||||||
|
let data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||||
|
if (data !== null)
|
||||||
|
this.onDetectURL(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets data from the given url and calls the initial callback with it.
|
||||||
|
*
|
||||||
|
* @param url The url detected
|
||||||
|
*/
|
||||||
|
onInitialUrl = (url: ?string) => {
|
||||||
|
if (url != null) {
|
||||||
|
let data = URLHandler.getUrlData(URLHandler.parseUrl(url));
|
||||||
|
if (data !== null)
|
||||||
|
this.onInitialURLParsed(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,18 @@ type response_format = {
|
||||||
|
|
||||||
const API_ENDPOINT = "https://www.amicale-insat.fr/api/";
|
const API_ENDPOINT = "https://www.amicale-insat.fr/api/";
|
||||||
|
|
||||||
export async function apiRequest(path: string, method: string, params: ?Object) {
|
/**
|
||||||
|
* Sends a request to the Amicale Website backend
|
||||||
|
*
|
||||||
|
* In case of failure, the promise will be rejected with the error code.
|
||||||
|
* In case of success, the promise will return the data object.
|
||||||
|
*
|
||||||
|
* @param path The API path from the API endpoint
|
||||||
|
* @param method The HTTP method to use (GET or POST)
|
||||||
|
* @param params The params to use for this request
|
||||||
|
* @returns {Promise<R>}
|
||||||
|
*/
|
||||||
|
export async function apiRequest(path: string, method: string, params: ?{ [key: string]: string }) {
|
||||||
if (params === undefined || params === null)
|
if (params === undefined || params === null)
|
||||||
params = {};
|
params = {};
|
||||||
|
|
||||||
|
@ -51,6 +62,14 @@ export async function apiRequest(path: string, method: string, params: ?Object)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given API response is valid.
|
||||||
|
*
|
||||||
|
* For a request to be valid, it must match the response_format as defined in this file.
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
export function isResponseValid(response: response_format) {
|
export function isResponseValid(response: response_format) {
|
||||||
let valid = response !== undefined
|
let valid = response !== undefined
|
||||||
&& response.error !== undefined
|
&& response.error !== undefined
|
||||||
|
@ -63,7 +82,11 @@ export function isResponseValid(response: response_format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read data from FETCH_URL and return it.
|
* Reads data from the given url and returns it.
|
||||||
|
*
|
||||||
|
* Only use this function for non API calls.
|
||||||
|
* For Amicale API calls, please use the apiRequest function.
|
||||||
|
*
|
||||||
* If no data was found, returns an empty object
|
* If no data was found, returns an empty object
|
||||||
*
|
*
|
||||||
* @param url The urls to fetch data from
|
* @param url The urls to fetch data from
|
||||||
|
|
|
@ -1,7 +1,19 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {StatusBar} from 'react-native';
|
|
||||||
import {useCollapsibleStack} from "react-navigation-collapsible";
|
import {useCollapsibleStack} from "react-navigation-collapsible";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function used to manipulate Collapsible Hooks from a class.
|
||||||
|
*
|
||||||
|
* Usage :
|
||||||
|
*
|
||||||
|
* export withCollapsible(Component)
|
||||||
|
*
|
||||||
|
* replacing Component with the one you want to use.
|
||||||
|
* This component will then receive the collapsibleStack prop.
|
||||||
|
*
|
||||||
|
* @param Component The component to use Collapsible with
|
||||||
|
* @returns {React.ComponentType<React.ClassAttributes<unknown>>}
|
||||||
|
*/
|
||||||
export const withCollapsible = (Component: any) => {
|
export const withCollapsible = (Component: any) => {
|
||||||
return React.forwardRef((props: any, ref: any) => {
|
return React.forwardRef((props: any, ref: any) => {
|
||||||
|
|
||||||
|
@ -14,7 +26,6 @@ export const withCollapsible = (Component: any) => {
|
||||||
progress,
|
progress,
|
||||||
opacity,
|
opacity,
|
||||||
} = useCollapsibleStack();
|
} = useCollapsibleStack();
|
||||||
const statusbarHeight = StatusBar.currentHeight != null ? StatusBar.currentHeight : 0;
|
|
||||||
return <Component
|
return <Component
|
||||||
collapsibleStack={{
|
collapsibleStack={{
|
||||||
onScroll,
|
onScroll,
|
||||||
|
|
Loading…
Reference in a new issue