@fto-consult/common
Version:
Un ensemble de bibliothèques et d'utilistaires communs pour le développement d'applications javascript
224 lines (188 loc) • 8.91 kB
JavaScript
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/****@namespace navigation */
import {isObj,isFunction,extendObj,defaultStr,defaultObj,isNonNullString} from "$cutils";
import {getURIPathName} from "$cutils/uri";
import {isWeb,isClientSide} from "$cplatform";
import actions from "../actions";
import { navigationRef } from "$active-platform/navigation";
export * from "$active-platform/navigation";
import * as React from "react";
/**** permet d'uniformaliser le nom d'un écran ou d'une route*/
export const sanitizeName = function (screenName){
if(!isNonNullString(screenName)) return "";
const split = screenName.split("?");
screenName = split[0].trim().toSnakeCase().toLowerCase().replace(/\s/g, "-").replaceAll("_","-").replaceAll("--","-").trim();
if(split.length > 1){
const qs = split.filter((v,index)=>index>0 && isNonNullString(v)).join("&");
return `${screenName}${qs?`?${qs}`:""}`
}
return screenName;
}
const ROUTER_MANAGER = {};
let initialRouteName = "";
let isNavigationReady = false;
export const isReady = x=> isNavigationReady;
export const setIsReady = isReady => isNavigationReady = isReady;
export const setInitialRouteName = (name)=> isNonNullString(name)? initialRouteName = name : undefined;
export const getInitialRouteName = ()=> initialRouteName;
export const DRAWER_NAVIGATOR_NAME = "DRAWER_NAVIGATOR_NAME";
export const activeNavigationRef = React.createRef(null);
export const setActiveNavigation = (navigation)=>{
activeNavigationRef.current = navigation;
}
export const ROUTES_CALLBACK = {};
export function setActiveRoute (currentRoute){
currentRoute = isNonNullString(currentRoute)? {name:currentRoute}: defaultObj(currentRoute);
currentRoute.name = sanitizeName(currentRoute.name);
ROUTER_MANAGER.currentRoute = currentRoute;
return currentRoute;
}
export const canUseNavigationRef = x=> isObj(navigationRef) && isFunction(navigationRef.isReady) && navigationRef.isReady();
export const getActiveRoute = x=> {
if(isObj(ROUTER_MANAGER.currentRoute) && isNonNullString(ROUTER_MANAGER.currentRoute.name)){
ROUTER_MANAGER.currentRoute.routeName = defaultStr(ROUTER_MANAGER.currentRoute.routeName,ROUTER_MANAGER.currentRoute.name);
return ROUTER_MANAGER.currentRoute;
}
if(canUseNavigationRef() && navigationRef.getCurrentRoute){
return defaultObj(navigationRef.getCurrentRoute());
}
const name = defaultStr(getInitialRouteName());
return {name,routeName:name};
};
/**** permet de naviguer vers la route précédente
* @param {object} options - les options supplémentaires à passer à la fonction navigation
* @param {object} navigation - l'objet navigation à utiliser de manière personalisé pour la navigation
* @return {boolean} si la navigation a eu lieu où pas
*/
export const goBack = (options,navigation)=>{
if(typeof options ==='function'){
options = {onGoBack:options};
}
navigation = isValidNavigation(navigation) ? navigation : navigationRef;
if(typeof navigation.canGoBack ==='function' && navigation.canGoBack()){
options = defaultObj(options);
if(typeof options.beforeGoBack =='function' && options.beforeGoBack({...options,beforeGoBack:undefined,goBack:()=> navigation.goBack(null)}) === false) return false;
navigation.goBack(null);
if(typeof options.onGoBack ==='function'){
options.onGoBack();
} if(typeof options.callback ==='function'){
options.callback();
}
return true;
}
return false;
}
export const EXIT_COUNTER = {
counter : 0,
reset : ()=>{
EXIT_COUNTER.counter = 0;
},
}
/*** vérifie si l'objet navigation passé en paramètre est valide où pas */
export const isValidNavigation = (navigation)=> isObj(navigation) && isFunction(navigation.navigate) && isFunction(navigation.goBack);
export const useNavigation = ()=> {
return activeNavigationRef.current && activeNavigationRef.current.setOptions ? activeNavigationRef.current : navigationRef;
};
/*** retourne les options de la route courante */
export const getRouteOptions = (opts)=>{
let {route} = defaultObj(opts);
route = defaultObj(route);
const routeName = sanitizeName(defaultStr(route.name,route.routeName));
route.params = {...defaultObj(route.params),...defaultObj(ROUTES_CALLBACK[routeName])};
route.data = defaultObj(route.data,route.params.data);
return route;
}
export const getRouteOpts = getRouteOptions;
/*** permet de garder les options de l'écran courant */
let screenOptions = {};
export const setScreenOptions = (options)=>{
screenOptions = typeof options =='object' && options ? options : {};
return screenOptions;
}
export const useScreenOptions = ()=>{
return defaultObj(screenOptions);
}
export const getScreenOptions = useScreenOptions;
export const isRouteActive = (routeName)=>{
if(isNonNullString(routeName)){
routeName = {routeName};
}
routeName = defaultObj(routeName).routeName;
let currentRoute = defaultStr(getActiveRoute().name);
routeName = isObj(routeName)? defaultStr(routeName.routeName,routeName.name) : defaultStr(routeName);
if(!currentRoute){
currentRoute = getInitialRouteName();
}
const sanit = sanitizeName(routeName);
return routeName && (sanit === currentRoute || sanit === sanitizeName(currentRoute)) ? true : false;
}
export const currentRouteRef = React.createRef(null);
export const setRoute = (route)=>{
currentRouteRef.current = route;
}
/*** retourne l'objet route courante, surtout en environnement react-native avec comme router react-navigation */
export const useRoute = (route)=>{
if(currentRouteRef.current) return currentRouteRef.current;
if(!canUseNavigationRef()) return {};
return navigationRef.getCurrentRoute();
}
export const getRoute = useRoute;
/**** retourne les props à passer à l'objet tableDataItem
* @param props {object} les props à passer à l'écran en cours
* @param table {string ||object}, les options de la table récupérée en base de données
*/
export function getScreenProps(props){
const {params,data} = getRouteOptions(props);
return {...params,...props,data:defaultObj(params.data,data,props?.data)};
}
/*** permet de navigater ver la route toRoute en utilisant l'objet navigation
* @param {(string|object)} toRoute - la route vers laquelle on souhaite naviguer
* @param {object} navigation - l'objet à utiliser pour la navigation
*/
export const navigate = (toRoute,navigation)=>{
if(!isClientSide()) return;
if(isNonNullString(toRoute)){
toRoute = {url:toRoute};
}
if(!isObj(toRoute)) return null;
let {routeName,route,from,url,routeParams,href,params,source,...rest} = toRoute;
routeName = sanitizeName(defaultStr(url,href,routeName,route));
params = extendObj({},params,routeParams);
params = {...defaultObj(rest),...params};
source = defaultStr(source).toLowerCase();
const currentNavigation = isValidNavigation(navigation) ? navigation : navigationRef;
const {navigate} = currentNavigation;
if(typeof navigate === "function"){
if(typeof currentNavigation.isReady =='function' && !currentNavigation.isReady()) return;
params = {...defaultObj(rest),...params};
ROUTES_CALLBACK[routeName] = {};
///on persiste les paramètes de la route
for(let i in params){
if(typeof params[i] ==='function'){
ROUTES_CALLBACK[routeName][i] = params[i];
delete params[i];
}
}
return navigate(routeName,params)
}
}
/*** redigige l'utilisateur vers le chemin pathname s'il s'agit d'une application web
* @param {string} pathname - le chemin vers lequel l'utilisateur sera redirigé
* @param {boolean} force - si la redirection sera forcée au cas où l'url actuel est le même que celui vers lequel on souhaite rédirigé l'utilisateur
*/
export const redirectIfWeb = (pathname,force)=>{
pathname = getURIPathName(pathname);
if(isWeb() && typeof window !=="undefined" && window.location){
let xN = pathname.ltrim("/").rtrim("/").trim();
let cW = defaultStr(window.location.pathname).ltrim("/").rtrim("/").trim();
if((xN !== cW) || (force === true) ){
window.location.pathname = pathname;
}
return window.location.pathname;
}
return null;
}
export const redirectOnWeb = redirectIfWeb;
export const redirect = redirectIfWeb;