Files
bigbluebutton-tablet/react-native/app/routes/component.tsx
2023-01-27 10:55:56 -03:00

179 lines
5.3 KiB
TypeScript

import * as React from 'react';
import { NavigationContainer, useNavigation} from '@react-navigation/native';
import {ListPortals} from '../pages/list_portals/component';
import {usePortal} from '../contexts/portals/hook';
import AsyncStorage from '@react-native-async-storage/async-storage';
import i18next from 'i18next';
import {createDrawerNavigator} from '@react-navigation/drawer';
import SdkContainer from '../../bootstrap/sdk/container';
import {initTranslation} from '../translations/index';
import { Alert, Linking, Text } from 'react-native';
import { createNewPortal } from '../pages/utils/createNewPortal';
import { emitter } from '../emitter/emitter';
import { IPortal } from '../pages/utils/types';
const DeepLink = ()=>{
initTranslation();
const SCHEME = 'bigbluebutton-tablet://';
var lastDeepLinkPortalName:String|undefined = undefined;
const navigation = useNavigation();
const {portals, setPortals} = usePortal();
function decodeUrlParameter(str:string) {
return decodeURIComponent(str.replace(/\+/g, '%20'));
}
async function createPortalFromDeepLink(link: string){
const linkWithoutScheme = link.replace(SCHEME, '').replace(/\+/g, ' ');
if(linkWithoutScheme === ''){
navigation.navigate(i18next.t('mobileApp.portals.drawerNavigation.button.label'))
return Alert.alert(i18next.t('mobileApp.portals.handleWithoutURL'))
}
//
let linkParts = linkWithoutScheme.split('/' + encodeURIComponent("https://"));
let portalName = linkParts[0];
let portalLink = linkParts[1];
if(!portalName || !portalLink) {
navigation.navigate(i18next.t('mobileApp.portals.drawerNavigation.button.label'))
return Alert.alert(i18next.t('mobileApp.portals.handleWithoutURL'))
}
portalName=decodeUrlParameter(portalName);
portalLink= 'https://' + decodeUrlParameter(portalLink);
portalLink=portalLink.replace(/%20/g, '+');
// Join links are temporary (discarded on next app launch)
const isTemporary = portalLink.includes('/bigbluebutton/api/join?');
const portalToAdd:IPortal = {
name: portalName,
url: portalLink,
temporary: isTemporary
}
lastDeepLinkPortalName = portalName;
// Adding LinkedPortal to AsyncStorage
const newPortals = await createNewPortal(portalToAdd)
// Adding to context
setPortals(newPortals)
// Navigate to it
navigation.navigate(lastDeepLinkPortalName);
}
async function checkIfHaveTemporaryPortal(){
let portalsParsed: IPortal[]|null = null;
try {
let items = await AsyncStorage.getAllKeys();
// If portal storage is empty, initialize it
if(!items.includes('portal')) {
await AsyncStorage.setItem('portal', JSON.stringify([]));
}
const portalsFromStorage = await AsyncStorage.getItem('portal')
portalsParsed = portalsFromStorage ? JSON.parse(portalsFromStorage) : null
} catch (e) {
console.log('error', e);
}
if(!portalsParsed){
console.error("Invalid portal storage: ", portalsParsed);
return;
}
// Clear temporary portals from previous executions
const portalsWithoutTemporary = portalsParsed.filter((portal: IPortal)=>{
if(portal.temporary == true) return false;
if(portal.name == lastDeepLinkPortalName) return false;
return portal;
});
await AsyncStorage.setItem('portal', JSON.stringify(portalsWithoutTemporary));
setPortals(portalsWithoutTemporary);
// Handle app launch with link
getLinkFromAppLaunch();
// Handle link when app is running
Linking.addEventListener('url', (url)=>{
createPortalFromDeepLink(url.url);
});
}
async function getLinkFromAppLaunch(){
const linkFromAppClosed = await Linking.getInitialURL();
if(linkFromAppClosed === null) return;
createPortalFromDeepLink(linkFromAppClosed);
}
React.useEffect(() => {
checkIfHaveTemporaryPortal();
}, []);
return null;
}
const Drawer = createDrawerNavigator();
export const Routes = () => {
initTranslation();
const {portals, setPortals} = usePortal();
async function getPortals() {
try {
let items = await AsyncStorage.getAllKeys();
if (items.includes('portal')) {
let portalsStorage = await AsyncStorage.getItem('portal');
portalsStorage = JSON.parse(portalsStorage);
setPortals(portalsStorage);
}
} catch (e) {
console.log('error', e);
return null;
}
}
React.useEffect(() => {
getPortals();
}, []);
return (
<>
<NavigationContainer>
<DeepLink/>
<Drawer.Navigator
initialRouteName={i18next.t('mobileApp.portals.drawerNavigation.button.label')}
screenOptions={{
headerShown: false,
}}>
<Drawer.Screen
name={i18next.t('mobileApp.portals.drawerNavigation.button.label')}
component={ListPortals}
/>
{portals && portals.length
? portals.map((item: { name: React.Key | null | undefined; url: string; }) => {
return (
<Drawer.Screen
key={item.name}
name={item.name}
children={() => <SdkContainer url={item.url} />}
/>
);
})
: null}
</Drawer.Navigator>
</NavigationContainer>
</>
);
};