├── web-build ├── .gitignore ├── favicon.ico ├── favicon-16.png ├── favicon-32.png ├── fonts │ ├── Entypo.ttf │ ├── AntDesign.ttf │ ├── Feather.ttf │ ├── Fontisto.ttf │ ├── Ionicons.ttf │ ├── FontAwesome.ttf │ ├── Foundation.ttf │ ├── MaterialIcons.ttf │ ├── SimpleLineIcons.ttf │ ├── FontAwesome5_Brands.ttf │ ├── FontAwesome5_Solid.ttf │ └── MaterialCommunityIcons.ttf ├── static │ ├── media │ │ └── logo.f1c5195b.png │ └── js │ │ ├── runtime~app.2e9f1821.js │ │ ├── 2.505c84bf.chunk.js.LICENSE.txt │ │ ├── runtime~app.2e9f1821.js.map │ │ ├── app.cc664779.chunk.js │ │ └── app.cc664779.chunk.js.map ├── pwa │ ├── chrome-icon │ │ ├── chrome-icon-144.png │ │ ├── chrome-icon-192.png │ │ └── chrome-icon-512.png │ ├── apple-touch-icon │ │ └── apple-touch-icon-180.png │ └── apple-touch-startup-image │ │ ├── apple-touch-startup-image-1125x2436.png │ │ ├── apple-touch-startup-image-1242x2208.png │ │ ├── apple-touch-startup-image-1242x2688.png │ │ ├── apple-touch-startup-image-1536x2048.png │ │ ├── apple-touch-startup-image-1668x2224.png │ │ ├── apple-touch-startup-image-1668x2388.png │ │ ├── apple-touch-startup-image-2048x2732.png │ │ ├── apple-touch-startup-image-640x1136.png │ │ ├── apple-touch-startup-image-750x1334.png │ │ └── apple-touch-startup-image-828x1792.png ├── serve.json ├── manifest.json ├── asset-manifest.json └── index.html ├── assets ├── icon.png ├── logo.png ├── favicon.png ├── splash.png └── adaptive-icon.png ├── .expo-shared └── assets.json ├── .gitignore ├── tsconfig.json ├── reducers ├── darkModeReducer.tsx ├── searchOptionReducer.tsx ├── rootReducer.tsx └── searchQueryReducer.tsx ├── babel.config.js ├── components ├── Logo.tsx ├── SearchContainer.tsx ├── Main.tsx ├── Footer.tsx ├── SearchBar.tsx ├── RadioButtonContainer.tsx ├── Header.tsx └── SearchResults.tsx ├── app.json ├── package.json ├── App.tsx └── README.md /web-build/.gitignore: -------------------------------------------------------------------------------- 1 | .vercel 2 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/assets/icon.png -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/assets/logo.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/assets/favicon.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/assets/splash.png -------------------------------------------------------------------------------- /web-build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/favicon.ico -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/assets/adaptive-icon.png -------------------------------------------------------------------------------- /web-build/favicon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/favicon-16.png -------------------------------------------------------------------------------- /web-build/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/favicon-32.png -------------------------------------------------------------------------------- /web-build/fonts/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/Entypo.ttf -------------------------------------------------------------------------------- /web-build/fonts/AntDesign.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/AntDesign.ttf -------------------------------------------------------------------------------- /web-build/fonts/Feather.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/Feather.ttf -------------------------------------------------------------------------------- /web-build/fonts/Fontisto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/Fontisto.ttf -------------------------------------------------------------------------------- /web-build/fonts/Ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/Ionicons.ttf -------------------------------------------------------------------------------- /web-build/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /web-build/fonts/Foundation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/Foundation.ttf -------------------------------------------------------------------------------- /web-build/fonts/MaterialIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/MaterialIcons.ttf -------------------------------------------------------------------------------- /web-build/fonts/SimpleLineIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/SimpleLineIcons.ttf -------------------------------------------------------------------------------- /web-build/fonts/FontAwesome5_Brands.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/FontAwesome5_Brands.ttf -------------------------------------------------------------------------------- /web-build/fonts/FontAwesome5_Solid.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/FontAwesome5_Solid.ttf -------------------------------------------------------------------------------- /web-build/static/media/logo.f1c5195b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/static/media/logo.f1c5195b.png -------------------------------------------------------------------------------- /web-build/fonts/MaterialCommunityIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/fonts/MaterialCommunityIcons.ttf -------------------------------------------------------------------------------- /web-build/pwa/chrome-icon/chrome-icon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/chrome-icon/chrome-icon-144.png -------------------------------------------------------------------------------- /web-build/pwa/chrome-icon/chrome-icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/chrome-icon/chrome-icon-192.png -------------------------------------------------------------------------------- /web-build/pwa/chrome-icon/chrome-icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/chrome-icon/chrome-icon-512.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-icon/apple-touch-icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-icon/apple-touch-icon-180.png -------------------------------------------------------------------------------- /.expo-shared/assets.json: -------------------------------------------------------------------------------- 1 | { 2 | "12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, 3 | "40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true 4 | } 5 | -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1125x2436.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1125x2436.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1242x2208.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1242x2208.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1242x2688.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1242x2688.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1536x2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1536x2048.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1668x2224.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1668x2224.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1668x2388.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-1668x2388.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-2048x2732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-2048x2732.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-640x1136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-640x1136.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-750x1334.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-750x1334.png -------------------------------------------------------------------------------- /web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-828x1792.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yonureker/gitsearch/HEAD/web-build/pwa/apple-touch-startup-image/apple-touch-startup-image-828x1792.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | .expo/* 3 | npm-debug.* 4 | *.jks 5 | *.p8 6 | *.p12 7 | *.key 8 | *.mobileprovision 9 | *.orig.* 10 | 11 | # macOS 12 | .DS_Store 13 | 14 | # env 15 | .env 16 | 17 | .vercel 18 | .static 19 | 20 | -------------------------------------------------------------------------------- /web-build/serve.json: -------------------------------------------------------------------------------- 1 | { 2 | "headers": [ 3 | { 4 | "source": "static/**/*.js", 5 | "headers": [ 6 | { 7 | "key": "Cache-Control", 8 | "value": "public, max-age=31536000, immutable" 9 | } 10 | ] 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "jsx": "react-native", 5 | "lib": ["dom", "esnext"], 6 | "moduleResolution": "node", 7 | "noEmit": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true, 10 | "strict": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /reducers/darkModeReducer.tsx: -------------------------------------------------------------------------------- 1 | const initialState = { 2 | theme: false 3 | } 4 | 5 | const darkModeReducer = (state = initialState, action) => { 6 | switch (action.type) { 7 | case "TOGGLE_THEME": 8 | return {...state, theme: !state.theme} 9 | break; 10 | default: 11 | return state; 12 | } 13 | } 14 | 15 | export default darkModeReducer; -------------------------------------------------------------------------------- /reducers/searchOptionReducer.tsx: -------------------------------------------------------------------------------- 1 | const initialState = {value: 'repositories'} 2 | 3 | const searchOptionReducer = (state = initialState, action) => { 4 | switch(action.type) { 5 | case "TOGGLE_OPTION": 6 | return {...state, value: action.payload}; 7 | break; 8 | default: 9 | return state; 10 | } 11 | } 12 | 13 | export default searchOptionReducer; -------------------------------------------------------------------------------- /reducers/rootReducer.tsx: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import searchOptionReducer from './searchOptionReducer'; 3 | import searchQueryReducer from './searchQueryReducer'; 4 | import darkModeReducer from './darkModeReducer' 5 | 6 | const rootReducer = combineReducers({ 7 | query: searchQueryReducer, 8 | searchOption: searchOptionReducer, 9 | darkMode: darkModeReducer 10 | }); 11 | 12 | export default rootReducer; -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: ["babel-preset-expo"], 5 | env: { 6 | production: { 7 | plugins: [ 8 | "react-native-paper/babel", 9 | [ 10 | "module:react-native-dotenv", 11 | { 12 | moduleName: "react-native-dotenv" 13 | }] 14 | ] 15 | } 16 | } 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /reducers/searchQueryReducer.tsx: -------------------------------------------------------------------------------- 1 | const initialState = {text: ''} 2 | 3 | const searchQueryReducer = (state = initialState, action) => { 4 | switch(action.type) { 5 | case "UPDATE_QUERY": 6 | return {...state, text: action.payload}; 7 | break; 8 | case "RESET_QUERY": 9 | return {...state, text: ''}; 10 | break; 11 | default: 12 | return state; 13 | } 14 | } 15 | 16 | export default searchQueryReducer; -------------------------------------------------------------------------------- /components/Logo.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { View, Image, StyleSheet } from 'react-native' 3 | 4 | export default function Logo() { 5 | return ( 6 | 7 | 8 | 9 | ) 10 | } 11 | 12 | const styles = StyleSheet.create({ 13 | container: { 14 | alignItems: "center", 15 | justifyContent: "center", 16 | }, 17 | image: { 18 | aspectRatio: 5.5, 19 | resizeMode: 'contain', 20 | width: 276, 21 | height: 50 22 | } 23 | }) 24 | 25 | -------------------------------------------------------------------------------- /web-build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "background_color": "#ffffff", 3 | "display": "standalone", 4 | "lang": "en", 5 | "name": "gitsearch", 6 | "short_name": "gitsearch", 7 | "start_url": "/?utm_source=web_app_manifest", 8 | "orientation": "portrait", 9 | "icons": [ 10 | { 11 | "src": "/pwa/chrome-icon/chrome-icon-144.png", 12 | "sizes": "144x144", 13 | "type": "image/png" 14 | }, 15 | { 16 | "src": "/pwa/chrome-icon/chrome-icon-192.png", 17 | "sizes": "192x192", 18 | "type": "image/png" 19 | }, 20 | { 21 | "src": "/pwa/chrome-icon/chrome-icon-512.png", 22 | "sizes": "512x512", 23 | "type": "image/png" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /components/SearchContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react' 2 | import { StyleSheet, Text, View } from 'react-native' 3 | import SearchBar from './SearchBar' 4 | import RadioButtonContainer from './RadioButtonContainer' 5 | import SearchResults from './SearchResults'; 6 | 7 | export default function SearchContainer() { 8 | 9 | 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | 19 | const styles = StyleSheet.create({ 20 | container: { 21 | height: 150, 22 | width: '100%', 23 | maxWidth: 600, 24 | padding: 10, 25 | marginBottom: 150 26 | } 27 | }) 28 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "gitsearch", 4 | "slug": "gitsearch", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "splash": { 9 | "image": "./assets/splash.png", 10 | "resizeMode": "contain", 11 | "backgroundColor": "#ffffff" 12 | }, 13 | "updates": { 14 | "fallbackToCacheTimeout": 0 15 | }, 16 | "assetBundlePatterns": [ 17 | "**/*" 18 | ], 19 | "ios": { 20 | "supportsTablet": true 21 | }, 22 | "android": { 23 | "adaptiveIcon": { 24 | "foregroundImage": "./assets/adaptive-icon.png", 25 | "backgroundColor": "#FFFFFF" 26 | } 27 | }, 28 | "web": { 29 | "favicon": "./assets/favicon.png" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /components/Main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Platform, SafeAreaView, StyleSheet, Text, View } from "react-native"; 3 | import { StatusBar } from "expo-status-bar"; 4 | import { useSelector } from "react-redux"; 5 | 6 | import Header from "../components/Header"; 7 | import Logo from "../components/Logo"; 8 | import SearchContainer from "../components/SearchContainer"; 9 | import Footer from "../components/Footer"; 10 | 11 | export default function Main() { 12 | const darkMode = useSelector(state => state.darkMode.theme) 13 | const containerStyle = darkMode ? styles.darkModeContainer : null 14 | 15 | return ( 16 | 17 | 18 | 19 | 20 | {Platform.OS === "web" && } 21 | 22 | 23 | ) 24 | } 25 | 26 | const styles = StyleSheet.create({ 27 | container: { 28 | flex: 1, 29 | backgroundColor: "#fff", 30 | alignItems: "center", 31 | justifyContent: "center", 32 | }, 33 | darkModeContainer : { 34 | backgroundColor: 'black' 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { StyleSheet, Text, View } from 'react-native'; 3 | import { Ionicons } from "@expo/vector-icons"; 4 | import { useDispatch, useSelector } from 'react-redux'; 5 | 6 | export default function Footer() { 7 | const darkMode = useSelector(state => state.darkMode.theme) 8 | const textStyle = darkMode ? styles.darkModeText : null; 9 | const containerStyle = darkMode ? styles.darkModeContainer : null 10 | 11 | return ( 12 | 13 | 14 | Built with React Native Web 15 | 16 | 17 | ) 18 | } 19 | 20 | const styles = StyleSheet.create({ 21 | container: { 22 | position: 'absolute', 23 | bottom: 0, 24 | zIndex: 99, 25 | elevation: 99, 26 | backgroundColor: '#F2F2F2', 27 | width: '100%' 28 | }, 29 | item: { 30 | padding: 10, 31 | justifyContent: 'center', 32 | alignItems: 'center' 33 | }, 34 | darkModeText : { 35 | color: 'white' 36 | }, 37 | darkModeContainer : { 38 | backgroundColor: '#2B2828', 39 | }, 40 | }) 41 | -------------------------------------------------------------------------------- /components/SearchBar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { StyleSheet } from 'react-native'; 3 | import { Searchbar } from 'react-native-paper'; 4 | import { useDispatch, useSelector } from 'react-redux'; 5 | 6 | export default function SearchBar() { 7 | const dispatch = useDispatch(); 8 | const query = useSelector(state => state.query.text) 9 | const darkMode = useSelector(state => state.darkMode.theme) 10 | 11 | const containerStyle = darkMode ? styles.darkModeContainer : null 12 | const textStyle = darkMode ? styles.darkModeText : null; 13 | 14 | const onChangeSearch = (newQuery : string) => dispatch({type: "UPDATE_QUERY", payload: newQuery}); 15 | 16 | return ( 17 | 26 | ); 27 | } 28 | 29 | const styles = StyleSheet.create({ 30 | container: { 31 | marginTop: 20, 32 | borderWidth: 1, 33 | borderColor: '#DFE1E5' 34 | }, 35 | darkModeContainer : { 36 | backgroundColor: 'black', 37 | }, 38 | darkModeText : { 39 | color: 'white' 40 | } 41 | }) 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "node_modules/expo/AppEntry.js", 3 | "scripts": { 4 | "start": "expo start", 5 | "android": "expo start --android", 6 | "ios": "expo start --ios", 7 | "web": "expo start --web", 8 | "eject": "expo eject" 9 | }, 10 | "dependencies": { 11 | "@apollo/client": "^3.3.16", 12 | "@types/react-native-dotenv": "^0.2.0", 13 | "apollo-link-context": "^1.0.20", 14 | "dotenv": "^9.0.0", 15 | "expo": "~40.0.0", 16 | "expo-cli": "^4.4.3", 17 | "expo-status-bar": "~1.0.3", 18 | "global": "^4.4.0", 19 | "graphql": "^15.5.0", 20 | "react": "16.13.1", 21 | "react-bootstrap-typeahead": "^5.1.4", 22 | "react-dom": "16.13.1", 23 | "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.1.tar.gz", 24 | "react-native-dotenv": "^2.5.5", 25 | "react-native-paper": "^4.7.1", 26 | "react-native-svg": "^12.1.0", 27 | "react-native-vector-icons": "^8.0.0", 28 | "react-native-web": "~0.13.12", 29 | "react-redux": "^7.2.2", 30 | "react-switch": "^6.0.0", 31 | "redux": "^4.0.5" 32 | }, 33 | "devDependencies": { 34 | "@babel/core": "~7.9.0", 35 | "@types/react": "~16.9.35", 36 | "@types/react-dom": "~16.9.8", 37 | "@types/react-native": "~0.63.2", 38 | "gh-pages": "^3.1.0", 39 | "redux-logger": "^3.0.6", 40 | "typescript": "~4.0.0" 41 | }, 42 | "private": true 43 | } 44 | -------------------------------------------------------------------------------- /web-build/static/js/runtime~app.2e9f1821.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,l,f=r[0],i=r[1],a=r[2],c=0,s=[];c { 28 | // get the authentication token from local storage if it exists 29 | const token = "Bearer " + githubToken; 30 | // return the headers to the context so httpLink can read them 31 | return { 32 | headers: { 33 | ...headers, 34 | authorization: token ? token : null 35 | } 36 | }; 37 | }); 38 | 39 | const client = new ApolloClient({ 40 | link: authLink.concat(httpLink), 41 | cache: new InMemoryCache() 42 | }); 43 | 44 | return ( 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /web-build/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "app.js": "/static/js/app.cc664779.chunk.js", 4 | "app.js.map": "/static/js/app.cc664779.chunk.js.map", 5 | "runtime~app.js": "/static/js/runtime~app.2e9f1821.js", 6 | "runtime~app.js.map": "/static/js/runtime~app.2e9f1821.js.map", 7 | "static/js/2.505c84bf.chunk.js": "/static/js/2.505c84bf.chunk.js", 8 | "static/js/2.505c84bf.chunk.js.map": "/static/js/2.505c84bf.chunk.js.map", 9 | "fonts/AntDesign.ttf": "/./fonts/AntDesign.ttf", 10 | "fonts/Entypo.ttf": "/./fonts/Entypo.ttf", 11 | "fonts/Feather.ttf": "/./fonts/Feather.ttf", 12 | "fonts/FontAwesome.ttf": "/./fonts/FontAwesome.ttf", 13 | "fonts/FontAwesome5_Brands.ttf": "/./fonts/FontAwesome5_Brands.ttf", 14 | "fonts/FontAwesome5_Solid.ttf": "/./fonts/FontAwesome5_Solid.ttf", 15 | "fonts/Fontisto.ttf": "/./fonts/Fontisto.ttf", 16 | "fonts/Foundation.ttf": "/./fonts/Foundation.ttf", 17 | "fonts/Ionicons.ttf": "/./fonts/Ionicons.ttf", 18 | "fonts/MaterialCommunityIcons.ttf": "/./fonts/MaterialCommunityIcons.ttf", 19 | "fonts/MaterialIcons.ttf": "/./fonts/MaterialIcons.ttf", 20 | "fonts/SimpleLineIcons.ttf": "/./fonts/SimpleLineIcons.ttf", 21 | "favicon-16.png": "/favicon-16.png", 22 | "favicon-32.png": "/favicon-32.png", 23 | "favicon.ico": "/favicon.ico", 24 | "index.html": "/index.html", 25 | "manifest.json": "/manifest.json", 26 | "serve.json": "/serve.json", 27 | "static/js/2.505c84bf.chunk.js.LICENSE.txt": "/static/js/2.505c84bf.chunk.js.LICENSE.txt", 28 | "static/media/logo.png": "/static/media/logo.f1c5195b.png" 29 | }, 30 | "entrypoints": [ 31 | "static/js/runtime~app.2e9f1821.js", 32 | "static/js/2.505c84bf.chunk.js", 33 | "static/js/app.cc664779.chunk.js" 34 | ] 35 | } -------------------------------------------------------------------------------- /components/RadioButtonContainer.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { StyleSheet, Text, View } from "react-native"; 3 | import { RadioButton } from "react-native-paper"; 4 | import { useDispatch, useSelector } from "react-redux"; 5 | 6 | export default function RadioButtonContainer() { 7 | const dispatch = useDispatch(); 8 | const option = useSelector((state) => state.searchOption.value); 9 | const darkMode = useSelector(state => state.darkMode.theme) 10 | 11 | const textStyle = darkMode ? styles.darkModeText : null; 12 | 13 | 14 | return ( 15 | { 17 | dispatch({ type: "TOGGLE_OPTION", payload: newValue }) 18 | dispatch({type: "RESET_QUERY"}) 19 | } 20 | } 21 | value={option} 22 | > 23 | 24 | 25 | 26 | Search Users 27 | 28 | 29 | 30 | Search Repositories 31 | 32 | {/* 33 | 34 | Search Topics 35 | */} 36 | 37 | 38 | ); 39 | } 40 | 41 | const styles = StyleSheet.create({ 42 | container: { 43 | flexDirection: "row", 44 | justifyContent: "center", 45 | alignItems: "center", 46 | }, 47 | darkModeText : { 48 | color: 'white' 49 | } 50 | }); 51 | -------------------------------------------------------------------------------- /web-build/static/js/2.505c84bf.chunk.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /*! ***************************************************************************** 8 | Copyright (c) Microsoft Corporation. 9 | 10 | Permission to use, copy, modify, and/or distribute this software for any 11 | purpose with or without fee is hereby granted. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 14 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 15 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 16 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 17 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 18 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19 | PERFORMANCE OF THIS SOFTWARE. 20 | ***************************************************************************** */ 21 | 22 | /** @license React v0.19.1 23 | * scheduler.production.min.js 24 | * 25 | * Copyright (c) Facebook, Inc. and its affiliates. 26 | * 27 | * This source code is licensed under the MIT license found in the 28 | * LICENSE file in the root directory of this source tree. 29 | */ 30 | 31 | /** @license React v16.13.1 32 | * react-dom.production.min.js 33 | * 34 | * Copyright (c) Facebook, Inc. and its affiliates. 35 | * 36 | * This source code is licensed under the MIT license found in the 37 | * LICENSE file in the root directory of this source tree. 38 | */ 39 | 40 | /** @license React v16.13.1 41 | * react-is.production.min.js 42 | * 43 | * Copyright (c) Facebook, Inc. and its affiliates. 44 | * 45 | * This source code is licensed under the MIT license found in the 46 | * LICENSE file in the root directory of this source tree. 47 | */ 48 | 49 | /** @license React v16.13.1 50 | * react.production.min.js 51 | * 52 | * Copyright (c) Facebook, Inc. and its affiliates. 53 | * 54 | * This source code is licensed under the MIT license found in the 55 | * LICENSE file in the root directory of this source tree. 56 | */ 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## GitSearch 2 | 3 | GitSearch is a search engine where you can search Github users and repositories. Search results are shown as user types the query. The application uses the Github GraphQL API to display user or repository search results. The web app is built with React Native web components and the website is deployed via Vercel. 4 | 5 | ## Demo 6 | 7 | Live demo is available [here](https://gitsearch-six.vercel.app/) 8 | 9 | ## GraphQL 10 | 11 | I initially built the app with [Github REST API](https://docs.github.com/en/rest) where you simply fetch the data from either https://api.github.com/search/users?q=${query} or https://api.github.com/search/repositories?q=${query} and save the necessary portion of the response to a state to display the required info. 12 | 13 | Later, I realized that Github also has a [GraphQL API](https://docs.github.com/en/graphql) and wanted to have an intro about the GraphQL query language. After playing around with the [explorer](https://docs.github.com/en/graphql/overview/explorer), I come up with queries to search Github users and repositories given a query from the user: 14 | 15 | ```javascript 16 | const GET_USERS = gql` 17 | query SearchUsers($userQuery: String!) { 18 | search(query: $userQuery, type: USER, first: 20) { 19 | edges { 20 | node { 21 | ... on User { 22 | avatarUrl 23 | id 24 | login 25 | url 26 | } 27 | } 28 | } 29 | } 30 | } 31 | `; 32 | 33 | const GET_REPOSITORIES = gql` 34 | query SearchRepositories($userQuery: String!) { 35 | search(query: $userQuery, type: REPOSITORY, first: 20) { 36 | edges { 37 | node { 38 | ... on Repository { 39 | id 40 | url 41 | description 42 | stargazerCount 43 | nameWithOwner 44 | owner { 45 | avatarUrl 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | `; 53 | ``` 54 | 55 | ## Optimizing Search 56 | 57 | I have implemented a few conditions to make the search more data efficient for the user: 58 | 59 | * The user has to enter at least 3 characters before the search starts. 60 | * When the user stops typing, there is a 1 second delay before the search starts. 61 | 62 | ```javascript 63 | useEffect(() => { 64 | if (query.length >= 3) { 65 | const timeoutId = setTimeout(() => handleNewSearch(), 1000); 66 | return () => clearTimeout(timeoutId); 67 | } 68 | }, [query]); 69 | ``` -------------------------------------------------------------------------------- /components/Header.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | Linking, 7 | Pressable, 8 | Platform, 9 | } from "react-native"; 10 | import Constants from "expo-constants"; 11 | import { Ionicons } from "@expo/vector-icons"; 12 | import { useDispatch, useSelector } from "react-redux"; 13 | import Switch from "react-switch"; 14 | 15 | const STATUSBAR_HEIGHT = Constants.statusBarHeight; 16 | 17 | export default function Header() { 18 | const dispatch = useDispatch(); 19 | const darkMode = useSelector(state => state.darkMode.theme); 20 | 21 | const containerStyle = darkMode ? styles.darkModeContainer : null 22 | const textStyle = darkMode ? styles.darkModeText : null; 23 | 24 | const handleChange = () => { 25 | dispatch({ 26 | type: "TOGGLE_THEME" 27 | }) 28 | }; 29 | 30 | // const toggleDarkMode = () => () 31 | 32 | return ( 33 | 34 | 35 | Onur Eker 36 | 37 | 38 | 39 | 54 | 55 | 56 | {" "} 57 | 58 | } 59 | checkedIcon={ 60 | 68 | 69 | 70 | {" "} 71 | 72 | } 73 | /> 74 | 75 | 76 | 78 | Linking.openURL(`https://www.linkedin.com/in/onureker/`) 79 | } 80 | > 81 | 82 | LinkedIn 83 | 84 | 85 | 86 | 87 | Linking.openURL(`https://github.com/yonureker/`)} 89 | > 90 | 91 | Github 92 | 93 | 94 | 95 | 96 | 97 | ); 98 | } 99 | 100 | const styles = StyleSheet.create({ 101 | container: { 102 | width: "100%", 103 | alignItems: "center", 104 | justifyContent: "space-between", 105 | position: "absolute", 106 | top: Platform.OS === "android" ? STATUSBAR_HEIGHT : 0, 107 | flexDirection: "row", 108 | paddingRight: 10, 109 | paddingLeft: 10, 110 | backgroundColor: "#F2F2F2", 111 | }, 112 | item: { 113 | padding: 10, 114 | justifyContent: "center", 115 | alignItems: "center", 116 | }, 117 | darkModeText : { 118 | color: 'white' 119 | }, 120 | darkModeContainer : { 121 | backgroundColor: '#2B2828', 122 | }, 123 | }); 124 | -------------------------------------------------------------------------------- /web-build/index.html: -------------------------------------------------------------------------------- 1 | gitsearchOh no! It looks like JavaScript is not enabled in your browser.Reload -------------------------------------------------------------------------------- /web-build/static/js/runtime~app.2e9f1821.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack/bootstrap"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","1","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","this","oldJsonpFunction","slice"],"mappings":"aACE,SAASA,EAAqBC,GAQ7B,IAPA,IAMIC,EAAUC,EANVC,EAAWH,EAAK,GAChBI,EAAcJ,EAAK,GACnBK,EAAiBL,EAAK,GAIHM,EAAI,EAAGC,EAAW,GACpCD,EAAIH,EAASK,OAAQF,IACzBJ,EAAUC,EAASG,GAChBG,OAAOC,UAAUC,eAAeC,KAAKC,EAAiBX,IAAYW,EAAgBX,IACpFK,EAASO,KAAKD,EAAgBX,GAAS,IAExCW,EAAgBX,GAAW,EAE5B,IAAID,KAAYG,EACZK,OAAOC,UAAUC,eAAeC,KAAKR,EAAaH,KACpDc,EAAQd,GAAYG,EAAYH,IAKlC,IAFGe,GAAqBA,EAAoBhB,GAEtCO,EAASC,QACdD,EAASU,OAATV,GAOD,OAHAW,EAAgBJ,KAAKK,MAAMD,EAAiBb,GAAkB,IAGvDe,IAER,SAASA,IAER,IADA,IAAIC,EACIf,EAAI,EAAGA,EAAIY,EAAgBV,OAAQF,IAAK,CAG/C,IAFA,IAAIgB,EAAiBJ,EAAgBZ,GACjCiB,GAAY,EACRC,EAAI,EAAGA,EAAIF,EAAed,OAAQgB,IAAK,CAC9C,IAAIC,EAAQH,EAAeE,GACG,IAA3BX,EAAgBY,KAAcF,GAAY,GAE3CA,IACFL,EAAgBQ,OAAOpB,IAAK,GAC5Be,EAASM,EAAoBA,EAAoBC,EAAIN,EAAe,KAItE,OAAOD,EAIR,IAAIQ,EAAmB,GAKnBhB,EAAkB,CACrBiB,EAAG,GAGAZ,EAAkB,GAGtB,SAASS,EAAoB1B,GAG5B,GAAG4B,EAAiB5B,GACnB,OAAO4B,EAAiB5B,GAAU8B,QAGnC,IAAIC,EAASH,EAAiB5B,GAAY,CACzCK,EAAGL,EACHgC,GAAG,EACHF,QAAS,IAUV,OANAhB,EAAQd,GAAUW,KAAKoB,EAAOD,QAASC,EAAQA,EAAOD,QAASJ,GAG/DK,EAAOC,GAAI,EAGJD,EAAOD,QAKfJ,EAAoBO,EAAInB,EAGxBY,EAAoBQ,EAAIN,EAGxBF,EAAoBS,EAAI,SAASL,EAASM,EAAMC,GAC3CX,EAAoBY,EAAER,EAASM,IAClC5B,OAAO+B,eAAeT,EAASM,EAAM,CAAEI,YAAY,EAAMC,IAAKJ,KAKhEX,EAAoBgB,EAAI,SAASZ,GACX,qBAAXa,QAA0BA,OAAOC,aAC1CpC,OAAO+B,eAAeT,EAASa,OAAOC,YAAa,CAAEC,MAAO,WAE7DrC,OAAO+B,eAAeT,EAAS,aAAc,CAAEe,OAAO,KAQvDnB,EAAoBoB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQnB,EAAoBmB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,kBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKzC,OAAO0C,OAAO,MAGvB,GAFAxB,EAAoBgB,EAAEO,GACtBzC,OAAO+B,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOnB,EAAoBS,EAAEc,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRvB,EAAoB2B,EAAI,SAAStB,GAChC,IAAIM,EAASN,GAAUA,EAAOiB,WAC7B,WAAwB,OAAOjB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAL,EAAoBS,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRX,EAAoBY,EAAI,SAASgB,EAAQC,GAAY,OAAO/C,OAAOC,UAAUC,eAAeC,KAAK2C,EAAQC,IAGzG7B,EAAoB8B,EAAI,IAExB,IAAIC,EAAaC,KAAmB,aAAIA,KAAmB,cAAK,GAC5DC,EAAmBF,EAAW5C,KAAKuC,KAAKK,GAC5CA,EAAW5C,KAAOf,EAClB2D,EAAaA,EAAWG,QACxB,IAAI,IAAIvD,EAAI,EAAGA,EAAIoD,EAAWlD,OAAQF,IAAKP,EAAqB2D,EAAWpD,IAC3E,IAAIU,EAAsB4C,EAI1BxC,I","file":"static/js/runtime~app.2e9f1821.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t1: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n \tvar jsonpArray = this[\"webpackJsonp\"] = this[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// run deferred modules from other chunks\n \tcheckDeferredModules();\n"],"sourceRoot":""} -------------------------------------------------------------------------------- /components/SearchResults.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | import { 3 | StyleSheet, 4 | Text, 5 | View, 6 | Image, 7 | TouchableOpacity, 8 | FlatList 9 | } from "react-native"; 10 | import { useSelector } from "react-redux"; 11 | import { ActivityIndicator } from "react-native-paper"; 12 | import * as Linking from "expo-linking"; 13 | import { MaterialIcons } from "@expo/vector-icons"; 14 | import { gql, useLazyQuery } from "@apollo/client"; 15 | 16 | const GET_USERS = gql` 17 | query SearchUsers($userQuery: String!) { 18 | search(query: $userQuery, type: USER, first: 20) { 19 | edges { 20 | node { 21 | ... on User { 22 | avatarUrl 23 | id 24 | login 25 | url 26 | } 27 | } 28 | } 29 | } 30 | } 31 | `; 32 | 33 | const GET_REPOSITORIES = gql` 34 | query SearchRepositories($userQuery: String!) { 35 | search(query: $userQuery, type: REPOSITORY, first: 20) { 36 | edges { 37 | node { 38 | ... on Repository { 39 | id 40 | url 41 | description 42 | stargazerCount 43 | nameWithOwner 44 | owner { 45 | avatarUrl 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | `; 53 | 54 | export default function SearchResults() { 55 | const query = useSelector((state) => state.query.text); 56 | const option = useSelector((state) => state.searchOption.value); 57 | const darkMode = useSelector((state) => state.darkMode.theme); 58 | 59 | const textStyle = darkMode ? styles.darkModeText : null; 60 | const backgroundStyle = darkMode ? styles.darkModeBackground : null; 61 | 62 | const [getUsers, { loading: loadingUsers, data: userData }] = useLazyQuery( 63 | GET_USERS, 64 | { 65 | variables: { userQuery: query } 66 | } 67 | ); 68 | 69 | const [ 70 | getRepositories, 71 | { loading: loadingRepositories, data: repositoryData } 72 | ] = useLazyQuery(GET_REPOSITORIES, { 73 | variables: { userQuery: query } 74 | }); 75 | 76 | const options = userData || repositoryData; 77 | 78 | //repositoryData.search.edges 79 | 80 | useEffect(() => { 81 | if (query.length >= 3) { 82 | const timeoutId = setTimeout(() => handleNewSearch(), 1000); 83 | return () => clearTimeout(timeoutId); 84 | } 85 | }, [query]); 86 | 87 | const handleNewSearch = () => { 88 | if (option === "users") { 89 | getUsers(); 90 | } else { 91 | getRepositories(); 92 | } 93 | }; 94 | 95 | if (query === "") { 96 | return null; 97 | } 98 | 99 | return ( 100 | 101 | {(loadingUsers || loadingRepositories) && ( 102 | 103 | )} 104 | 105 | {options && ( 106 | item.node.id} 114 | data={options.search.edges} 115 | indicatorStyle="black" 116 | initialNumToRender={10} 117 | renderItem={({ item }) => ( 118 | Linking.openURL(`${item.node.url}`)} 120 | > 121 | {option === "users" && ( 122 | 123 | 124 | 128 | 129 | 130 | 135 | {item.node.login} 136 | 137 | 138 | 139 | )} 140 | 141 | {option === "repositories" && ( 142 | 143 | 144 | 148 | 149 | 150 | 158 | 159 | 164 | {item.node.nameWithOwner} 165 | 166 | 167 | 168 | 169 | 170 | 175 | 176 | 177 | 178 | 179 | {item.node.stargazerCount} 180 | 181 | 182 | 183 | 184 | 185 | 190 | {item.node.description} 191 | 192 | 193 | 194 | 195 | )} 196 | 197 | )} 198 | /> 199 | )} 200 | 201 | ); 202 | } 203 | 204 | const styles = StyleSheet.create({ 205 | screenContainer: { 206 | maxHeight: 300, 207 | marginTop: 10, 208 | borderWidth: 1, 209 | borderColor: "#E8E8E8", 210 | borderTopLeftRadius: 10, 211 | borderBottomLeftRadius: 10, 212 | borderRadius: 10, 213 | overflow: "hidden" 214 | }, 215 | itemContainer: { 216 | flexDirection: "row", 217 | padding: 5, 218 | paddingLeft: 10, 219 | borderBottomWidth: 1, 220 | borderColor: "#F2F2F2", 221 | alignItems: "center" 222 | }, 223 | starSnippetContainer: { 224 | borderWidth: 1, 225 | borderColor: "#D9DBDB", 226 | borderRadius: 10, 227 | height: 25, 228 | width: 110, 229 | minWidth: 90, 230 | flexDirection: "row", 231 | alignItems: "center", 232 | justifyContent: "center", 233 | flex: 1 234 | }, 235 | starIconBox: { 236 | height: "100%", 237 | flexDirection: "row", 238 | borderRightWidth: 1, 239 | borderTopLeftRadius: 10, 240 | borderBottomLeftRadius: 10, 241 | borderRightColor: "#D9DBDB", 242 | backgroundColor: "#FAFBFC", 243 | alignItems: "center", 244 | paddingLeft: 5, 245 | paddingRight: 5 246 | // padding: 10, 247 | }, 248 | image: { height: 40, width: 40, marginRight: 10 }, 249 | darkModeText: { 250 | color: "white" 251 | }, 252 | boldText: { 253 | fontWeight: "bold" 254 | }, 255 | darkModeBackground: { 256 | backgroundColor: "black" 257 | } 258 | }); 259 | -------------------------------------------------------------------------------- /web-build/static/js/app.cc664779.chunk.js: -------------------------------------------------------------------------------- 1 | (this.webpackJsonp=this.webpackJsonp||[]).push([[0],{201:function(e,t,r){"use strict";r.d(t,"a",(function(){return he}));var n=r(13),a=r.n(n),o=r(0),c=r.n(o),i=r(200),l=r(204),u=r(26),s=r(72),d=r(54),m=r(159);function f(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function y(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:p,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"TOGGLE_OPTION":return y(y({},e),{},{value:t.payload});default:return e}};function g(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function h(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:E,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"UPDATE_QUERY":return h(h({},e),{},{text:t.payload});case"RESET_QUERY":return h(h({},e),{},{text:""});default:return e}};function j(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function k(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:v,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case"TOGGLE_THEME":return k(k({},e),{},{theme:!e.theme});default:return e}},C=Object(s.b)({query:O,searchOption:b,darkMode:w}),x=r(21),P=r(5),M=r(4),T=r(202),D=r(25),R=r(127),S=r(126),I=r(27),F=r(260),L=r(164),B=r.n(L),z=I.a.statusBarHeight;function U(){var e=Object(u.b)(),t=Object(u.c)((function(e){return e.darkMode.theme})),r=t?Q.darkModeContainer:null,n=t?Q.darkModeText:null;return c.a.createElement(M.a,{style:[Q.container,r]},c.a.createElement(M.a,{style:Q.item},c.a.createElement(D.a,{style:n},"Onur Eker")),c.a.createElement(M.a,{style:{flexDirection:"row"}},c.a.createElement(M.a,{style:Q.item},c.a.createElement(B.a,{onChange:function(){e({type:"TOGGLE_THEME"})},checked:t,height:26,offColor:"#3D3F47",onColor:"#134484",uncheckedIcon:c.a.createElement(M.a,{style:{flex:1,justifyContent:"center",alignItems:"center",height:"100%"}},c.a.createElement(M.a,null,c.a.createElement(F.a,{color:"yellow",name:"md-sunny",size:18}))," "),checkedIcon:c.a.createElement(M.a,{style:{flex:1,justifyContent:"center",alignItems:"center",height:"100%"}},c.a.createElement(M.a,null,c.a.createElement(F.a,{color:"yellow",name:"md-moon",size:18}))," ")})),c.a.createElement(M.a,{style:Q.item},c.a.createElement(S.a,{onPress:function(){return R.a.openURL("https://www.linkedin.com/in/onureker/")}},c.a.createElement(D.a,{style:n},c.a.createElement(F.a,{name:"logo-linkedin",size:14})," LinkedIn"))),c.a.createElement(M.a,{style:Q.item},c.a.createElement(S.a,{onPress:function(){return R.a.openURL("https://github.com/yonureker/")}},c.a.createElement(D.a,{style:n},c.a.createElement(F.a,{name:"logo-github",size:14})," Github")))))}var Q=P.a.create({container:{width:"100%",alignItems:"center",justifyContent:"space-between",position:"absolute",top:"android"===x.a.OS?z:0,flexDirection:"row",paddingRight:10,paddingLeft:10,backgroundColor:"#F2F2F2"},item:{padding:10,justifyContent:"center",alignItems:"center"},darkModeText:{color:"white"},darkModeContainer:{backgroundColor:"#2B2828"}}),G=r(61);function W(){return c.a.createElement(M.a,{style:q.container},c.a.createElement(G.a,{source:r(235),style:q.image}))}var q=P.a.create({container:{alignItems:"center",justifyContent:"center"},image:{aspectRatio:5.5,resizeMode:"contain",width:276,height:50}}),_=r(203);function H(){var e=Object(u.b)(),t=Object(u.c)((function(e){return e.query.text})),r=Object(u.c)((function(e){return e.darkMode.theme})),n=r?Y.darkModeContainer:null,a=r?Y.darkModeText:null;return c.a.createElement(_.a,{placeholder:"Search",placeholderTextColor:a,onChangeText:function(t){return e({type:"UPDATE_QUERY",payload:t})},value:t,style:[Y.container,n],inputStyle:a,iconColor:r?"white":"black"})}var Y=P.a.create({container:{marginTop:20,borderWidth:1,borderColor:"#DFE1E5"},darkModeContainer:{backgroundColor:"black"},darkModeText:{color:"white"}}),A=r(115);function N(){var e=Object(u.b)(),t=Object(u.c)((function(e){return e.searchOption.value})),r=Object(u.c)((function(e){return e.darkMode.theme}))?$.darkModeText:null;return c.a.createElement(A.a.Group,{onValueChange:function(t){e({type:"TOGGLE_OPTION",payload:t}),e({type:"RESET_QUERY"})},value:t},c.a.createElement(M.a,{style:{flexDirection:"row",justifyContent:"space-evenly"}},c.a.createElement(M.a,{style:$.container},c.a.createElement(A.a,{value:"users",uncheckedColor:"gray",status:"users"===t?"checked":"unchecked"}),c.a.createElement(D.a,{style:r},"Search Users")),c.a.createElement(M.a,{style:$.container},c.a.createElement(A.a,{value:"repositories",uncheckedColor:"gray",status:"repositories"===t?"checked":"unchecked"}),c.a.createElement(D.a,{style:r},"Search Repositories"))))}var $=P.a.create({container:{flexDirection:"row",justifyContent:"center",alignItems:"center"},darkModeText:{color:"white"}}),J=r(50),V=r.n(J),Z=r(131),K=r.n(Z),X=r(197),ee=r(111),te=r(206),re=r(205),ne=r(262);function ae(){var e=K()(["\n query SearchRepositories($userQuery: String!) {\n search(query: $userQuery, type: REPOSITORY, first: 20) {\n edges {\n node {\n ... on Repository {\n id\n url\n description\n stargazerCount\n nameWithOwner\n owner {\n avatarUrl\n }\n }\n }\n }\n }\n }\n"]);return ae=function(){return e},e}function oe(){var e=K()(["\n query SearchUsers($userQuery: String!) {\n search(query: $userQuery, type: USER, first: 20) {\n edges {\n node {\n ... on User {\n avatarUrl\n id\n login\n url\n }\n }\n }\n }\n }\n"]);return oe=function(){return e},e}var ce=Object(d.gql)(oe()),ie=Object(d.gql)(ae());function le(){var e=Object(u.c)((function(e){return e.query.text})),t=Object(u.c)((function(e){return e.searchOption.value})),r=Object(u.c)((function(e){return e.darkMode.theme})),n=r?ue.darkModeText:null,a=r?ue.darkModeBackground:null,i=Object(d.useLazyQuery)(ce,{variables:{userQuery:e}}),l=V()(i,2),s=l[0],m=l[1],f=m.loading,y=m.data,p=Object(d.useLazyQuery)(ie,{variables:{userQuery:e}}),b=V()(p,2),g=b[0],h=b[1],E=h.loading,O=h.data,j=y||O;Object(o.useEffect)((function(){if(e.length>=3){var t=setTimeout((function(){return k()}),1e3);return function(){return clearTimeout(t)}}}),[e]);var k=function(){"users"===t?s():g()};return""===e?null:c.a.createElement(M.a,{style:ue.screenContainer},(f||E)&&c.a.createElement(te.a,{style:{padding:10},size:"large",animating:!0}),j&&c.a.createElement(ee.a,{style:{maxHeight:280},keyExtractor:function(e){return e.node.id},data:j.search.edges,indicatorStyle:"black",initialNumToRender:10,renderItem:function(e){var r=e.item;return c.a.createElement(X.a,{onPress:function(){return re.a(""+r.node.url)}},"users"===t&&c.a.createElement(M.a,{style:ue.itemContainer},c.a.createElement(M.a,null,c.a.createElement(G.a,{source:{uri:""+r.node.avatarUrl},style:ue.image})),c.a.createElement(M.a,null,c.a.createElement(D.a,{numberOfLines:1,ellipsizeMode:"tail",style:n},r.node.login))),"repositories"===t&&c.a.createElement(M.a,{style:ue.itemContainer},c.a.createElement(M.a,null,c.a.createElement(G.a,{source:{uri:""+r.node.owner.avatarUrl},style:ue.image})),c.a.createElement(M.a,{style:{flex:1}},c.a.createElement(M.a,{style:{flex:1,flexDirection:"row",alignItems:"center",justifyContent:"space-between"}},c.a.createElement(M.a,{style:{flex:10}},c.a.createElement(D.a,{style:[n,ue.boldText],numberOfLines:1,ellipsizeMode:"tail"},r.node.nameWithOwner)),c.a.createElement(M.a,{style:ue.starSnippetContainer},c.a.createElement(M.a,{style:[ue.starIconBox,a]},c.a.createElement(M.a,null,c.a.createElement(ne.a,{name:"star-border",size:16,color:"gray"}))),c.a.createElement(M.a,{style:{flex:1}},c.a.createElement(D.a,{style:[{alignSelf:"center"},n]},r.node.stargazerCount)))),c.a.createElement(M.a,{style:{marginTop:2}},c.a.createElement(D.a,{numberOfLines:1,ellipsizeMode:"tail",style:n},r.node.description)))))}}))}var ue=P.a.create({screenContainer:{maxHeight:300,marginTop:10,borderWidth:1,borderColor:"#E8E8E8",borderTopLeftRadius:10,borderBottomLeftRadius:10,borderRadius:10,overflow:"hidden"},itemContainer:{flexDirection:"row",padding:5,paddingLeft:10,borderBottomWidth:1,borderColor:"#F2F2F2",alignItems:"center"},starSnippetContainer:{borderWidth:1,borderColor:"#D9DBDB",borderRadius:10,height:25,width:110,minWidth:90,flexDirection:"row",alignItems:"center",justifyContent:"center",flex:1},starIconBox:{height:"100%",flexDirection:"row",borderRightWidth:1,borderTopLeftRadius:10,borderBottomLeftRadius:10,borderRightColor:"#D9DBDB",backgroundColor:"#FAFBFC",alignItems:"center",paddingLeft:5,paddingRight:5},image:{height:40,width:40,marginRight:10},darkModeText:{color:"white"},boldText:{fontWeight:"bold"},darkModeBackground:{backgroundColor:"black"}});function se(){return c.a.createElement(M.a,{style:de.container},c.a.createElement(N,null),c.a.createElement(H,null),c.a.createElement(le,null))}var de=P.a.create({container:{height:150,width:"100%",maxWidth:600,padding:10,marginBottom:150}});function me(){var e=Object(u.c)((function(e){return e.darkMode.theme})),t=e?fe.darkModeText:null,r=e?fe.darkModeContainer:null;return c.a.createElement(M.a,{style:[fe.container,r]},c.a.createElement(M.a,{style:fe.item},c.a.createElement(D.a,{style:t},"Built with React Native Web ",c.a.createElement(F.a,{name:"heart",size:14,color:"red"}))))}var fe=P.a.create({container:{position:"absolute",bottom:0,zIndex:99,elevation:99,backgroundColor:"#F2F2F2",width:"100%"},item:{padding:10,justifyContent:"center",alignItems:"center"},darkModeText:{color:"white"},darkModeContainer:{backgroundColor:"#2B2828"}});function ye(){var e=Object(u.c)((function(e){return e.darkMode.theme}))?pe.darkModeContainer:null;return c.a.createElement(M.a,{style:[pe.container,e]},c.a.createElement(U,null),c.a.createElement(W,null),c.a.createElement(se,null),"web"===x.a.OS&&c.a.createElement(me,null),c.a.createElement(T.a,{backgroundColor:"#F2F2F2"}))}var pe=P.a.create({container:{flex:1,backgroundColor:"#fff",alignItems:"center",justifyContent:"center"},darkModeContainer:{backgroundColor:"black"}});function be(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function ge(e){for(var t=1;t {\n switch(action.type) {\n case \"TOGGLE_OPTION\":\n return {...state, value: action.payload};\n break;\n default:\n return state;\n }\n}\n\nexport default searchOptionReducer;","const initialState = {text: ''}\n\nconst searchQueryReducer = (state = initialState, action) => {\n switch(action.type) {\n case \"UPDATE_QUERY\":\n return {...state, text: action.payload};\n break;\n case \"RESET_QUERY\":\n return {...state, text: ''};\n break;\n default:\n return state;\n }\n}\n\nexport default searchQueryReducer;","const initialState = {\n theme: false\n}\n\nconst darkModeReducer = (state = initialState, action) => {\n switch (action.type) {\n case \"TOGGLE_THEME\":\n return {...state, theme: !state.theme}\n break;\n default:\n return state;\n }\n}\n\nexport default darkModeReducer;","import { combineReducers } from 'redux';\nimport searchOptionReducer from './searchOptionReducer';\nimport searchQueryReducer from './searchQueryReducer';\nimport darkModeReducer from './darkModeReducer'\n\nconst rootReducer = combineReducers({\n query: searchQueryReducer,\n searchOption: searchOptionReducer,\n darkMode: darkModeReducer\n});\n\nexport default rootReducer;","import React, { useState } from \"react\";\nimport {\n StyleSheet,\n Text,\n View,\n Linking,\n Pressable,\n Platform,\n} from \"react-native\";\nimport Constants from \"expo-constants\";\nimport { Ionicons } from \"@expo/vector-icons\";\nimport { useDispatch, useSelector } from \"react-redux\";\nimport Switch from \"react-switch\";\n\nconst STATUSBAR_HEIGHT = Constants.statusBarHeight;\n\nexport default function Header() {\n const dispatch = useDispatch();\n const darkMode = useSelector(state => state.darkMode.theme);\n\n const containerStyle = darkMode ? styles.darkModeContainer : null\n const textStyle = darkMode ? styles.darkModeText : null;\n\n const handleChange = () => {\n dispatch({\n type: \"TOGGLE_THEME\"\n })\n };\n\n // const toggleDarkMode = () => ()\n\n return (\n \n \n Onur Eker\n \n \n \n \n \n \n {\" \"}\n \n }\n checkedIcon={\n \n \n \n {\" \"}\n \n }\n />\n \n \n \n Linking.openURL(`https://www.linkedin.com/in/onureker/`)\n }\n >\n \n LinkedIn\n \n \n \n \n Linking.openURL(`https://github.com/yonureker/`)}\n >\n \n Github\n \n \n \n \n \n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n width: \"100%\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n position: \"absolute\",\n top: Platform.OS === \"android\" ? STATUSBAR_HEIGHT : 0,\n flexDirection: \"row\",\n paddingRight: 10,\n paddingLeft: 10,\n backgroundColor: \"#F2F2F2\",\n },\n item: {\n padding: 10,\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n darkModeText : {\n color: 'white'\n },\n darkModeContainer : {\n backgroundColor: '#2B2828',\n },\n});\n","import React from 'react'\nimport { View, Image, StyleSheet } from 'react-native'\n\nexport default function Logo() {\n return (\n \n \n \n )\n}\n\nconst styles = StyleSheet.create({\n container: {\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n image: {\n aspectRatio: 5.5,\n resizeMode: 'contain',\n width: 276,\n height: 50\n }\n})\n\n","import React from 'react'\nimport { StyleSheet } from 'react-native';\nimport { Searchbar } from 'react-native-paper';\nimport { useDispatch, useSelector } from 'react-redux';\n\nexport default function SearchBar() {\n const dispatch = useDispatch();\n const query = useSelector(state => state.query.text)\n const darkMode = useSelector(state => state.darkMode.theme)\n\n const containerStyle = darkMode ? styles.darkModeContainer : null\n const textStyle = darkMode ? styles.darkModeText : null;\n\n const onChangeSearch = (newQuery : string) => dispatch({type: \"UPDATE_QUERY\", payload: newQuery});\n\n return (\n \n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n marginTop: 20,\n borderWidth: 1,\n borderColor: '#DFE1E5'\n },\n darkModeContainer : {\n backgroundColor: 'black',\n },\n darkModeText : {\n color: 'white'\n }\n})\n","import React from \"react\";\nimport { StyleSheet, Text, View } from \"react-native\";\nimport { RadioButton } from \"react-native-paper\";\nimport { useDispatch, useSelector } from \"react-redux\";\n\nexport default function RadioButtonContainer() {\n const dispatch = useDispatch();\n const option = useSelector((state) => state.searchOption.value);\n const darkMode = useSelector(state => state.darkMode.theme)\n \n const textStyle = darkMode ? styles.darkModeText : null;\n\n\n return (\n {\n dispatch({ type: \"TOGGLE_OPTION\", payload: newValue })\n dispatch({type: \"RESET_QUERY\"})\n }\n }\n value={option}\n >\n \n \n \n Search Users\n \n \n \n Search Repositories\n \n {/* \n \n Search Topics\n */}\n \n \n );\n}\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: \"row\",\n justifyContent: \"center\",\n alignItems: \"center\",\n },\n darkModeText : {\n color: 'white'\n }\n});\n","import React, { useState, useEffect } from \"react\";\nimport {\n StyleSheet,\n Text,\n View,\n Image,\n TouchableOpacity,\n FlatList\n} from \"react-native\";\nimport { useSelector } from \"react-redux\";\nimport { ActivityIndicator } from \"react-native-paper\";\nimport * as Linking from \"expo-linking\";\nimport { MaterialIcons } from \"@expo/vector-icons\";\nimport { gql, useLazyQuery } from \"@apollo/client\";\n\nconst GET_USERS = gql`\n query SearchUsers($userQuery: String!) {\n search(query: $userQuery, type: USER, first: 20) {\n edges {\n node {\n ... on User {\n avatarUrl\n id\n login\n url\n }\n }\n }\n }\n }\n`;\n\nconst GET_REPOSITORIES = gql`\n query SearchRepositories($userQuery: String!) {\n search(query: $userQuery, type: REPOSITORY, first: 20) {\n edges {\n node {\n ... on Repository {\n id\n url\n description\n stargazerCount\n nameWithOwner\n owner {\n avatarUrl\n }\n }\n }\n }\n }\n }\n`;\n\nexport default function SearchResults() {\n const query = useSelector((state) => state.query.text);\n const option = useSelector((state) => state.searchOption.value);\n const darkMode = useSelector((state) => state.darkMode.theme);\n\n const textStyle = darkMode ? styles.darkModeText : null;\n const backgroundStyle = darkMode ? styles.darkModeBackground : null;\n\n const [getUsers, { loading: loadingUsers, data: userData }] = useLazyQuery(\n GET_USERS,\n {\n variables: { userQuery: query }\n }\n );\n\n const [\n getRepositories,\n { loading: loadingRepositories, data: repositoryData }\n ] = useLazyQuery(GET_REPOSITORIES, {\n variables: { userQuery: query }\n });\n\n const options = userData || repositoryData;\n\n //repositoryData.search.edges\n\n useEffect(() => {\n if (query.length >= 3) {\n const timeoutId = setTimeout(() => handleNewSearch(), 1000);\n return () => clearTimeout(timeoutId);\n }\n }, [query]);\n\n const handleNewSearch = () => {\n if (option === \"users\") {\n getUsers();\n } else {\n getRepositories();\n }\n };\n\n if (query === \"\") {\n return null;\n }\n\n return (\n \n {(loadingUsers || loadingRepositories) && (\n \n )}\n\n {options && (\n item.node.id}\n data={options.search.edges}\n indicatorStyle=\"black\"\n initialNumToRender={10}\n renderItem={({ item }) => (\n Linking.openURL(`${item.node.url}`)}\n >\n {option === \"users\" && (\n \n \n \n \n \n \n {item.node.login}\n \n \n \n )}\n\n {option === \"repositories\" && (\n \n \n \n \n \n \n \n \n {item.node.nameWithOwner}\n \n \n \n \n \n \n \n \n \n \n {item.node.stargazerCount}\n \n \n \n \n \n \n {item.node.description}\n \n \n \n \n )}\n \n )}\n />\n )}\n \n );\n}\n\nconst styles = StyleSheet.create({\n screenContainer: {\n maxHeight: 300,\n marginTop: 10,\n borderWidth: 1,\n borderColor: \"#E8E8E8\",\n borderTopLeftRadius: 10,\n borderBottomLeftRadius: 10,\n borderRadius: 10,\n overflow: \"hidden\"\n },\n itemContainer: {\n flexDirection: \"row\",\n padding: 5,\n paddingLeft: 10,\n borderBottomWidth: 1,\n borderColor: \"#F2F2F2\",\n alignItems: \"center\"\n },\n starSnippetContainer: {\n borderWidth: 1,\n borderColor: \"#D9DBDB\",\n borderRadius: 10,\n height: 25,\n width: 110,\n minWidth: 90,\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flex: 1\n },\n starIconBox: {\n height: \"100%\",\n flexDirection: \"row\",\n borderRightWidth: 1,\n borderTopLeftRadius: 10,\n borderBottomLeftRadius: 10,\n borderRightColor: \"#D9DBDB\",\n backgroundColor: \"#FAFBFC\",\n alignItems: \"center\",\n paddingLeft: 5,\n paddingRight: 5\n // padding: 10,\n },\n image: { height: 40, width: 40, marginRight: 10 },\n darkModeText: {\n color: \"white\"\n },\n boldText: {\n fontWeight: \"bold\"\n },\n darkModeBackground: {\n backgroundColor: \"black\"\n }\n});\n","import React, {useState} from 'react'\nimport { StyleSheet, Text, View } from 'react-native'\nimport SearchBar from './SearchBar'\nimport RadioButtonContainer from './RadioButtonContainer'\nimport SearchResults from './SearchResults';\n\nexport default function SearchContainer() {\n\n\n return (\n \n \n \n \n \n )\n}\n\nconst styles = StyleSheet.create({\n container: {\n height: 150,\n width: '100%',\n maxWidth: 600,\n padding: 10,\n marginBottom: 150\n }\n})\n","import React from 'react'\nimport { StyleSheet, Text, View } from 'react-native';\nimport { Ionicons } from \"@expo/vector-icons\"; \nimport { useDispatch, useSelector } from 'react-redux';\n\nexport default function Footer() {\n const darkMode = useSelector(state => state.darkMode.theme)\n const textStyle = darkMode ? styles.darkModeText : null;\n const containerStyle = darkMode ? styles.darkModeContainer : null\n\n return (\n \n \n Built with React Native Web \n \n \n )\n}\n\nconst styles = StyleSheet.create({\n container: {\n position: 'absolute',\n bottom: 0,\n zIndex: 99,\n elevation: 99,\n backgroundColor: '#F2F2F2',\n width: '100%'\n },\n item: {\n padding: 10,\n justifyContent: 'center',\n alignItems: 'center'\n },\n darkModeText : {\n color: 'white'\n },\n darkModeContainer : {\n backgroundColor: '#2B2828',\n },\n})\n","import React from 'react'\nimport { Platform, SafeAreaView, StyleSheet, Text, View } from \"react-native\";\nimport { StatusBar } from \"expo-status-bar\";\nimport { useSelector } from \"react-redux\";\n\nimport Header from \"../components/Header\";\nimport Logo from \"../components/Logo\";\nimport SearchContainer from \"../components/SearchContainer\";\nimport Footer from \"../components/Footer\";\n\nexport default function Main() {\n const darkMode = useSelector(state => state.darkMode.theme)\n const containerStyle = darkMode ? styles.darkModeContainer : null\n\n return (\n \n \n \n \n {Platform.OS === \"web\" && }\n \n \n )\n}\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n backgroundColor: \"#fff\",\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n darkModeContainer : {\n backgroundColor: 'black'\n }\n});\n","import React from \"react\";\nimport { Platform, SafeAreaView, StyleSheet, Text, View } from \"react-native\";\nimport { Provider as PaperProvider } from \"react-native-paper\";\nimport { Provider, useSelector } from \"react-redux\";\nimport { createStore } from \"redux\";\nimport {\n ApolloClient,\n InMemoryCache,\n ApolloProvider,\n HttpLink\n} from \"@apollo/client\";\nimport { setContext } from \"@apollo/client/link/context\";\nimport { TOKEN } from \"react-native-dotenv\";\n\nimport rootReducer from \"./reducers/rootReducer\";\nimport Main from \"./components/Main\";\n\nconst githubToken = TOKEN;\n\nexport default function App() {\n const store = createStore(rootReducer);\n\n const httpLink = new HttpLink({\n uri: \"https://api.github.com/graphql\"\n });\n\n const authLink = setContext((_, { headers }) => {\n // get the authentication token from local storage if it exists\n const token = \"Bearer \" + githubToken;\n // return the headers to the context so httpLink can read them\n return {\n headers: {\n ...headers,\n authorization: token ? token : null\n }\n };\n });\n\n const client = new ApolloClient({\n link: authLink.concat(httpLink),\n cache: new InMemoryCache()\n });\n\n return (\n \n \n \n \n \n \n \n \n \n );\n}\n","module.exports = __webpack_public_path__ + \"static/media/logo.f1c5195b.png\";"],"sourceRoot":""} --------------------------------------------------------------------------------
Oh no! It looks like JavaScript is not enabled in your browser.
Reload