diff --git a/App.tsx b/App.tsx index 40949c4..022972f 100644 --- a/App.tsx +++ b/App.tsx @@ -1,22 +1,21 @@ import 'react-native-gesture-handler'; import * as React from 'react'; -import {StyleSheet, View, Platform, SafeAreaView} from 'react-native'; -import {BigbluebuttonMobile} from 'bigbluebutton-mobile-sdk'; -import { Bootstrap } from './react-native/bootstrap/start/component'; +import { StyleSheet, Platform, LogBox } from 'react-native'; import { Routes } from './react-native/app/routes/component'; +import { PortalContextContainer } from './react-native/app/contexts/portals/container'; export default function App() { + React.useEffect(()=>{ + LogBox.ignoreLogs([ + "[react-native-gesture-handler] Seems like you\'re using an old API with gesture components, check out new Gestures system!", + ]); + }) return ( <> + + ); } - -const styles = StyleSheet.create({ - bbb: { - marginTop: Platform.select({ios: 20, android: 0}), - flex: 1, - }, -}); diff --git a/react-native/app/components/button/component.tsx b/react-native/app/components/button/component.tsx new file mode 100644 index 0000000..16bfbd2 --- /dev/null +++ b/react-native/app/components/button/component.tsx @@ -0,0 +1,19 @@ +import React from 'react' +import { Text } from 'react-native' +import { TouchableOpacity } from 'react-native-gesture-handler' +import { ButtonAppStyle, TextButton } from './styles'; + +type IButtonApp = { + children?: object + onPress?: Function +} +export const ButtonApp = ({children, onPress}:IButtonApp)=>{ + return ( + <> + + {children} + + + + ) +} \ No newline at end of file diff --git a/react-native/app/components/button/styles.ts b/react-native/app/components/button/styles.ts new file mode 100644 index 0000000..1da892c --- /dev/null +++ b/react-native/app/components/button/styles.ts @@ -0,0 +1,19 @@ +import styled from 'styled-components/native'; +import { colors } from '../../styles/colors'; + + +export const ButtonAppStyle = styled.TouchableHighlight` + height: 50px; + font-size: 22px; + background-color: ${colors.primary_light}; + border-radius: 5px; + align-items: center; + justify-content: center; +` + +export const TextButton = styled.Text` + font-size: 22px; + font-weight: bold; + color: #fff; + +` \ No newline at end of file diff --git a/react-native/app/components/input/text/component.tsx b/react-native/app/components/input/text/component.tsx new file mode 100644 index 0000000..90e81e8 --- /dev/null +++ b/react-native/app/components/input/text/component.tsx @@ -0,0 +1,21 @@ +import React from 'react' +import { LabelInput, WrapperInputText } from './styles'; + +type IInputText = { + children?: object; + placeholder: string; + label: string; + onChangeText?: any, + value?: any +} +export const InputText = (props: IInputText)=>{ + + const {children, placeholder, label, onChangeText, value} = props + + return ( + <> + {props.label} + + + ) +} \ No newline at end of file diff --git a/react-native/app/components/input/text/styles.ts b/react-native/app/components/input/text/styles.ts new file mode 100644 index 0000000..8b40d5e --- /dev/null +++ b/react-native/app/components/input/text/styles.ts @@ -0,0 +1,16 @@ +import styled from 'styled-components/native'; + + +export const WrapperInputText = styled.TextInput` + background-color: #f2f2f2; + padding: 10px 20px 10px 20px; + border-radius: 5px + +` + +export const LabelInput = styled.Text` + color: #fff; + font-size: 20px; + font-weight: bold; + +` \ No newline at end of file diff --git a/react-native/app/pages/list_portals/component.tsx b/react-native/app/pages/list_portals/component.tsx new file mode 100644 index 0000000..1eead86 --- /dev/null +++ b/react-native/app/pages/list_portals/component.tsx @@ -0,0 +1,116 @@ +import AsyncStorage from '@react-native-async-storage/async-storage' +import React, { useRef } from 'react' +import { ButtonDelete, ButtonOpen, DivButtonDelete, DivDelete, ItemList, TextButtonOpen, TextItem, TextWithoutPortal, WrapperItemListText, WrapperItemListView, WrapperList, WrapperListContainer, WrapperViewAdd } from './styles' +import { usePortal } from '../../contexts/portals/hook'; +import { Modalize } from 'react-native-modalize'; +import { Alert } from 'react-native'; +import { StorePortals } from '../store_portals/component'; +import FontAwesome5 from 'react-native-vector-icons/FontAwesome5'; +import { colors } from '../../styles/colors'; +import { SwipeListView } from 'react-native-swipe-list-view'; +import { IHandles } from 'react-native-modalize/lib/options'; +import { IItem, IItemDelete, IListPortalsDTO } from './types' + +export const ListPortals = ({ navigation }: IListPortalsDTO)=>{ + const icon = ; + 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 as string) + setPortals(portalsStorage) + console.log('portals', portals) + } else { + console.log('Dont Have Portals Storage') + } + } catch(e){ + console.log('error',e) + } + } + + React.useEffect(()=>{getPortals()}, []) + + const modalizeRef = useRef(null); + + const onOpen = () => modalizeRef.current?.open(); + + const DeleteItem = async (item:IItemDelete)=>{ + try{ + let items = await AsyncStorage.getAllKeys() + if(items.includes('portal')){ + + let portalsStorage = await AsyncStorage.getItem('portal') + portalsStorage = JSON.parse(portalsStorage as string) + const newPortalStorage = portalsStorage?.filter((portalItem: IItemDelete)=>{ + if(item.name == portalItem.name) return false + return portalItem + }) + + await AsyncStorage.setItem('portal', JSON.stringify(newPortalStorage)) + setPortals(newPortalStorage) + } else { + Alert.alert('Portals', 'Dont have Portals in Storage') + } + } catch(e){ + console.log('error',e) + } + } + + const onPress = (namePortal:string) => navigation.navigate(namePortal); + + const Item = ({namePortal, url}: IItem)=>( + onPress(namePortal)}> + {namePortal} + {url} + + ) + + return ( + + + + New Portal {icon} + + + + + + + + + { + portals && portals.length != 0 ? + } + renderHiddenItem={ (rowData, rowMap) => ( + + + DeleteItem(rowData.item as IItemDelete)}> + + + + + )} + leftOpenValue={0} + rightOpenValue={-80} + disableRightSwipe={true} + closeOnRowPress={true} + closeOnRowOpen={true} + onRowOpen={(rowKey, rowMap) => { + setTimeout(() => { + if(rowMap[rowKey] != undefined){ + rowMap[rowKey].closeRow() + } + }, 3000) + }} + /> + : There aren't Portals + } + + ) +} \ No newline at end of file diff --git a/react-native/app/pages/list_portals/styles.ts b/react-native/app/pages/list_portals/styles.ts new file mode 100644 index 0000000..13239b2 --- /dev/null +++ b/react-native/app/pages/list_portals/styles.ts @@ -0,0 +1,125 @@ +import styled from 'styled-components/native' +import { colors } from '../../styles/colors'; +import { TouchableOpacity } from 'react-native-gesture-handler'; +import { SwipeListView } from 'react-native-swipe-list-view'; + + +export const WrapperListContainer = styled.View` + background-color: ${colors.secundary}; + flex: 1 ; + justify-content: center; + align-items: center; + padding: 20px; +`; + +export const WrapperList = styled.FlatList` + background-color: ${colors.primary}; + width: 95%; + + border-radius: 10px; +` + +export const WrapperItemListText = styled.TouchableOpacity` + + width: 300px; + padding: 5px; + margin: 3% auto; + height: 80px; + background-color: ${colors.primary_light}; + border-radius: 10px; + flex-direction: column; + align-items: center; + justify-content: center; +` +export const WrapperItemListView = styled.View` + display: flex; + flex: 1; + background-color: black; + + padding: 10px; + justify-content: center; + align-items: center; + text-align: center; + height: 100px; + width: 200px; + +` + +export const ItemList = styled.Text` + color: #fff; + padding: 2px; + font-size: 16px; + + font-weight: ${(props)=>(props.bold ? 'bold': 'normal')}; + +` + + +export const TextItem = styled.Text` + font-size: 18px; +` + +export const WrapperViewAdd = styled.View` + background-color: ${colors.primary}; + margin: 70px 0px 0px 0px; + +` + +export const ButtonOpen = styled.TouchableOpacity` + padding: 10px; + background-color: ${colors.primary}; + width: 90%; + margin: 10px; + border-radius: 10px; + + align-items: center; + justify-content: center; + + +` + +export const TextButtonOpen = styled.Text` + color: #fff; + font-size: 20px; + font-weight: bold; +` + + +export const TextWithoutPortal = styled.Text` + color: ${colors.primary}; + font-size: 20px; + +` + +export const ButtonDelete = styled.TouchableOpacity` + background-color: ${colors.white}; + border-radius: 10px; + margin: 3% auto; + width: 100%; + height: 80px; + //left: 20px; + + + justify-content: center; + align-items: center; + + flex-direction: row; + +` + +export const DivButtonDelete = styled.View` + width: 100px; + align-items: center; + justify-content: center; + margin: 3% 0px; + align-content: center; + justify-items: center; + + +` + +export const DivDelete = styled.View` + width: 300px; + justify-content: flex-end; + align-items: flex-end; +` \ No newline at end of file diff --git a/react-native/app/pages/list_portals/types.ts b/react-native/app/pages/list_portals/types.ts new file mode 100644 index 0000000..721fdf8 --- /dev/null +++ b/react-native/app/pages/list_portals/types.ts @@ -0,0 +1,14 @@ +import { DrawerScreenProps } from '@react-navigation/drawer'; +export type IItem = { + url: string; + namePortal: string; +} + +export type IListPortalsDTO = { + navigation: DrawerScreenProps +} + +export type IItemDelete = { + name: string; + url: string +} \ No newline at end of file diff --git a/react-native/app/pages/store_portals/component.tsx b/react-native/app/pages/store_portals/component.tsx new file mode 100644 index 0000000..c772ff6 --- /dev/null +++ b/react-native/app/pages/store_portals/component.tsx @@ -0,0 +1,71 @@ +import React from 'react' +import { InputText } from '../../components/input/text/component'; +import { TextEmptyFileds, WrapperInput, WrapperStore, WrapperStoreContainer } from './styles'; +import { Text } from 'react-native'; +import { ButtonApp } from '../../components/button/component'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { usePortal } from '../../contexts/portals/hook'; +import { IStore } from './types'; + +export const StorePortals = ({navigation, modalizeRef}:IStore)=>{ + const {portals, setPortals} = usePortal() + const [name, setName] = React.useState(''); + const [url, setUrl] = React.useState(''); + const [emptyFields, setEmptyFields] = React.useState(false); + + async function newPortal(name:string, url:string){ + let portalsStorage; + portalsStorage = await AsyncStorage.getItem('portal') + portalsStorage = portalsStorage ? JSON.parse(portalsStorage) : null + portalsStorage.push({name, url}) + await AsyncStorage.setItem('portal', JSON.stringify(portalsStorage)) + setPortals(portalsStorage) + setTimeout(()=>{ + modalizeRef?.current?.close(); + }, 500) + + navigation.navigate(name) + } + + async function onPress(){ + + if(!name || !url) return setEmptyFields(true) + try{ + await newPortal(name, url ) + } catch(e){ + console.log('error', e) + await AsyncStorage.setItem('portal', JSON.stringify([])) + newPortal(name, url ) + return null + } + } + + const textEmptyFields = ()=>( + <> + { + emptyFields ? + Empty Fields + : null + } + + ) + + return ( + <> + + + {textEmptyFields()} + + setName(e)} placeholder='Demo Server' label='Portal Name'/> + + + setUrl(e)} placeholder='https://bigbluebutton.org/' label='Server URL'/> + + + Add + + + + + ) +} \ No newline at end of file diff --git a/react-native/app/pages/store_portals/styles.ts b/react-native/app/pages/store_portals/styles.ts new file mode 100644 index 0000000..ed708d6 --- /dev/null +++ b/react-native/app/pages/store_portals/styles.ts @@ -0,0 +1,35 @@ +import styled from 'styled-components/native' +import { colors } from '../../styles/colors'; + +export const WrapperStoreContainer = styled.View` + background-color: ${colors.white}; + flex: 1 ; + justify-content: center; + align-items: center; +`; + + + +export const WrapperStore = styled.View` + background-color: ${colors.primary}; + width: 80%; + height: 95%; + border-radius: 10px; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 5px; + padding-top: 20px; +` + + +export const WrapperInput = styled.View` + background-color: transparent; + width: 80%; + height: 100px; + margin: 20px; + +` +export const TextEmptyFileds = styled.Text` + color: ${colors.danger} +` \ No newline at end of file diff --git a/react-native/app/pages/store_portals/types.ts b/react-native/app/pages/store_portals/types.ts new file mode 100644 index 0000000..a137346 --- /dev/null +++ b/react-native/app/pages/store_portals/types.ts @@ -0,0 +1,6 @@ +import { Modalize } from 'react-native-modalize'; +import { IHandles } from 'react-native-modalize/lib/options'; +export type IStore = { + navigation?: any; + modalizeRef?: IHandles +} \ No newline at end of file diff --git a/react-native/app/routes/component.js b/react-native/app/routes/component.js index de02eef..03f129c 100644 --- a/react-native/app/routes/component.js +++ b/react-native/app/routes/component.js @@ -1,37 +1,70 @@ import * as React from 'react'; -import { Button, View } from 'react-native'; -import { createDrawerNavigator } from '@react-navigation/drawer'; +import { Alert } from 'react-native'; import { NavigationContainer } 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'; -function NotificationsScreen({ navigation }) { - return ( - -