commit f79821182d7abfe1fc7a63c1dfc541e63b53fa01 Author: nganhkhoa Date: Thu Apr 15 15:52:54 2021 +0700 working app diff --git a/.buckconfig b/.buckconfig new file mode 100644 index 0000000..934256c --- /dev/null +++ b/.buckconfig @@ -0,0 +1,6 @@ + +[android] + target = Google Inc.:Google APIs:23 + +[maven_repositories] + central = https://repo1.maven.org/maven2 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7c28613 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +# Windows files +[*.bat] +end_of_line = crlf diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..40c6dcd --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: '@react-native-community', +}; diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..315f274 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,66 @@ +[ignore] +; We fork some components by platform +.*/*[.]android.js + +; Ignore "BUCK" generated dirs +/\.buckd/ + +; Ignore polyfills +node_modules/react-native/Libraries/polyfills/.* + +; Flow doesn't support platforms +.*/Libraries/Utilities/LoadingView.js + +[untyped] +.*/node_modules/@react-native-community/cli/.*/.* + +[include] + +[libs] +node_modules/react-native/interface.js +node_modules/react-native/flow/ + +[options] +emoji=true + +esproposal.optional_chaining=enable +esproposal.nullish_coalescing=enable + +exact_by_default=true + +module.file_ext=.js +module.file_ext=.json +module.file_ext=.ios.js + +munge_underscores=true + +module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' +module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FlowFixMeProps +suppress_type=$FlowFixMeState + +[lints] +sketchy-null-number=warn +sketchy-null-mixed=warn +sketchy-number=warn +untyped-type-import=warn +nonstrict-import=warn +deprecated-type=warn +unsafe-getters-setters=warn +unnecessary-invariant=warn +signature-verification-failure=warn + +[strict] +deprecated-type +nonstrict-import +sketchy-null +unclear-type +unsafe-getters-setters +untyped-import +untyped-type-import + +[version] +^0.137.0 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..45a3dcb --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Windows files should use crlf line endings +# https://help.github.com/articles/dealing-with-line-endings/ +*.bat text eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ad572e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,59 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +*.keystore +!debug.keystore + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +*/fastlane/report.xml +*/fastlane/Preview.html +*/fastlane/screenshots + +# Bundle artifact +*.jsbundle + +# CocoaPods +/ios/Pods/ diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..84196d9 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + bracketSpacing: false, + jsxBracketSameLine: true, + singleQuote: true, + trailingComma: 'all', + arrowParens: 'avoid', +}; diff --git a/.watchmanconfig b/.watchmanconfig new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/.watchmanconfig @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/App.js b/App.js new file mode 100644 index 0000000..ac55a32 --- /dev/null +++ b/App.js @@ -0,0 +1,161 @@ +import React, { useEffect, useState } from 'react'; +import type {Node} from 'react'; +import { + SafeAreaView, + Text, + TextInput, + View, + Button, +} from 'react-native'; + +import axios from 'axios'; + +import AsyncStorage from '@react-native-async-storage/async-storage'; + +import LoginView from "./views/LoginView"; +import StatusView, { appState } from "./views/StatusView"; + +import { decryptor } from "./Utils"; +import pi from "./Pi"; +import farm from "./Farm"; + +const App: () => Node = () => { + const [errorMessage, setErrorMessage] = useState(""); + const [username, setUsername] = useState(""); + const [userInfo, setUserInfo] = useState({ + username: "", + subscribers: [], + }); + + const [activeCount, setActiveCount] = useState(0); + const [totalCount, setTotalCount] = useState(0); + + // ["loginScreen", "statusFetch", "waiting", "waking", "fullyAwake"] + const [appStatus, setAppStatus] = useState(appState.default); + + const fetchUserData = async () => { + const userInfo = await farm.GetUserInfo(username); + const statusChecker = userInfo.subscribers.map(sub => { + return pi.StatusChecker(sub); + }); + const botStatuses = await Promise.all(statusChecker); + const botActive = botStatuses.reduce((acc, s) => s ? acc + 1 : acc, 0); + + setUserInfo(userInfo); + setTotalCount(botStatuses.length); + setActiveCount(botActive); + + return botActive == botStatuses.length; + }; + + const wakeup = () => { + setAppStatus(appState.waking) + const waker = userInfo.subscribers.map(sub => { + return pi.Waker(sub); + }); + Promise.all(waker) + .then((botStatuses) => { + setErrorMessage("") + const botActive = botStatuses.reduce((acc, s) => s ? acc + 1 : acc, 0) + setActiveCount(botActive); + if (botActive == botStatuses.length) { + setAppStatus(appState.fullyAwake) + } else { + setAppStatus(appState.waiting) + } + }) + .catch((err) => { + setErrorMessage("Cannot Wake Up") + }) + } + + const login = () => { + setAppStatus(appState.statusFetch) + fetchUserData() + .then((awaken) => { + setErrorMessage("") + if (awaken) { + setAppStatus(appState.fullyAwake) + } else { + setAppStatus(appState.waiting) + } + AsyncStorage.setItem("username", username) + .catch((_) => {}) + }) + .catch((err) => { + setErrorMessage("Cannot fetch user information") + }) + } + + const logout = () => { + setUsername(""); + setUserInfo({ + username: "", + subscribers: [], + }); + setAppStatus(appState.loginScreen) + AsyncStorage.removeItem("username", null); + } + + const tryGetUser = () => { + AsyncStorage.getItem("username") + .then((localUser) => { + if (localUser !== null) { + setUsername(localUser); + } + }) + .catch((_) => {}); + } + + useEffect(tryGetUser, []); + + return ( + + + { + (appStatus == appState.loginScreen) + ? + + + : + +