├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── cordova ├── .gitignore ├── config.xml ├── package-lock.json ├── package.json └── www │ ├── 403 Error Forbidden-bro.svg │ ├── 404 Error-bro.svg │ ├── Mobile login-cuate-green.svg │ ├── Mobile login-cuate.svg │ ├── asset-manifest.json │ ├── browser-matrix.js │ ├── browser-matrix.js.map │ ├── circle-scatter-haikei.svg │ ├── circle-scatter-haikei1.svg │ ├── css │ └── index.css │ ├── favicon.ico │ ├── icons8-tiger-96.png │ ├── img │ └── logo.png │ ├── index.html │ ├── index.js │ ├── js │ └── index.js │ ├── load.js │ ├── logo.svg │ ├── logo_profile_static_avatar.svg │ ├── manifest.json │ ├── matrix.js │ ├── olm.js │ ├── olm.wasm │ ├── olm_legacy.js │ ├── personal_site.svg │ ├── profile_image.svg │ ├── profile_page.svg │ ├── security-camera.png │ ├── static │ ├── css │ │ ├── main.690c4373.css │ │ └── main.690c4373.css.map │ └── js │ │ ├── main.dd218d9e.js │ │ ├── main.dd218d9e.js.LICENSE.txt │ │ └── main.dd218d9e.js.map │ ├── testvideo1.mp4 │ ├── undraw_security_on_re_e491.svg │ ├── user-logo.png │ ├── videoblocks-short-dynamik-clip-zoom-to-glass-with-matcha-latte_svv3mxtcm__fb4b8b0ed6b33e9c30afdd0a1e5afd6d__P360.mp4 │ └── wave-haikei.svg ├── docs ├── _config.yml └── index.md ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── 403 Error Forbidden-bro.svg ├── 404 Error-bro.svg ├── Mobile login-cuate-green.svg ├── Mobile login-cuate.svg ├── browser-matrix.js ├── browser-matrix.js.map ├── circle-scatter-haikei.svg ├── circle-scatter-haikei1.svg ├── configuration-gear-options-svgrepo-com.svg ├── favicon.ico ├── icons8-tiger-96.png ├── index.html ├── index.js ├── load.js ├── logo.svg ├── logo_profile_static_avatar.svg ├── manifest.json ├── matrix.js ├── olm.js ├── olm.wasm ├── olm_legacy.js ├── personal_site.svg ├── profile_cover_page.svg ├── profile_image.svg ├── profile_page.svg ├── security-camera.png ├── setting_page.svg ├── testvideo1.mp4 ├── undraw_security_on_re_e491.svg ├── user-logo.png ├── videoblocks-short-dynamik-clip-zoom-to-glass-with-matcha-latte_svv3mxtcm__fb4b8b0ed6b33e9c30afdd0a1e5afd6d__P360.mp4 └── wave-haikei.svg ├── src ├── App.css ├── App.js ├── App.test.js ├── actions │ └── profile.js ├── components │ ├── BottomNavigationBar │ │ └── index.js │ ├── Footer │ │ ├── Footer.js │ │ ├── index.js │ │ └── style.css │ ├── Header │ │ ├── Header.js │ │ ├── index.js │ │ └── style.css │ ├── Login │ │ ├── index.js │ │ ├── logIn.js │ │ └── style.css │ ├── ModalPopUp │ │ └── index.js │ ├── ModalRequest │ │ └── index.js │ ├── Navbar │ │ └── index.js │ ├── TopNavBar │ │ └── index.js │ └── TopNavigationBar │ │ └── index.js ├── constants │ └── actionTypes.js ├── context │ └── auth.js ├── hooks │ └── useMatrixClient.js ├── index.css ├── index.js ├── load.js ├── navigation │ └── index.js ├── pages │ ├── Homepage.js │ ├── Page403.js │ ├── Page404.js │ ├── Profilepage.js │ ├── Requests.js │ ├── Roompage.js │ ├── Settingpage.js │ └── styles.css ├── reducers │ └── profile.js ├── reportWebVitals.js ├── serviceWorker.js ├── setupTests.js ├── store │ └── index.js ├── styles │ ├── index.js │ └── main.css └── utils │ └── index.js └── tailwind.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5502 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Golder Tiger Capstone team 2022 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open Source Video Security Camera 2 | 3 | ### Portland State University Capstone Project 2022 4 | 5 | Project Link: https://securitycameracapstone.netlify.app 6 | 7 | ## Demo Link: 8 | 9 | Youtube: https://www.youtube.com/watch?v=v_Zcuo2PaQs 10 | 11 | ## Table of content: 12 | 13 | - [Project Overview](#project-overview) 14 | - [Screenshots](#screenshot) 15 | - [Functionality](#functionality) 16 | - [Technologies](#technologies) 17 | - [Setup](#setup) 18 | - [Status](#status) 19 | - [Credits](#credits) 20 | - [License](#license) 21 | 22 | ## Screenshot 23 | 24 | ![1](https://user-images.githubusercontent.com/20541596/171967227-24df30fc-bba2-41f8-b977-ebc6584b72f6.PNG) 25 | 26 | ## Project Overview 27 | We are creating a way to connect a motion-based security camera system to a remote application of our creation using the Matrix chatroom protocol. The reason why consumer security solutions do not always guarantee who has access to your data is that they do not always provide complete security. Consumer security camera systems often store images and videos on the servers of the company providing the system, sending video through their servers. You have no control over their security practices. With our solution, you can host the server yourself, and have end-to-end encryption giving you complete control over your data. 28 | 29 | Our system has two main parts: the camera hub software, and the phone client. The camera hub uses MotionEye, an open-source solution to manage security cameras, and their recordings on a Linux-based system. The second part of the app let users be notified when there are motion detection events, and provide images and videos to their phone from the security cameras. The communication between the two takes place using a Matrix chatroom protocol. Users can choose to host the Matrix server themselves, or use any hosting services as they please. 30 | 31 | ## Functionality 32 | ### Camera Hub: 33 | - Use MotionEye as camera manager. 34 | - Take snapshots, and record video. 35 | - Upload recorded images and videos to the Matrix server. 36 | - Accept commands that appear on the Matrix server. 37 | - Accept commands to get a current screenshot. 38 | - Run as a service/daemon on a Linux computer. 39 | - Detect camera configuration and send notifications to Matrix server. 40 | - Has an install script to make setup easier, along with manual instructions. 41 | - Save configurations, so the hub will start back up upon an unexpected reboot. 42 | 43 | ### Front End 44 | #### Features: 45 | - The authentication pages allow users to log in and log out. 46 | - The layout to create or delete the Matrix Room. 47 | - Showing the thumbnail as receiving the motion detect notifications from the camera. 48 | - Requesting and showing the recording videos. 49 | - Adding and removing other users to the Matrix room. 50 | - Creating and deleting rooms. 51 | - Changing avatar. 52 | - Banning or Unbanning users in a room. 53 | 54 | ## Technologies 55 | 56 | `HTLM`,`CSS`,`bootstrap`,`React`,`tailwindCSS`,`NodeJS`,`Matrix SDK`,`Marix-react SDK` 57 | 58 | `MotionEye`, `Matrix NIO`, `Raspberry Pi` 59 | 60 | ## Setup 61 | 62 | ### Instruction on how to setup Camera Controller can be found here: 63 | 64 | https://github.com/Open-Source-Videos/Matrix-surveillance-camera-controller 65 | 66 | ### Run the app in the development mode 67 | 68 | Download or clone the repository. 69 | 70 | Open your terminal, Then run: 71 | 72 | ```bash 73 | npm install 74 | npm start 75 | ``` 76 | or 77 | ```bash 78 | yarn 79 | yarn start 80 | ``` 81 | 82 | ## Status 83 | 84 | - Version 1.0 85 | 86 | ## Credits 87 | List of contributors: 88 | - [Tri Le](a@pdx.edu) 89 | - [Phuoc Nguyen](a@pdx.edu) 90 | - [Thiep Tran](a@pdx.edu) 91 | - [Minh Nguyen](a@pdx.edu) 92 | - [Tuan Dinh](a@pdx.edu) 93 | - [Michael Fulton](a@pdx.edu) 94 | - [Henry Nguyen](a@pdx.edu) 95 | 96 | ## License 97 | Golden Tiger Capstone Team 2022, Portland State University 2022 98 | 99 | Licensed under the [MIT License](LICENSE) 100 | -------------------------------------------------------------------------------- /cordova/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | 19 | .DS_Store 20 | 21 | # Generated by package manager 22 | node_modules/ 23 | 24 | # Generated by Cordova 25 | /plugins/ 26 | /platforms/ 27 | -------------------------------------------------------------------------------- /cordova/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | HelloCordova 4 | Sample Apache Cordova App 5 | 6 | Apache Cordova Team 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /cordova/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "io.cordova.hellocordova", 3 | "displayName": "HelloCordova", 4 | "version": "1.0.0", 5 | "description": "A sample Apache Cordova application that responds to the deviceready event.", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [ 11 | "ecosystem:cordova" 12 | ], 13 | "author": "Apache Cordova Team", 14 | "license": "Apache-2.0", 15 | "devDependencies": { 16 | "cordova-ios": "^6.2.0" 17 | }, 18 | "cordova": { 19 | "platforms": [ 20 | "ios" 21 | ] 22 | } 23 | } -------------------------------------------------------------------------------- /cordova/www/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.css": "./static/css/main.690c4373.css", 4 | "main.js": "./static/js/main.dd218d9e.js", 5 | "index.html": "./index.html", 6 | "main.690c4373.css.map": "./static/css/main.690c4373.css.map", 7 | "main.dd218d9e.js.map": "./static/js/main.dd218d9e.js.map" 8 | }, 9 | "entrypoints": [ 10 | "static/css/main.690c4373.css", 11 | "static/js/main.dd218d9e.js" 12 | ] 13 | } -------------------------------------------------------------------------------- /cordova/www/circle-scatter-haikei.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cordova/www/circle-scatter-haikei1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cordova/www/css/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | * { 20 | -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */ 21 | } 22 | 23 | body { 24 | -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */ 25 | -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */ 26 | -webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */ 27 | background-color:#E4E4E4; 28 | background-image:linear-gradient(to bottom, #A7A7A7 0%, #E4E4E4 51%); 29 | font-family: system-ui, -apple-system, -apple-system-font, 'Segoe UI', 'Roboto', sans-serif; 30 | font-size:12px; 31 | height:100vh; 32 | margin:0px; 33 | padding:0px; 34 | /* Padding to avoid the "unsafe" areas behind notches in the screen */ 35 | padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px) env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px); 36 | text-transform:uppercase; 37 | width:100%; 38 | } 39 | 40 | /* Portrait layout (default) */ 41 | .app { 42 | background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */ 43 | position:absolute; /* position in the center of the screen */ 44 | left:50%; 45 | top:50%; 46 | height:50px; /* text area height */ 47 | width:225px; /* text area width */ 48 | text-align:center; 49 | padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */ 50 | margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */ 51 | /* offset horizontal: half of text area width */ 52 | } 53 | 54 | /* Landscape layout (with min-width) */ 55 | @media screen and (min-aspect-ratio: 1/1) and (min-width:400px) { 56 | .app { 57 | background-position:left center; 58 | padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */ 59 | margin:-90px 0px 0px -198px; /* offset vertical: half of image height */ 60 | /* offset horizontal: half of image width and text area width */ 61 | } 62 | } 63 | 64 | h1 { 65 | font-size:24px; 66 | font-weight:normal; 67 | margin:0px; 68 | overflow:visible; 69 | padding:0px; 70 | text-align:center; 71 | } 72 | 73 | .event { 74 | border-radius:4px; 75 | color:#FFFFFF; 76 | font-size:12px; 77 | margin:0px 30px; 78 | padding:2px 0px; 79 | } 80 | 81 | .event.listening { 82 | background-color:#333333; 83 | display:block; 84 | } 85 | 86 | .event.received { 87 | background-color:#4B946A; 88 | display:none; 89 | } 90 | 91 | #deviceready.ready .event.listening { display: none; } 92 | #deviceready.ready .event.received { display: block; } 93 | 94 | @keyframes fade { 95 | from { opacity: 1.0; } 96 | 50% { opacity: 0.4; } 97 | to { opacity: 1.0; } 98 | } 99 | 100 | .blink { 101 | animation:fade 3000ms infinite; 102 | -webkit-animation:fade 3000ms infinite; 103 | } 104 | 105 | 106 | @media screen and (prefers-color-scheme: dark) { 107 | body { 108 | background-image:linear-gradient(to bottom, #585858 0%, #1B1B1B 51%); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /cordova/www/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/favicon.ico -------------------------------------------------------------------------------- /cordova/www/icons8-tiger-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/icons8-tiger-96.png -------------------------------------------------------------------------------- /cordova/www/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/img/logo.png -------------------------------------------------------------------------------- /cordova/www/index.html: -------------------------------------------------------------------------------- 1 | Open Source Surveillance Camera
-------------------------------------------------------------------------------- /cordova/www/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | // Wait for the deviceready event before using any of Cordova's device APIs. 21 | // See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready 22 | document.addEventListener('deviceready', onDeviceReady, false); 23 | 24 | function onDeviceReady() { 25 | // Cordova is now initialized. Have fun! 26 | 27 | console.log('Running cordova-' + cordova.platformId + '@' + cordova.version); 28 | document.getElementById('deviceready').classList.add('ready'); 29 | } 30 | -------------------------------------------------------------------------------- /cordova/www/js/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | // Wait for the deviceready event before using any of Cordova's device APIs. 21 | // See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready 22 | document.addEventListener('deviceready', onDeviceReady, false); 23 | 24 | function onDeviceReady() { 25 | // Cordova is now initialized. Have fun! 26 | 27 | console.log('Running cordova-' + cordova.platformId + '@' + cordova.version); 28 | document.getElementById('deviceready').classList.add('ready'); 29 | } 30 | -------------------------------------------------------------------------------- /cordova/www/load.js: -------------------------------------------------------------------------------- 1 | window.Olm = Olm; 2 | window.matrixClient = matrixcs; 3 | -------------------------------------------------------------------------------- /cordova/www/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cordova/www/logo_profile_static_avatar.svg: -------------------------------------------------------------------------------- 1 | profile pic -------------------------------------------------------------------------------- /cordova/www/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /cordova/www/olm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/olm.wasm -------------------------------------------------------------------------------- /cordova/www/personal_site.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cordova/www/profile_image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /cordova/www/profile_page.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cordova/www/security-camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/security-camera.png -------------------------------------------------------------------------------- /cordova/www/static/js/main.dd218d9e.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | Copyright (c) 2018 Jed Watson. 3 | Licensed under the MIT License (MIT), see 4 | http://jedwatson.github.io/classnames 5 | */ 6 | 7 | /** 8 | * @license React 9 | * react-dom.production.min.js 10 | * 11 | * Copyright (c) Facebook, Inc. and its affiliates. 12 | * 13 | * This source code is licensed under the MIT license found in the 14 | * LICENSE file in the root directory of this source tree. 15 | */ 16 | 17 | /** 18 | * @license React 19 | * react-jsx-runtime.production.min.js 20 | * 21 | * Copyright (c) Facebook, Inc. and its affiliates. 22 | * 23 | * This source code is licensed under the MIT license found in the 24 | * LICENSE file in the root directory of this source tree. 25 | */ 26 | 27 | /** 28 | * @license React 29 | * react.production.min.js 30 | * 31 | * Copyright (c) Facebook, Inc. and its affiliates. 32 | * 33 | * This source code is licensed under the MIT license found in the 34 | * LICENSE file in the root directory of this source tree. 35 | */ 36 | 37 | /** 38 | * @license React 39 | * scheduler.production.min.js 40 | * 41 | * Copyright (c) Facebook, Inc. and its affiliates. 42 | * 43 | * This source code is licensed under the MIT license found in the 44 | * LICENSE file in the root directory of this source tree. 45 | */ 46 | 47 | /** @license React v16.13.1 48 | * react-is.production.min.js 49 | * 50 | * Copyright (c) Facebook, Inc. and its affiliates. 51 | * 52 | * This source code is licensed under the MIT license found in the 53 | * LICENSE file in the root directory of this source tree. 54 | */ 55 | 56 | /** @license React v17.0.2 57 | * react-is.production.min.js 58 | * 59 | * Copyright (c) Facebook, Inc. and its affiliates. 60 | * 61 | * This source code is licensed under the MIT license found in the 62 | * LICENSE file in the root directory of this source tree. 63 | */ 64 | -------------------------------------------------------------------------------- /cordova/www/testvideo1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/testvideo1.mp4 -------------------------------------------------------------------------------- /cordova/www/undraw_security_on_re_e491.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cordova/www/user-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/user-logo.png -------------------------------------------------------------------------------- /cordova/www/videoblocks-short-dynamik-clip-zoom-to-glass-with-matcha-latte_svv3mxtcm__fb4b8b0ed6b33e9c30afdd0a1e5afd6d__P360.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/cordova/www/videoblocks-short-dynamik-clip-zoom-to-glass-with-matcha-latte_svv3mxtcm__fb4b8b0ed6b33e9c30afdd0a1e5afd6d__P360.mp4 -------------------------------------------------------------------------------- /cordova/www/wave-haikei.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | ## Welcome to GitHub Pages 2 | 3 | You can use the [editor on GitHub](https://github.com/TuanDinh140194/camera_security/edit/main/docs/index.md) to maintain and preview the content for your website in Markdown files. 4 | 5 | Whenever you commit to this repository, GitHub Pages will run [Jekyll](https://jekyllrb.com/) to rebuild the pages in your site, from the content in your Markdown files. 6 | 7 | ### Markdown 8 | 9 | Markdown is a lightweight and easy-to-use syntax for styling your writing. It includes conventions for 10 | 11 | ```markdown 12 | Syntax highlighted code block 13 | 14 | # Header 1 15 | ## Header 2 16 | ### Header 3 17 | 18 | - Bulleted 19 | - List 20 | 21 | 1. Numbered 22 | 2. List 23 | 24 | **Bold** and _Italic_ and `Code` text 25 | 26 | [Link](url) and ![Image](src) 27 | ``` 28 | 29 | For more details see [Basic writing and formatting syntax](https://docs.github.com/en/github/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax). 30 | 31 | ### Jekyll Themes 32 | 33 | Your Pages site will use the layout and styles from the Jekyll theme you have selected in your [repository settings](https://github.com/TuanDinh140194/camera_security/settings/pages). The name of this theme is saved in the Jekyll `_config.yml` configuration file. 34 | 35 | ### Support or Contact 36 | 37 | Having trouble with Pages? Check out our [documentation](https://docs.github.com/categories/github-pages-basics/) or [contact support](https://support.github.com/contact) and we’ll help you sort it out. 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "capstone-frontend-web", 3 | "version": "0.1.0", 4 | "private": true, 5 | 6 | "dependencies": { 7 | "@headlessui/react": "^1.6.0", 8 | "@heroicons/react": "^1.0.6", 9 | "@react-icons/all-files": "^4.1.0", 10 | "@tailwindcss/forms": "^0.5.1", 11 | "@testing-library/jest-dom": "^5.16.4", 12 | "@testing-library/react": "^13.0.1", 13 | "@testing-library/user-event": "^13.5.0", 14 | "add": "^2.0.6", 15 | "aos": "^2.3.4", 16 | "axios": "^0.26.1", 17 | "bootstrap": "^5.1.3", 18 | "clsx": "^1.1.1", 19 | "flowbite": "^1.4.2", 20 | "ionicons": "^6.0.1", 21 | "react": "^18.0.0", 22 | "react-bootstrap": "^0.32.4", 23 | "react-date-picker": "^8.4.0", 24 | "react-datetime-picker": "^3.5.0", 25 | "react-dom": "^18.0.0", 26 | "react-icons": "^4.3.1", 27 | "react-redux": "^7.2.8", 28 | "react-router": "^5.2.0", 29 | "react-router-dom": "^5.2.0", 30 | "react-scripts": "^5.0.1", 31 | "redux": "^4.1.2", 32 | "redux-thunk": "^2.4.1", 33 | "styled-components": "^5.3.5", 34 | "svg-loaders": "^0.2.0", 35 | "svg-loaders-react": "^2.2.1", 36 | "web-vitals": "^2.1.4" 37 | }, 38 | 39 | "scripts": { 40 | "start": "react-scripts start", 41 | "predeploy": "npm run build", 42 | "deploy": "gh-pages -d build", 43 | "build": "react-scripts build", 44 | "test": "react-scripts test", 45 | "eject": "react-scripts eject" 46 | }, 47 | "eslintConfig": { 48 | "extends": [ 49 | "react-app", 50 | "react-app/jest" 51 | ] 52 | }, 53 | "browserslist": { 54 | "production": [ 55 | ">0.2%", 56 | "not dead", 57 | "not op_mini all" 58 | ], 59 | "development": [ 60 | "last 1 chrome version", 61 | "last 1 firefox version", 62 | "last 1 safari version" 63 | ] 64 | }, 65 | "devDependencies": { 66 | "autoprefixer": "^10.4.4", 67 | "gh-pages": "^4.0.0", 68 | "postcss": "^8.4.12", 69 | "tailwindcss": "^3.0.24" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/circle-scatter-haikei.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/circle-scatter-haikei1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/configuration-gear-options-svgrepo-com.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/public/favicon.ico -------------------------------------------------------------------------------- /public/icons8-tiger-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/public/icons8-tiger-96.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | 17 | Open Source Surveillance Camera 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /public/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | // Wait for the deviceready event before using any of Cordova's device APIs. 21 | // See https://cordova.apache.org/docs/en/latest/cordova/events/events.html#deviceready 22 | document.addEventListener('deviceready', onDeviceReady, false); 23 | 24 | function onDeviceReady() { 25 | // Cordova is now initialized. Have fun! 26 | 27 | console.log('Running cordova-' + cordova.platformId + '@' + cordova.version); 28 | document.getElementById('deviceready').classList.add('ready'); 29 | } 30 | -------------------------------------------------------------------------------- /public/load.js: -------------------------------------------------------------------------------- 1 | window.Olm = Olm; 2 | window.matrixClient = matrixcs; 3 | -------------------------------------------------------------------------------- /public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/logo_profile_static_avatar.svg: -------------------------------------------------------------------------------- 1 | profile pic -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/olm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/public/olm.wasm -------------------------------------------------------------------------------- /public/personal_site.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/profile_image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /public/profile_page.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/security-camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/public/security-camera.png -------------------------------------------------------------------------------- /public/setting_page.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/testvideo1.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/public/testvideo1.mp4 -------------------------------------------------------------------------------- /public/undraw_security_on_re_e491.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/user-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/public/user-logo.png -------------------------------------------------------------------------------- /public/videoblocks-short-dynamik-clip-zoom-to-glass-with-matcha-latte_svv3mxtcm__fb4b8b0ed6b33e9c30afdd0a1e5afd6d__P360.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Open-Source-Videos/Matrix-surveillant-camera-security-web/46ae319c33d5220d404eb854368df981a41f19ed/public/videoblocks-short-dynamik-clip-zoom-to-glass-with-matcha-latte_svv3mxtcm__fb4b8b0ed6b33e9c30afdd0a1e5afd6d__P360.mp4 -------------------------------------------------------------------------------- /public/wave-haikei.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, {useEffect} from 'react'; 7 | import { connect } from 'react-redux'; 8 | // import Header from './components/Header/Header'; 9 | // import Footer from './components/Footer'; 10 | import Navigation from './navigation'; 11 | import { getStore } from './utils'; 12 | import { ActionCreators } from './actions/profile'; 13 | import AOS from 'aos'; 14 | import 'aos/dist/aos.css'; 15 | 16 | // import { GlobalContext, initialGlobalState} from './hooks/useMatrixClient' 17 | import './styles'; 18 | 19 | function App() { 20 | // const [state, setState] = useState({ 21 | // ...initialGlobalState, 22 | // update, 23 | // }); 24 | 25 | // function update(data) { 26 | // setState(Object.assign({}, state, data)); 27 | // } 28 | 29 | useEffect(() => { 30 | AOS.init(); 31 | AOS.refresh(); 32 | const user = getStore('user'); 33 | if (user) { 34 | this.props.dispatch(ActionCreators.login(user)); 35 | } 36 | }, []); 37 | return ( 38 |
39 | 40 |
41 | ); 42 | } 43 | 44 | // 45 | // 46 | 47 | // class App extends React.Component { 48 | // componentDidMount() { 49 | // const user = getStore('user') 50 | // if (user) { 51 | // this.props.dispatch(ActionCreators.login(user)); 52 | // } 53 | // } 54 | // render() { 55 | // return ( 56 | //
57 | // 58 | //
59 | // ) 60 | // } 61 | // } 62 | 63 | const mapStateToProps = (state) => { 64 | return { 65 | profile: state.user.profile, 66 | }; 67 | }; 68 | 69 | export default connect(mapStateToProps)(App); 70 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import { render, screen } from '@testing-library/react'; 7 | import App from './App'; 8 | 9 | test('renders learn react link', () => { 10 | render(); 11 | const linkElement = screen.getByText(/learn react/i); 12 | expect(linkElement).toBeInTheDocument(); 13 | }); 14 | -------------------------------------------------------------------------------- /src/actions/profile.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | import { Types } from '../constants/actionTypes'; 6 | 7 | export const ActionCreators = { 8 | 9 | addProfile: (user) => ({ type: Types.ADD_USER, payload: { user } }), 10 | 11 | updateProfileImage: (image) => ({ type: Types.UPDATE_PROFILE_PICTURE, payload: { image } }), 12 | 13 | updateProfile: (user) => ({ type: Types.UPDATE_USER, payload: { user } }), 14 | 15 | formSubmittionStatus: (status) => ({ type: Types.FORM_SUBMITION_STATUS, payload: { status }}), 16 | 17 | login: (user) => ({ type: Types.LOGIN, payload: { user } }) 18 | } -------------------------------------------------------------------------------- /src/components/BottomNavigationBar/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, { 7 | useState, 8 | useEffect 9 | } from 'react'; 10 | import useMatrixClient from '../../hooks/useMatrixClient'; 11 | import { 12 | useHistory, 13 | useLocation 14 | } from "react-router-dom"; 15 | import { clearState } from '../../pages/Homepage'; 16 | import { clearAllStates } from "../../pages/Requests"; 17 | import { 18 | HomeIcon, 19 | AnnotationIcon, 20 | CogIcon 21 | } from '@heroicons/react/outline' 22 | 23 | 24 | const BottomNavigationBar = () => { 25 | const history = useHistory(); 26 | const { 27 | isLogin, 28 | getAvatar, 29 | testLogin, 30 | } = useMatrixClient(); 31 | const location = useLocation(); 32 | const { pathname } = location; 33 | const splitLocation = pathname.split("/"); 34 | 35 | const handleRouter = (e, target_link) => { 36 | e.preventDefault(); 37 | //console.log("TARGET:", e.target) 38 | //let link = e.target.href; 39 | //console.log("LINK: ", link); 40 | 41 | console.log("LINK: ", target_link); 42 | 43 | //let target = window.location.origin + "/"; 44 | //console.log("TARGET: ", target) 45 | //let p = target_link?.replace(target, ""); 46 | //console.log("P: ", p) 47 | //history.push(p); 48 | history.push(target_link); 49 | } 50 | 51 | const [avatar, setAvatar] = useState(null); 52 | const [yesLogin, setYesLogin] = useState(false); 53 | 54 | useEffect(() => { 55 | (async () => { 56 | if (isLogin() === false) { 57 | console.log('Run test login'); 58 | setYesLogin(await testLogin()); 59 | } 60 | setTimeout(() => { 61 | setYesLogin(isLogin()); 62 | const get_avatar = () => { 63 | (async () => { 64 | try { 65 | let profileAvatar = await getAvatar(); 66 | if (profileAvatar === null || profileAvatar === '') { 67 | setAvatar('logo_profile_static_avatar.svg'); 68 | } else { 69 | setAvatar(profileAvatar); 70 | } 71 | } catch (e) { 72 | console.log('error', e); 73 | setAvatar(null); 74 | } 75 | })(); 76 | }; 77 | 78 | get_avatar(); 79 | }, 500); 80 | })(); 81 | }, [avatar, isLogin, testLogin]); 82 | 83 | 84 | return ( 85 |
89 | 147 |
148 | ) 149 | } 150 | 151 | export default BottomNavigationBar; 152 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, { Component } from 'react'; 7 | import './style.css'; 8 | 9 | export class Footer extends Component { 10 | render() { 11 | return ( 12 | 13 | ) 14 | } 15 | } 16 | 17 | export default Footer; -------------------------------------------------------------------------------- /src/components/Footer/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import Footer from './Footer'; 7 | 8 | export default Footer; -------------------------------------------------------------------------------- /src/components/Footer/style.css: -------------------------------------------------------------------------------- 1 | footer { 2 | position: fixed; 3 | bottom: 0; 4 | left: 0; 5 | bottom: 0; 6 | width: 100%; 7 | min-height: 8vh; 8 | display: flex !important; 9 | align-items: center; 10 | justify-content: center; 11 | background-color: #daf5ff; 12 | background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%); 13 | } -------------------------------------------------------------------------------- /src/components/Header/Header.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, { Component } from 'react'; 7 | import './style.css'; 8 | 9 | export class Header extends Component { 10 | render() { 11 | return ( 12 |
OpenCamera-Capstone
13 | ) 14 | } 15 | } 16 | 17 | export default Header; -------------------------------------------------------------------------------- /src/components/Header/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import Header from './Header'; 7 | 8 | export default Header; -------------------------------------------------------------------------------- /src/components/Header/style.css: -------------------------------------------------------------------------------- 1 | /*header { 2 | min-height: 8vh; 3 | display: flex !important; 4 | align-items: center; 5 | justify-content: center; 6 | color: #282c34; 7 | background-color: #daf5ff; 8 | border-bottom: 1px solid #daf5ff; 9 | background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%); 10 | }*/ -------------------------------------------------------------------------------- /src/components/Login/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import logIn from "./logIn"; 7 | 8 | export default logIn; -------------------------------------------------------------------------------- /src/components/Login/style.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | .Login{ 4 | margin: 0 auto; 5 | margin-top: 70px; 6 | max-width: 400px; 7 | padding: 40px 40px; 8 | 9 | 10 | } 11 | #button{ 12 | background-color: #000000 !important; 13 | margin-top: 30px; 14 | } 15 | #sign_up, #problem { 16 | color: red; 17 | font-weight: bold; 18 | text-decoration: underline; 19 | } 20 | 21 | #header, figcaption{ 22 | text-align: center; 23 | font-weight: bold; 24 | padding-bottom: 50px; 25 | } 26 | 27 | #homeserver1{ 28 | font-weight: bold; 29 | } 30 | 31 | #mainImg{ 32 | margin-top: -100px; 33 | text-align: center !important; 34 | align-items: center !important; 35 | } 36 | 37 | img{ 38 | display: inline !important; 39 | } 40 | 41 | #helpBlock{ 42 | color: red; 43 | } 44 | 45 | /*body { 46 | background-color: #a3e635 !important; 47 | background-image: linear-gradient(120deg, #C2E91C 0%, #96e6a1 100%); 48 | }*/ 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/components/ModalPopUp/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React from "react"; 7 | import '../../index.css'; 8 | 9 | export const ModalPopUp = ({onClickPause, videoURL}) => { 10 | return ( 11 | <> 12 |
13 |
14 |
15 |
16 | 26 |
27 | 28 |
29 |
33 | 44 |
45 |
46 |
47 |
48 |
49 |
50 | 51 | ); 52 | } -------------------------------------------------------------------------------- /src/components/ModalRequest/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import { Dialog } from '@headlessui/react' 7 | 8 | export const ModalRequest = ({ 9 | isOpen, 10 | onClickClose, 11 | dialogTitle, 12 | dialogBody, 13 | requestAction 14 | }) => { 15 | 16 | 17 | const bg_gradient = " bg-gradient-to-r from-orange-400 to-rose-400 hover:bg-orange-200 "; 18 | const btn_class_primary= "m-2 inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gradient-to-r from-orange-400 to-rose-400 hover:bg-orange-100 text-sm font-medium text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500" 19 | const btn_class_outline = bg_gradient + " m-2 relative inline-flex items-center justify-center p-0.5 overflow-hidden text-sm font-medium text-orange-500 rounded-lg group group-hover:from-orange-400 group-hover:to-rose-400 hover:text-white focus:ring-4 focus:outline-none focus:ring-rose-200 " 20 | const btn_text_span_outline = "w-full relative p-2 transition-all ease-in duration-75 bg-white hover:bg-gradient-to-r from-orange-400 to-rose-400 rounded-md group-hover:bg-opacity-0" 21 | 22 | return ( 23 | 28 | 29 |
30 | 31 | 32 | 33 | {dialogTitle} 34 | 35 | 36 | <> 37 | {dialogBody} 38 | 39 | 40 |
41 | 49 | 50 | 56 |
57 |
58 |
59 | ) 60 | } -------------------------------------------------------------------------------- /src/components/Navbar/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React from "react" 7 | import { useHistory } from "react-router-dom"; 8 | 9 | 10 | export const Navbar = () => { 11 | const history = useHistory(); 12 | 13 | const handleRouter = (e) => { 14 | e.preventDefault(); 15 | let link = e.target.href; 16 | let target = window.location.origin + "/"; 17 | let p = link.replace(target, ""); 18 | history.push(p); 19 | } 20 | 21 | const tabItem = { 22 | position: "absolute", 23 | inset: "auto auto 0px 0px", 24 | margin: "0px", 25 | transform: "translate(1284px, 976px)" 26 | }; 27 | 28 | return ( 29 | 80 | ) 81 | } -------------------------------------------------------------------------------- /src/components/TopNavBar/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, { 7 | useState 8 | } from "react"; 9 | import { useHistory, useLocation } from "react-router-dom"; 10 | import useMatrixClient from "../../hooks/useMatrixClient"; 11 | import { Transition } from "@headlessui/react"; 12 | import {clearState } from '../../pages/Homepage'; 13 | 14 | const TopNavBar = () => { 15 | const [isOpen, setIsOpen] = useState(false); 16 | const history = useHistory(); 17 | const { isLogin, logoutMatrixServer } = useMatrixClient(); 18 | const location = useLocation(); 19 | const { pathname } = location; 20 | const splitLocation = pathname.split("/"); 21 | 22 | const handleRouter = (e) => { 23 | e.preventDefault(); 24 | let link = e.target.href; 25 | let target = window.location.origin + "/"; 26 | let p = link.replace(target, ""); 27 | history.push(p); 28 | } 29 | 30 | const handleLogout = () => { 31 | logoutMatrixServer(); 32 | console.log("=======================") 33 | console.log("IS LOGIN: ", isLogin()); 34 | console.log("=======================") 35 | history.push("/login"); 36 | clearState(); 37 | } 38 | 39 | const tabItem = "text-gray-800 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium text-decoration-none" 40 | const tabItemMobile = "hover:bg-gray-700 text-gray-800 hover:text-white block px-3 py-2 rounded-md text-base font-medium text-decoration-none" 41 | 42 | return ( 43 |
44 | 204 |
205 | ); 206 | } 207 | 208 | export default TopNavBar; 209 | -------------------------------------------------------------------------------- /src/components/TopNavigationBar/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, { 7 | useState, 8 | useEffect, 9 | Fragment 10 | } from 'react'; 11 | import useMatrixClient from '../../hooks/useMatrixClient'; 12 | import { 13 | Popover, 14 | Transition 15 | } from '@headlessui/react' 16 | import { 17 | useHistory, 18 | useLocation 19 | } from "react-router-dom"; 20 | import { clearState } from '../../pages/Homepage'; 21 | import { clearAllStates } from "../../pages/Requests"; 22 | import { 23 | MenuIcon, 24 | XIcon, 25 | } from '@heroicons/react/outline' 26 | 27 | 28 | const TopNavigationBar = () => { 29 | const history = useHistory(); 30 | const { 31 | isLogin, 32 | logoutMatrixServer, 33 | getAvatar, 34 | testLogin, 35 | } = useMatrixClient(); 36 | const location = useLocation(); 37 | const { pathname } = location; 38 | const splitLocation = pathname.split("/"); 39 | 40 | const handleRouter = (link,e) => { 41 | e.preventDefault(); 42 | //let link = e.target.href; 43 | let target = window.location.origin + "/"; 44 | console.log('link=',link); 45 | let p = link?.replace(target, ""); 46 | history.push(p); 47 | } 48 | 49 | const handleLogout = () => { 50 | logoutMatrixServer(); 51 | history.push("/login"); 52 | clearState(); 53 | clearAllStates(); 54 | } 55 | 56 | const tabItem = "text-gray-800 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium text-decoration-none"; 57 | const tabItemMenu = "-m-3 p-3 flex items-center rounded-md hover:bg-gray-50 text-decoration-none" 58 | const tabItemMenuText = "ml-3 text-base font-medium text-gray-900 text-decoration"; 59 | 60 | const [avatar, setAvatar] = useState(null); 61 | const [yesLogin, setYesLogin] = useState(false); 62 | 63 | useEffect(() => { 64 | (async () => { 65 | 66 | if (isLogin() === false) { 67 | console.log('Run test login'); 68 | setYesLogin(await testLogin()); 69 | } 70 | 71 | setTimeout(() => { 72 | setYesLogin(isLogin()); 73 | const get_avatar = () => { 74 | (async () => { 75 | try { 76 | let profileAvatar = await getAvatar(); 77 | if (profileAvatar === null || profileAvatar === '') { 78 | setAvatar('logo_profile_static_avatar.svg'); 79 | } else { 80 | setAvatar(profileAvatar); 81 | } 82 | } catch (e) { 83 | console.log('error', e); 84 | setAvatar(null); 85 | } 86 | })(); 87 | }; 88 | 89 | get_avatar(); 90 | }, 500); 91 | })(); 92 | }, [avatar, isLogin, testLogin, getAvatar]); 93 | 94 | 95 | return ( 96 | 97 |
98 |
99 |
100 | 105 | Logo 110 | OpenCamera 111 | 112 |
113 | 114 |
115 | 116 | Open menu 117 | 119 |
120 | 121 | 122 | { handleRouter("/homepage",e);} } 126 | > 127 | Homepage 128 | 129 | 130 | { handleRouter("/requests",e);} } 134 | > 135 | Requests 136 | 137 | 138 | { handleRouter("/profile",e);} } 142 | > 143 | Profile 144 | 145 | 146 | {/*{ handleRouter("/setting",e);} } 150 | > 151 | Settings 152 | */} 153 | 154 | 155 |
156 | 163 | {/* isLogin() ? (*/ 164 | 171 | /*) : ( 172 | <> 173 | )*/} 174 |
175 |
176 |
177 | 178 | 187 | 188 |
189 |
190 |
191 |
192 | Logo 197 | OpenCamera 198 |
199 |
200 | 201 | Close menu 202 | 204 |
205 |
206 | 238 |
239 |
240 |
241 | 248 |
249 |
250 | {/* isLogin() ? (*/ 251 | 258 | /*) : ( 259 | <> 260 | )*/} 261 |
262 |
263 |
264 |
265 |
266 |
267 | ) 268 | } 269 | 270 | export default TopNavigationBar; 271 | -------------------------------------------------------------------------------- /src/constants/actionTypes.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | export const Types = { 7 | LOGIN: 'LOGIN', 8 | ADD_USER: 'ADD_USER', 9 | UPDATE_USER: 'UPDATE_USER', 10 | UPDATE_PROFILE_PICTURE: 'UPDATE_PROFILE_PICTURE', 11 | FORM_SUBMITION_STATUS: 'FORM_SUBMITION_STATUS' 12 | } -------------------------------------------------------------------------------- /src/context/auth.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import { createContext, useContext } from 'react'; 7 | 8 | export const AuthContext = createContext(); 9 | 10 | export function useAuth() { 11 | return useContext(AuthContext); 12 | } -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | body { 6 | margin: 0; 7 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 8 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 9 | sans-serif; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | background-color: #f9fafb !important; 13 | } 14 | 15 | code { 16 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 17 | } 18 | 19 | .shadow-neumorphism { 20 | /*border-radius: 20px; 21 | background: #ffffff; 22 | box-shadow: 5px 5px 6px #c4c4c4, 23 | -5px -5px 6px #ffffff;*/ 24 | border-radius: 20px; 25 | background: #ffffff; 26 | box-shadow: -5px -5px 23px #c4c4c4, 27 | 5px 5px 23px #ffffff; 28 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React from 'react'; 7 | import ReactDOM from 'react-dom'; 8 | import { Provider } from 'react-redux'; 9 | import configureStore from './store'; 10 | import App from './App'; 11 | import * as serviceWorker from './serviceWorker'; 12 | import 'flowbite'; 13 | 14 | const store = configureStore(); 15 | let startApp = () => { 16 | ReactDOM.render( 17 | 18 | 19 | 20 | 21 | , 22 | document.getElementById('root') 23 | ); 24 | } 25 | serviceWorker.unregister(); 26 | 27 | // If you want to start measuring performance in your app, pass a function 28 | // to log results (for example: reportWebVitals(console.log)) 29 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 30 | // reportWebVitals(); 31 | 32 | if(!window.cordova) { 33 | startApp() 34 | } else { 35 | document.addEventListener('deviceready', startApp, false) 36 | } -------------------------------------------------------------------------------- /src/load.js: -------------------------------------------------------------------------------- 1 | window.Olm = Olm; 2 | window.matrixClient = matrixcs; 3 | -------------------------------------------------------------------------------- /src/navigation/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, { 7 | Component 8 | } from 'react'; 9 | import { 10 | BrowserRouter as Router, 11 | Route, 12 | Switch 13 | } from 'react-router-dom'; 14 | import Login from '../components/Login'; 15 | import Home from '../pages/Homepage'; 16 | import Page404 from '../pages/Page404'; 17 | import Page403 from '../pages/Page403'; 18 | import { AuthContext } from '../context/auth'; 19 | import Profile from '../pages/Profilepage'; 20 | // import Setting from '../pages/Settingpage'; 21 | import Requests from '../pages/Requests'; 22 | import RoomPage from '../pages/Roompage'; 23 | 24 | class Navigation extends Component { 25 | render() { 26 | return ( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {/* */} 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ) 43 | } 44 | } 45 | 46 | export default Navigation; -------------------------------------------------------------------------------- /src/pages/Page403.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React, { useEffect, useState } from 'react'; 7 | import { Link } from 'react-router-dom'; 8 | var timeOut; 9 | const Page403 = () => { 10 | const [delayRender, setDelayRender] = useState(true); 11 | 12 | useEffect(() => { 13 | timeOut = setTimeout(() => { 14 | setDelayRender(false); 15 | }, 30000); 16 | 17 | return () => { 18 | clearTimeout(timeOut); 19 | }; 20 | }, []); 21 | return ( 22 | <> 23 | {delayRender ? ( 24 | <> 25 |
26 |
27 | Loading... 28 |
29 |
30 | 31 | ) : ( 32 |
33 | 403 Error 38 |
39 | 43 | Go to Home{' '} 44 | 45 |
46 |
47 | )} 48 | 49 | ); 50 | }; 51 | export default Page403; 52 | -------------------------------------------------------------------------------- /src/pages/Page404.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React from 'react'; 7 | import { Link } from 'react-router-dom'; 8 | import '../index.css'; 9 | 10 | class Page404 extends React.Component{ 11 | render(){ 12 | return ( 13 |
14 | 404 Error 19 |
20 | Go to Home 21 |
22 |
23 | ) 24 | } 25 | } 26 | export default Page404; -------------------------------------------------------------------------------- /src/pages/Roompage.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import { React, useState, useEffect } from 'react'; 7 | import useMatrixClient from '../hooks/useMatrixClient'; 8 | import Page403 from './Page403'; 9 | import { useHistory } from 'react-router-dom'; 10 | 11 | export var currentRoomID = null; 12 | export const setCurrentRoomID = (roomID) => { 13 | currentRoomID = roomID; 14 | }; 15 | 16 | const RoomPage = ({ 17 | roomList, 18 | avarta, 19 | displayName, 20 | createRoom, 21 | getHistory, 22 | }) => { 23 | const [showModal, setShowModal] = useState(false); 24 | const [roomName, setRoomName] = useState(null); 25 | const history = useHistory(); 26 | // const { createRoom, inviteUserToRoom } = useMatrixClient(); 27 | 28 | // useEffect(() => { 29 | // console.log('ROOM LIST: ', roomList); 30 | // }, [roomList]); 31 | 32 | const handleCreateRoom = async (e) => { 33 | // e.preventDefault(); 34 | const roomID = await createRoom(roomName); 35 | console.log('Create Room successfully', roomID); 36 | // const deviceID = await inviteUserToRoom( 37 | // '@test003:pdxinfosec.org', 38 | // roomID 39 | // ); 40 | // console.log('\n\n test devices:', deviceID); 41 | }; 42 | 43 | const listItems = roomList.map((number, index) => ( 44 |
  • { 47 | currentRoomID = number.roomId; 48 | history.push('/homepage'); 49 | getHistory(number.roomId, 20); 50 | localStorage.setItem('currentRoomID', currentRoomID); 51 | }} 52 | key={index} 53 | > 54 |
    55 |
    56 |
    {number.name}
    57 |
    58 |
    59 | Join 60 |
    61 |
    62 |
  • 63 | )); 64 | 65 | return ( 66 | <> 67 |
    68 |
    69 |
    70 |
    71 | Avatar 77 |
    78 |
    79 |
    80 |
    81 | 82 |
    83 |

    84 | {displayName} 85 |

    86 |
    87 | 88 |
    89 | 90 |
    91 | 92 |
    93 | 100 |
    101 | {showModal ? ( 102 | <> 103 |
    104 |
    105 | {/*content*/} 106 |
    107 | {/*header*/} 108 |
    109 | Workflow 114 |

    115 | Add Room 116 |

    117 | 125 |
    126 | {/*body*/} 127 | 128 |
    129 | 135 | 142 | setRoomName(event.target.value) 143 | } 144 | > 145 |
    146 | 147 |
    148 |

    149 | I always felt like I could do anything. 150 | That’s the main thing people are 151 | controlled by! Thoughts- their 152 | perception of themselves! They're slowed 153 | down by their perception of themselves. 154 | If you're taught you can’t do anything, 155 | you won’t do anything. I was taught I 156 | could do everything. 157 |

    158 |
    159 | 160 | {/*footer*/} 161 |
    162 | 169 | 179 |
    180 |
    181 |
    182 |
    183 |
    184 | 185 | ) : null} 186 | 187 | ); 188 | }; 189 | 190 | const RoomSelect = () => { 191 | const { 192 | isLogin, 193 | testLogin, 194 | getAvatar, 195 | // getRoomIdByName, 196 | getDisplayName, 197 | getMatrixRooms, 198 | createRoom, 199 | getHistory, 200 | } = useMatrixClient(); 201 | const [yesLogin, setYesLogin] = useState(false); 202 | 203 | const [avatar, setAvatar] = useState(null); 204 | const [roomList, setRoomList] = useState([]); 205 | const [displayName, setDisplayName] = useState(null); 206 | 207 | useEffect(() => { 208 | (async () => { 209 | if (isLogin() === false) { 210 | await testLogin(); 211 | } 212 | setTimeout(() => { 213 | setYesLogin(isLogin()); 214 | const get_room = () => { 215 | (async () => { 216 | try { 217 | // let room_id = await getRoomIdByName('Capstone-HelloWorld'); 218 | let matrixRoom = await getMatrixRooms(); 219 | let profileAvatar = await getAvatar(); 220 | let display_name = await getDisplayName(); 221 | setDisplayName(display_name); 222 | // setRoomID(room_id); 223 | setRoomList(matrixRoom); 224 | if ( 225 | profileAvatar === null || 226 | profileAvatar === '' 227 | ) { 228 | setAvatar(null); 229 | } else { 230 | setAvatar(profileAvatar); 231 | } 232 | } catch (e) { 233 | console.log('error', e); 234 | setDisplayName(null); 235 | setAvatar(null); 236 | // setRoomID(null); 237 | setRoomList(null); 238 | } 239 | })(); 240 | }; 241 | 242 | get_room(); 243 | }, 500); 244 | })(); 245 | }, [avatar, getAvatar, getDisplayName, getMatrixRooms, isLogin, testLogin]); 246 | 247 | return ( 248 | <> 249 | {yesLogin ? ( 250 |
    251 | {avatar ? ( 252 | 259 | ) : ( 260 | 265 | )} 266 |
    267 | ) : ( 268 | 269 | )} 270 | 271 | ); 272 | }; 273 | 274 | export default RoomSelect; 275 | -------------------------------------------------------------------------------- /src/pages/Settingpage.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import React from 'react'; 7 | import { useState, useEffect } from 'react'; 8 | import TopNavigationBar from '../components/TopNavigationBar'; 9 | import { PaperClipIcon } from '@heroicons/react/solid'; 10 | import useMatrixClient from '../hooks/useMatrixClient'; 11 | import Page403 from './Page403'; 12 | 13 | const ProfileView = () => { 14 | return ( 15 | <> 16 |
    17 |
    18 |
    27 |
    31 | 40 | 44 | 45 |
    46 |
    47 |
    48 |
    49 |
    50 |
    51 |
    52 |
    53 |
    54 |
    55 |
    56 |
    57 |
    58 |
    59 |
    60 |
    61 | 62 |
    63 |
    64 | 65 |
    66 |
    67 | 68 |
    69 |
    70 |
    71 |
    72 |
    73 |

    74 | Settings 75 |

    76 |

    77 | Personal details and application. 78 |

    79 |
    80 | 81 |
    82 |
    83 |
    84 |
    85 | HomeServer 86 |
    87 |
    88 | matrix.pdxinfosec.org 89 |
    90 |
    91 |
    92 |
    93 | Account 94 |
    95 |
    96 | @test003:pdxinfosec.org 97 |
    98 |
    99 |
    100 |
    101 | Email address 102 |
    103 |
    104 | margotfoster@example.com 105 |
    106 |
    107 |
    108 |
    109 | Room ID 110 |
    111 |
    112 | !bdQMmkTBTMqUPAOvms:pdxinfosec.org 113 |
    114 |
    115 |
    116 |
    117 | About 118 |
    119 |
    120 | Fugiat ipsum ipsum deserunt 121 | culpa aute sint do nostrud anim 122 | incididunt cillum culpa 123 | consequat. Excepteur qui ipsum 124 | aliquip consequat sint. Sit id 125 | mollit nulla mollit nostrud in 126 | ea officia proident. Irure 127 | nostrud pariatur mollit ad 128 | adipisicing reprehenderit 129 | deserunt qui eu. 130 |
    131 |
    132 |
    133 |
    134 | Attachments 135 |
    136 |
    137 |
      141 |
    • 142 |
      143 |
      151 | 159 |
    • 160 |
    • 161 |
      162 |
      170 | 178 |
    • 179 |
    180 |
    181 |
    182 |
    183 |
    184 |
    185 |
    186 |
    187 |
    188 | footer 189 |
    190 |
    191 |
    192 |
    193 | Open Source Security Camera App - 2022 194 |
    195 |
    196 |
    197 |
    198 |
    199 | 200 | ); 201 | }; 202 | 203 | const Setting = () => { 204 | const { isLogin, testLogin } = useMatrixClient(); 205 | const [yesLogin, setYesLogin] = useState(false); 206 | 207 | useEffect(() => { 208 | (async () => { 209 | if (isLogin() === false) { 210 | console.log('Run test login'); 211 | await testLogin(); 212 | } 213 | setTimeout(() => { 214 | setYesLogin(isLogin()); 215 | }, 500); 216 | })(); 217 | }, [isLogin, testLogin]); 218 | 219 | return ( 220 | <> 221 | {yesLogin ? ( 222 |
    223 | 224 | 225 |
    226 | ) : ( 227 | 228 | )} 229 | 230 | ); 231 | }; 232 | 233 | export default Setting; 234 | -------------------------------------------------------------------------------- /src/pages/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /src/reducers/profile.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import { Types } from '../constants/actionTypes'; 7 | 8 | const initialState = { 9 | profile: { 10 | firstName: '', 11 | lastName: '', 12 | telephone: '', 13 | age: 28, 14 | email: '', 15 | state: '', 16 | country: '', 17 | address: 'Home', 18 | address1: '', 19 | address2: '', 20 | interests: [], 21 | profileImage: '', 22 | subscribenewsletter: false 23 | }, 24 | formSubmitted: false 25 | } 26 | 27 | const reducer = (state = initialState, action) => { 28 | switch (action.type) { 29 | case Types.LOGIN: 30 | console.log('login', action.payload.user) 31 | return { 32 | ...state, 33 | profile: action.payload.user, 34 | formSubmitted: false // after update user formsubmition reset 35 | } 36 | case Types.ADD_USER: 37 | return { 38 | ...state, 39 | profile: action.payload.user, 40 | formSubmitted: false // after update user formsubmition reset 41 | } 42 | case Types.UPDATE_USER: 43 | return { 44 | ...state, 45 | profile: action.payload.user, 46 | formSubmitted: false // after update user formsubmition reset 47 | } 48 | case Types.UPDATE_PROFILE_PICTURE: 49 | return { 50 | ...state, 51 | profile: { 52 | ...state.profile, 53 | profileImage: action.payload.image 54 | } 55 | } 56 | case Types.FORM_SUBMITION_STATUS: 57 | return { 58 | ...state, 59 | formSubmitted: action.payload.status 60 | } 61 | default: 62 | return state; 63 | } 64 | } 65 | 66 | export default reducer; -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | const reportWebVitals = onPerfEntry => { 7 | if (onPerfEntry && onPerfEntry instanceof Function) { 8 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 9 | getCLS(onPerfEntry); 10 | getFID(onPerfEntry); 11 | getFCP(onPerfEntry); 12 | getLCP(onPerfEntry); 13 | getTTFB(onPerfEntry); 14 | }); 15 | } 16 | }; 17 | 18 | export default reportWebVitals; 19 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | // This optional code is used to register a service worker. 7 | // register() is not called by default. 8 | 9 | // This lets the app load faster on subsequent visits in production, and gives 10 | // it offline capabilities. However, it also means that developers (and users) 11 | // will only see deployed updates on subsequent visits to a page, after all the 12 | // existing tabs open on the page have been closed, since previously cached 13 | // resources are updated in the background. 14 | 15 | // To learn more about the benefits of this model and instructions on how to 16 | // opt-in, read https://bit.ly/CRA-PWA 17 | 18 | const isLocalhost = Boolean( 19 | window.location.hostname === 'localhost' || 20 | // [::1] is the IPv6 localhost address. 21 | window.location.hostname === '[::1]' || 22 | // 127.0.0.0/8 are considered localhost for IPv4. 23 | window.location.hostname.match( 24 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 25 | ) 26 | ); 27 | 28 | export function register(config) { 29 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 30 | // The URL constructor is available in all browsers that support SW. 31 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 32 | if (publicUrl.origin !== window.location.origin) { 33 | // Our service worker won't work if PUBLIC_URL is on a different origin 34 | // from what our page is served on. This might happen if a CDN is used to 35 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 36 | return; 37 | } 38 | 39 | window.addEventListener('load', () => { 40 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 41 | 42 | if (isLocalhost) { 43 | // This is running on localhost. Let's check if a service worker still exists or not. 44 | checkValidServiceWorker(swUrl, config); 45 | 46 | // Add some additional logging to localhost, pointing developers to the 47 | // service worker/PWA documentation. 48 | navigator.serviceWorker.ready.then(() => { 49 | console.log( 50 | 'This web app is being served cache-first by a service ' + 51 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 52 | ); 53 | }); 54 | } else { 55 | // Is not localhost. Just register service worker 56 | registerValidSW(swUrl, config); 57 | } 58 | }); 59 | } 60 | } 61 | 62 | function registerValidSW(swUrl, config) { 63 | navigator.serviceWorker 64 | .register(swUrl) 65 | .then(registration => { 66 | registration.onupdatefound = () => { 67 | const installingWorker = registration.installing; 68 | if (installingWorker == null) { 69 | return; 70 | } 71 | installingWorker.onstatechange = () => { 72 | if (installingWorker.state === 'installed') { 73 | if (navigator.serviceWorker.controller) { 74 | // At this point, the updated precached content has been fetched, 75 | // but the previous service worker will still serve the older 76 | // content until all client tabs are closed. 77 | console.log( 78 | 'New content is available and will be used when all ' + 79 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 80 | ); 81 | 82 | // Execute callback 83 | if (config && config.onUpdate) { 84 | config.onUpdate(registration); 85 | } 86 | } else { 87 | // At this point, everything has been precached. 88 | // It's the perfect time to display a 89 | // "Content is cached for offline use." message. 90 | console.log('Content is cached for offline use.'); 91 | 92 | // Execute callback 93 | if (config && config.onSuccess) { 94 | config.onSuccess(registration); 95 | } 96 | } 97 | } 98 | }; 99 | }; 100 | }) 101 | .catch(error => { 102 | console.error('Error during service worker registration:', error); 103 | }); 104 | } 105 | 106 | function checkValidServiceWorker(swUrl, config) { 107 | // Check if the service worker can be found. If it can't reload the page. 108 | fetch(swUrl, { 109 | headers: { 'Service-Worker': 'script' }, 110 | }) 111 | .then(response => { 112 | // Ensure service worker exists, and that we really are getting a JS file. 113 | const contentType = response.headers.get('content-type'); 114 | if ( 115 | response.status === 404 || 116 | (contentType != null && contentType.indexOf('javascript') === -1) 117 | ) { 118 | // No service worker found. Probably a different app. Reload the page. 119 | navigator.serviceWorker.ready.then(registration => { 120 | registration.unregister().then(() => { 121 | window.location.reload(); 122 | }); 123 | }); 124 | } else { 125 | // Service worker found. Proceed as normal. 126 | registerValidSW(swUrl, config); 127 | } 128 | }) 129 | .catch(() => { 130 | console.log( 131 | 'No internet connection found. App is running in offline mode.' 132 | ); 133 | }); 134 | } 135 | 136 | export function unregister() { 137 | if ('serviceWorker' in navigator) { 138 | navigator.serviceWorker.ready 139 | .then(registration => { 140 | registration.unregister(); 141 | }) 142 | .catch(error => { 143 | console.error(error.message); 144 | }); 145 | } 146 | } -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 7 | // allows you to do things like: 8 | // expect(element).toHaveTextContent(/react/i) 9 | // learn more: https://github.com/testing-library/jest-dom 10 | import '@testing-library/jest-dom'; 11 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | import { createStore, combineReducers, compose, applyMiddleware } from 'redux'; 7 | import thunk from 'redux-thunk'; 8 | 9 | import profile from '../reducers/profile'; 10 | 11 | const rootReducer = combineReducers({ 12 | user: profile 13 | }); 14 | 15 | const configureStore = () => { 16 | return createStore( 17 | rootReducer, 18 | compose(applyMiddleware(thunk)) 19 | ); 20 | }; 21 | 22 | export default configureStore; -------------------------------------------------------------------------------- /src/styles/index.js: -------------------------------------------------------------------------------- 1 | import './main.css'; -------------------------------------------------------------------------------- /src/styles/main.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100% !important; 3 | margin: 0; 4 | } 5 | .form-control, .col-form-label, .custom-select, label, header, footer { 6 | font-size: 0.8rem !important; 7 | } 8 | .button { 9 | padding: .6rem 2rem; 10 | line-height: 1.5; 11 | border-radius: .4rem; 12 | color: #fff; 13 | background-color: #1b8bec; 14 | border-color: #6c757d; 15 | text-decoration: none; 16 | border: 1px solid rgb(24, 24, 80); 17 | } 18 | .pagecenter { 19 | position: absolute; 20 | left: 50%; 21 | top: 50%; 22 | transform: translate(-50%, -50%); 23 | } 24 | .error { 25 | color: red; 26 | font-size: 0.8rem; 27 | } 28 | .right { 29 | text-align: right; 30 | } 31 | .link-button { 32 | background-color: transparent; 33 | border: none; 34 | cursor: pointer; 35 | text-decoration: underline; 36 | display: block; 37 | text-align: center; 38 | margin: 10px; 39 | width: 100%; 40 | color: #1b8bec; 41 | } 42 | .link-button:hover, 43 | .link-button:focus { 44 | text-decoration: none; 45 | } -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Open Source Video Team and contributors. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for details. 4 | // 5 | 6 | /** 7 | * Set localStorage 8 | */ 9 | export const setStore = (name, content) => { 10 | if (!name) return 11 | if (typeof content !== 'string') { 12 | content = JSON.stringify(content) 13 | } 14 | return window.localStorage.setItem(name, content) 15 | } 16 | 17 | /** 18 | * Get localStorage 19 | */ 20 | export const getStore = (name) => { 21 | if (!name) return 22 | return JSON.parse(window.localStorage.getItem(name)) 23 | } 24 | 25 | /** 26 | * Clear localStorage 27 | */ 28 | export const removeItem = (name) => { 29 | if (!name) return 30 | return window.localStorage.removeItem(name) 31 | } 32 | 33 | /** 34 | * Validate Email address 35 | */ 36 | export const isValidEmail = (value) => { 37 | return !(value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,64}$/i.test(value)) 38 | } 39 | 40 | /** 41 | * Format Phone Number 42 | */ 43 | export const formatPhoneNumber = (value) => { 44 | if (!value) return 45 | const currentValue = value.replace(/[^\d]/g, ''); 46 | const mobileNoLength = currentValue.length; 47 | if (mobileNoLength >=7) { 48 | if (mobileNoLength < 4) return currentValue; 49 | if (mobileNoLength < 7) return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3)}`; 50 | return `(${currentValue.slice(0, 3)}) ${currentValue.slice(3, 6)}-${currentValue.slice(6, 10)}`; 51 | } else{ 52 | return currentValue; 53 | } 54 | } -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | "./src/**/*.{js,jsx,ts,tsx, html}", 4 | "./node_modules/flowbite/**/*.{js,jsx,ts,tsx, html}", 5 | './src/components/**/*.{js,jsx,ts,tsx, html}', 6 | './src/pages/**/*.{js,jsx,ts,tsx, html}', 7 | ], 8 | theme: { 9 | extend: {}, 10 | }, 11 | plugins: [ 12 | require('flowbite/plugin') 13 | ], 14 | darkMode: 'class', 15 | } 16 | --------------------------------------------------------------------------------