From 5e3e586a4e6bb4d2dbf1e95070bcb0c83488fcc1 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 10:20:21 +0200 Subject: [PATCH 01/69] Added autocomplete input dependency --- package.json | 1 + yarn.lock | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/package.json b/package.json index b6d1cdc..231c3e0 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react": "16.3.1", "react-native": "https://github.com/expo/react-native/archive/sdk-27.0.0.tar.gz", "react-native-animatable": "^1.2.4", + "react-native-autocomplete-input": "^3.5.0", "react-native-fade-in-image": "1.3.0", "react-native-gravatar": "^1.0.2", "react-native-paper": "^1.2.6", diff --git a/yarn.lock b/yarn.lock index a1d5bdb..3ca363d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5032,6 +5032,12 @@ react-native-animatable@^1.2.4: dependencies: prop-types "^15.5.10" +react-native-autocomplete-input@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/react-native-autocomplete-input/-/react-native-autocomplete-input-3.5.0.tgz#2e52e3865abf1ad3e8d04f7e39f5314c03a89e4d" + dependencies: + prop-types "^15.5.10" + react-native-branch@2.0.0-beta.3: version "2.0.0-beta.3" resolved "https://registry.yarnpkg.com/react-native-branch/-/react-native-branch-2.0.0-beta.3.tgz#2167af86bbc9f964bd45bd5f37684e5b54965e32" From 8a4567def7423055245f4d3ffee9709e9c33469e Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 10:24:55 +0200 Subject: [PATCH 02/69] Fix unhandled nextTalks promise, and add Screen + Navigation for Attendees (not functional) --- src/Navigation.js | 2 ++ src/components/TalksUpNext.js | 4 ++-- src/screens/Attendees.js | 9 +++++++++ src/screens/index.js | 5 ++++- 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/screens/Attendees.js diff --git a/src/Navigation.js b/src/Navigation.js index 3871f73..456630e 100644 --- a/src/Navigation.js +++ b/src/Navigation.js @@ -145,6 +145,7 @@ const DrawerRouteConfig = { Profile: { screen: Screens.Profile }, Contacts: { screen: Screens.Contacts }, StaffCheckinLists: { screen: StaffCheckinListsNavigation }, + Attendees: { screen: Screens.Attendees }, }; const DrawerRouter = TabRouter(DrawerRouteConfig); @@ -369,6 +370,7 @@ class DrawerView extends React.Component { { route: 'Sponsors', title: 'Sponsors' }, { route: 'Profile', title: 'Profile' }, { route: 'Contacts', title: 'Contacts' }, + { route: 'Attendees', title: 'Attendees' }, { route: 'StaffCheckinLists', title: 'StaffCheckinLists', diff --git a/src/components/TalksUpNext.js b/src/components/TalksUpNext.js index cc4da34..c78623e 100644 --- a/src/components/TalksUpNext.js +++ b/src/components/TalksUpNext.js @@ -87,8 +87,8 @@ export default class TalksUpNext extends React.Component { 0, 3 ), - dateTime: nextTalks[0].startDate, - time: nextTalks[0].startDate + dateTime: nextTalks && nextTalks.length ? nextTalks[0].startDate : '', + time: nextTalks && nextTalks.length ? nextTalks[0].startDate : '' }); } else { that.setState({ nextTalks: [] }); diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js new file mode 100644 index 0000000..0202e6c --- /dev/null +++ b/src/screens/Attendees.js @@ -0,0 +1,9 @@ +import React, { Component } from 'react' + +class Attendees extends Component { + render() { + return
ATTENDEES
+ } +} + +export default Attendees \ No newline at end of file diff --git a/src/screens/index.js b/src/screens/index.js index bebbeac..833dac5 100644 --- a/src/screens/index.js +++ b/src/screens/index.js @@ -9,6 +9,8 @@ import Contacts from "./Contacts"; import TicketInstructions from "./TicketInstructions"; import StaffCheckinLists from "./StaffCheckinLists"; import CheckedInAttendeeInfo from "./CheckedInAttendeeInfo"; +import Attendees from "./Attendees"; + export default { Home, Crew, @@ -20,5 +22,6 @@ export default { Contacts, TicketInstructions, StaffCheckinLists, - CheckedInAttendeeInfo + CheckedInAttendeeInfo, + Attendees, }; From 13e813929bd70e7f113409fdc354fc6dfaecaefb Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 10:41:45 +0200 Subject: [PATCH 03/69] add attendeesquery --- src/data/attendeesquery.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/data/attendeesquery.js diff --git a/src/data/attendeesquery.js b/src/data/attendeesquery.js new file mode 100644 index 0000000..070419a --- /dev/null +++ b/src/data/attendeesquery.js @@ -0,0 +1,21 @@ +export const attendeesquery = ` +{ + events(slug: "reacteurope-2018") { + attendees(q:"a", uuid:"f35ad898-fe07-49cc-bd55-c4fbb59ac1b7") { + id + lastName + email + firstName + answers { + id + value + question { + id + title + } + } + + } + } + } +`; \ No newline at end of file From 473b07fa008c4d820d00d9217f346dac2b4340f6 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 10:46:23 +0200 Subject: [PATCH 04/69] add react-apollo --- package.json | 1 + yarn.lock | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/package.json b/package.json index 231c3e0..db357c6 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "path": "^0.12.7", "prettier": "^1.11.1", "react": "16.3.1", + "react-apollo": "^2.1.4", "react-native": "https://github.com/expo/react-native/archive/sdk-27.0.0.tar.gz", "react-native-animatable": "^1.2.4", "react-native-autocomplete-input": "^3.5.0", diff --git a/yarn.lock b/yarn.lock index 3ca363d..f2e949f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3974,6 +3974,10 @@ lodash.zipobject@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz#b399f5aba8ff62a746f6979bf20b214f964dbef8" +lodash@4.17.5: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + lodash@^3.5.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" @@ -4978,6 +4982,16 @@ rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-apollo@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-2.1.4.tgz#a51059ac56f1a7997cad636a5d36398b9c93ff12" + dependencies: + fbjs "^0.8.16" + hoist-non-react-statics "^2.5.0" + invariant "^2.2.2" + lodash "4.17.5" + prop-types "^15.6.0" + react-clone-referenced-element@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz#2bba8c69404c5e4a944398600bcc4c941f860682" From 12b9a69e3b7c4285211c1c5f6e9d9f7a2c3c305b Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 11:09:07 +0200 Subject: [PATCH 05/69] implement graphql query using react-apollo --- App.js | 21 +++++++- package.json | 4 ++ src/Navigation.js | 2 +- src/data/attendeesquery.js | 42 ++++++++------- src/screens/Attendees.js | 21 ++++++-- yarn.lock | 107 ++++++++++++++++++++++++++++++++++++- 6 files changed, 171 insertions(+), 26 deletions(-) diff --git a/App.js b/App.js index 733d163..b9e7cbe 100644 --- a/App.js +++ b/App.js @@ -1,7 +1,12 @@ import React from "react"; +import { ApolloClient } from 'apollo-client'; +import { ApolloProvider } from 'react-apollo'; +import { HttpLink } from 'apollo-link-http'; +import { InMemoryCache } from 'apollo-cache-inmemory'; import { Asset, AppLoading, Font, Updates } from "expo"; import { AsyncStorage, Alert, Platform, View } from "react-native"; import { Ionicons } from "@expo/vector-icons"; +import { GQL } from './src/constants' import { loadSavedTalksAsync } from "./src/utils/storage"; import { SafeAreaView } from "react-navigation"; import { ScheduleQuery } from "./src/data/schedulequery"; @@ -10,6 +15,15 @@ if (Platform.OS === "android") { SafeAreaView.setStatusBarHeight(0); } +const client = new ApolloClient({ + // By default, this client will send queries to the + // `/graphql` endpoint on the same host + // Pass the configuration option { uri: YOUR_GRAPHQL_API_URL } to the `HttpLink` to connect + // to a different host + link: new HttpLink({ uri: GQL.uri }), + cache: new InMemoryCache(), +}); + import Navigation from "./src/Navigation"; export default class App extends React.Component { @@ -84,7 +98,10 @@ export default class App extends React.Component { /> ); } - - return ; + return ( + + + + ); } } diff --git a/package.json b/package.json index db357c6..264f2c2 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,14 @@ "devtools": "react-devtools" }, "dependencies": { + "apollo-client": "^2.3.1", + "apollo-client-preset": "^1.0.8", "crypto-js": "^3.1.9-1", "expo": "^27.0.0", "fbemitter": "^2.1.1", "global": "^4.3.2", + "graphql": "^0.13.2", + "graphql-tag": "^2.9.2", "hoist-non-react-statics": "^2.3.1", "lodash": "^4.17.4", "moment": "2.21.0", diff --git a/src/Navigation.js b/src/Navigation.js index 456630e..a33ff50 100644 --- a/src/Navigation.js +++ b/src/Navigation.js @@ -370,12 +370,12 @@ class DrawerView extends React.Component { { route: 'Sponsors', title: 'Sponsors' }, { route: 'Profile', title: 'Profile' }, { route: 'Contacts', title: 'Contacts' }, - { route: 'Attendees', title: 'Attendees' }, { route: 'StaffCheckinLists', title: 'StaffCheckinLists', hidden: true, }, + { route: 'Attendees', title: 'Attendees' }, ])} diff --git a/src/data/attendeesquery.js b/src/data/attendeesquery.js index 070419a..fd12160 100644 --- a/src/data/attendeesquery.js +++ b/src/data/attendeesquery.js @@ -1,21 +1,25 @@ -export const attendeesquery = ` -{ - events(slug: "reacteurope-2018") { - attendees(q:"a", uuid:"f35ad898-fe07-49cc-bd55-c4fbb59ac1b7") { - id - lastName - email - firstName - answers { - id - value - question { - id - title - } +import gql from 'graphql-tag'; + +const GET_ATTENDEES = gql` + { + events(slug: "reacteurope-2018") { + attendees(q:"a", uuid:"f35ad898-fe07-49cc-bd55-c4fbb59ac1b7") { + id + lastName + email + firstName + answers { + id + value + question { + id + title + } + } + + } } - - } } - } -`; \ No newline at end of file +`; + +export default GET_ATTENDEES; \ No newline at end of file diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 0202e6c..8edf8dd 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,9 +1,24 @@ -import React, { Component } from 'react' +import React, { Component } from 'react'; +import { Text } from 'react-native'; +import { Query } from 'react-apollo'; +import GET_ATTENDEES from '../data/attendeesquery' class Attendees extends Component { render() { - return
ATTENDEES
+ return + {({ loading, error, data }) => { + if (loading) return Loading... + if (error) return Error ${error} + + const attendees = data && data.events && data.events[0] ? data.events[0].attendees : [] + console.log('attendees', attendees) + + return ATTENDEES + }} + + + } } -export default Attendees \ No newline at end of file +export default Attendees; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index f2e949f..eaf9da2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -435,6 +435,18 @@ lodash "^4.17.4" react-native-vector-icons "4.5.0" +"@types/async@2.0.49": + version "2.0.49" + resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.49.tgz#92e33d13f74c895cb9a7f38ba97db8431ed14bc0" + +"@types/graphql@0.12.6": + version "0.12.6" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.12.6.tgz#3d619198585fcabe5f4e1adfb5cf5f3388c66c13" + +"@types/zen-observable@^0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.3.tgz#91b728599544efbb7386d8b6633693a3c2e7ade5" + abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -566,6 +578,75 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +apollo-cache-inmemory@^1.1.7: + version "1.2.1" + resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.2.1.tgz#1f8222270aa7983eb9d2ac30057196378ab3bb01" + dependencies: + apollo-cache "^1.1.8" + apollo-utilities "^1.0.12" + graphql-anywhere "^4.1.10" + +apollo-cache@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.1.8.tgz#b078d33dec876d52b5a81a325d3c254d4e362d3c" + dependencies: + apollo-utilities "^1.0.12" + +apollo-client-preset@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/apollo-client-preset/-/apollo-client-preset-1.0.8.tgz#23bd7176849d0d815f12c648774d009b258a449e" + dependencies: + apollo-cache-inmemory "^1.1.7" + apollo-client "^2.2.2" + apollo-link "^1.0.6" + apollo-link-http "^1.3.1" + graphql-tag "^2.4.2" + +apollo-client@^2.2.2, apollo-client@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.3.1.tgz#64b204779b7e8b21f901529527a9a9c973eb7fd4" + dependencies: + "@types/zen-observable" "^0.5.3" + apollo-cache "^1.1.8" + apollo-link "^1.0.0" + apollo-link-dedup "^1.0.0" + apollo-utilities "^1.0.12" + symbol-observable "^1.0.2" + zen-observable "^0.8.0" + optionalDependencies: + "@types/async" "2.0.49" + +apollo-link-dedup@^1.0.0: + version "1.0.9" + resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.9.tgz#3c4e4af88ef027cbddfdb857c043fd0574051dad" + dependencies: + apollo-link "^1.2.2" + +apollo-link-http-common@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.4.tgz#877603f7904dc8f70242cac61808b1f8d034b2c3" + dependencies: + apollo-link "^1.2.2" + +apollo-link-http@^1.3.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.4.tgz#b80b7b4b342c655b6a5614624b076a36be368f43" + dependencies: + apollo-link "^1.2.2" + apollo-link-http-common "^0.2.4" + +apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.2.tgz#54c84199b18ac1af8d63553a68ca389c05217a03" + dependencies: + "@types/graphql" "0.12.6" + apollo-utilities "^1.0.0" + zen-observable-ts "^0.8.9" + +apollo-utilities@^1.0.0, apollo-utilities@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.12.tgz#9e2b2a34cf89f3bf0d73a664effd8c1bb5d1b7f7" + append-transform@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" @@ -2854,7 +2935,17 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -graphql@^0.13.1: +graphql-anywhere@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.1.10.tgz#247ada0c8d85b9d5d6b37180973442ac68ff15de" + dependencies: + apollo-utilities "^1.0.12" + +graphql-tag@^2.4.2, graphql-tag@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.9.2.tgz#2f60a5a981375f430bf1e6e95992427dc18af686" + +graphql@^0.13.1, graphql@^0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.13.2.tgz#4c740ae3c222823e7004096f832e7b93b2108270" dependencies: @@ -6007,6 +6098,10 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +symbol-observable@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -6630,3 +6725,13 @@ yauzl@2.4.1: resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" dependencies: fd-slicer "~1.0.1" + +zen-observable-ts@^0.8.9: + version "0.8.9" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.9.tgz#d3c97af08c0afdca37ebcadf7cc3ee96bda9bab1" + dependencies: + zen-observable "^0.8.0" + +zen-observable@^0.8.0: + version "0.8.8" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.8.tgz#1ea93995bf098754a58215a1e0a7309e5749ec42" From c49665f65d4098dec9e5dcae36a9e4a5ef42ec7e Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 11:49:17 +0200 Subject: [PATCH 06/69] Added rough draft of filtering & autocomplete --- src/components/ContactCard.js | 3 +- src/screens/Attendees.js | 325 ++++++++++++++++++++++++++++++++-- 2 files changed, 315 insertions(+), 13 deletions(-) diff --git a/src/components/ContactCard.js b/src/components/ContactCard.js index 63a9c41..b3803b9 100644 --- a/src/components/ContactCard.js +++ b/src/components/ContactCard.js @@ -22,6 +22,7 @@ import { export default class ContactCard extends React.Component { render() { const { contact } = this.props; + const { email } = contact; const bio = this.getContactBio(); const twitter = this.getContactTwitter(); return ( @@ -40,7 +41,7 @@ export default class ContactCard extends React.Component { {twitter !== "" ? ( ) : null} - + diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 8edf8dd..11a0277 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,24 +1,325 @@ -import React, { Component } from 'react'; -import { Text } from 'react-native'; +import React from 'react'; +import { + Animated, + Linking, + Platform, + Text, + Image, + TouchableOpacity, + ScrollView, + StyleSheet, + AsyncStorage, + View, +} from 'react-native'; +import { Asset, LinearGradient, WebBrowser, Video } from 'expo'; +import { BorderlessButton, RectButton } from 'react-native-gesture-handler'; +import { NavigationActions } from 'react-navigation'; +import FadeIn from 'react-native-fade-in-image'; +import { View as AnimatableView } from 'react-native-animatable'; +import { Ionicons } from '@expo/vector-icons'; +import { withNavigation } from 'react-navigation'; +import Autocomplete from 'react-native-autocomplete-input'; import { Query } from 'react-apollo'; + +import AnimatedScrollView from '../components/AnimatedScrollView'; +import MyContacts from '../components/MyContacts'; +import NavigationBar from '../components/NavigationBar'; +import MenuButton from '../components/MenuButton'; +import VideoBackground from '../components/VideoBackground'; +import { BoldText, SemiBoldText } from '../components/StyledText'; +import { connectDrawerButton } from '../Navigation'; +import { Colors, FontSizes, Layout } from '../constants'; +import { Speakers, Talks } from '../data'; +import { + HideWhenConferenceHasStarted, + HideWhenConferenceHasEnded, + ShowWhenConferenceHasEnded, +} from '../utils'; +import ContactCard from '../components/ContactCard'; import GET_ATTENDEES from '../data/attendeesquery' -class Attendees extends Component { - render() { - return +export const Schedule = require('../data/schedule.json'); +const Event = Schedule.events[0]; + +class Attendees extends React.Component { + state = { + scrollY: new Animated.Value(0), + }; + + render() { + const { scrollY } = this.state; + const headerOpacity = scrollY.interpolate({ + inputRange: [0, 150], + outputRange: [0, 1], + extrapolate: 'clamp', + }); + return ( + + + + + + + + } + animatedBackgroundOpacity={headerOpacity} + /> + + ); + } +} + +@withNavigation +class DeferredAttendeesContent extends React.Component { + state = { + ready: Platform.OS === 'android' ? false : true, + tickets: [], + attendees: [], + query: '', + }; + + async getTickets() { + try { + const value = await AsyncStorage.getItem('@MySuperStore:tickets'); + console.log('tickets', value); + this.setState({ tickets: JSON.parse(value) }); + this.tickets = JSON.parse(value); + } catch (err) { + console.log(err); + return []; + } + } + + async getAttendees() { + // TODO: Fill in correctly + try { + const value = await AsyncStorage.getItem('@MySuperStore:tickets'); + console.log('attendees', value); + this.setState({ attendees: JSON.parse(value) }); + this.attendees = JSON.parse(value); + } catch (err) { + console.log(err); + return []; + } + } + + constructor(props) { + super(props); + this.tickets = []; + this.attendees = []; + } + + componentDidMount() { + this.getTickets(); + this.getAttendees(); + if (this.state.ready) { + return; + } + + setTimeout(() => { + this.setState({ ready: true }); + }, 200); + } + + render() { + if (!this.state.ready) { + return null; + } + const { query, tickets } = this.state; + console.log('state (Attendees):', this.state); + + // + // {tix && tix.length > 0 ? ( + // + // + // + // Scan a contact badge's QR code + // + // + // + // ) : ( + // + // + // + // You need to scan your ticket first + // + // + // + // )} + + + + // + return ( + + {({ loading, error, data }) => { if (loading) return Loading... if (error) return Error ${error} const attendees = data && data.events && data.events[0] ? data.events[0].attendees : [] - console.log('attendees', attendees) - - return ATTENDEES + const comp = (attendee) => attendee.firstName.toLowerCase().trim().includes(query.toLowerCase().trim()); + const filteredAttendees = attendees.filter(comp); + console.log('filteredAttendees', filteredAttendees) + return ( + this.setState({ query: text })} + placeholder="PLACEHOLDER" + renderItem={({ name }) => ( + this.setState({ query: name })}> + + {name} + + + )} + /> + ); }} - - - } + + ); + } + + // _handlePressQRButton = () => { + // this.props.navigation.navigate({ + // routeName: 'QRContactScanner', + // key: 'QRContactScanner', + // }); + // }; + // + // _handlePressProfileQRButton = () => { + // this.props.navigation.navigate({ + // routeName: 'QRScanner', + // key: 'QRScanner', + // }); + // }; + + // _handlePressTwitterButton = async () => { + // try { + // await Linking.openURL( + // `twitter://user?screen_name=` + Event.twitterHandle + // ); + // } catch (e) { + // WebBrowser.openBrowserAsync('https://twitter.com/' + Event.twitterHandle); + // } + // }; } -export default Attendees; \ No newline at end of file +const OverscrollView = () => ( + +); + +const ClipBorderRadius = ({ children, style }) => { + return ( + + {children} + + ); +}; + +const BORDER_RADIUS = 3; + +const styles = StyleSheet.create({ + headerContent: { + alignItems: 'center', + marginTop: 5, + paddingVertical: 10, + }, + headerVideoLayer: { + ...StyleSheet.absoluteFillObject, + }, + headerVideoOverlay: { + ...StyleSheet.absoluteFillObject, + backgroundColor: Colors.blue, + opacity: 0.8, + }, + headerText: { + color: '#fff', + textAlign: 'center', + fontSize: 17, + lineHeight: 17 * 1.5, + }, + headerSmallText: { + color: '#fff', + textAlign: 'center', + fontSize: 7, + lineHeight: 7 * 1.5, + }, + bigButton: { + backgroundColor: Colors.blue, + paddingHorizontal: 15, + height: 50, + marginHorizontal: 15, + alignItems: 'center', + justifyContent: 'center', + borderRadius: BORDER_RADIUS, + overflow: 'hidden', + flexDirection: 'row', + }, + bigButtonText: { + fontSize: FontSizes.normalButton, + color: '#fff', + textAlign: 'center', + }, + seeAllTalks: { + fontSize: FontSizes.normalButton, + color: Colors.blue, + }, + autocompleteContainer: { + marginLeft: 10, + marginRight: 10 + }, +}); + +export default Attendees; From 796354bfc9ea0f22226a83500ac1c8b47f400692 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 10:20:21 +0200 Subject: [PATCH 07/69] Added autocomplete input dependency --- package.json | 1 + yarn.lock | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/package.json b/package.json index b6d1cdc..231c3e0 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "react": "16.3.1", "react-native": "https://github.com/expo/react-native/archive/sdk-27.0.0.tar.gz", "react-native-animatable": "^1.2.4", + "react-native-autocomplete-input": "^3.5.0", "react-native-fade-in-image": "1.3.0", "react-native-gravatar": "^1.0.2", "react-native-paper": "^1.2.6", diff --git a/yarn.lock b/yarn.lock index a1d5bdb..3ca363d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5032,6 +5032,12 @@ react-native-animatable@^1.2.4: dependencies: prop-types "^15.5.10" +react-native-autocomplete-input@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/react-native-autocomplete-input/-/react-native-autocomplete-input-3.5.0.tgz#2e52e3865abf1ad3e8d04f7e39f5314c03a89e4d" + dependencies: + prop-types "^15.5.10" + react-native-branch@2.0.0-beta.3: version "2.0.0-beta.3" resolved "https://registry.yarnpkg.com/react-native-branch/-/react-native-branch-2.0.0-beta.3.tgz#2167af86bbc9f964bd45bd5f37684e5b54965e32" From c1a661fedfd699f749865e59d762900c0c6ec509 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 10:24:55 +0200 Subject: [PATCH 08/69] Fix unhandled nextTalks promise, and add Screen + Navigation for Attendees (not functional) --- src/Navigation.js | 2 ++ src/components/TalksUpNext.js | 4 ++-- src/screens/Attendees.js | 9 +++++++++ src/screens/index.js | 5 ++++- 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/screens/Attendees.js diff --git a/src/Navigation.js b/src/Navigation.js index 3871f73..456630e 100644 --- a/src/Navigation.js +++ b/src/Navigation.js @@ -145,6 +145,7 @@ const DrawerRouteConfig = { Profile: { screen: Screens.Profile }, Contacts: { screen: Screens.Contacts }, StaffCheckinLists: { screen: StaffCheckinListsNavigation }, + Attendees: { screen: Screens.Attendees }, }; const DrawerRouter = TabRouter(DrawerRouteConfig); @@ -369,6 +370,7 @@ class DrawerView extends React.Component { { route: 'Sponsors', title: 'Sponsors' }, { route: 'Profile', title: 'Profile' }, { route: 'Contacts', title: 'Contacts' }, + { route: 'Attendees', title: 'Attendees' }, { route: 'StaffCheckinLists', title: 'StaffCheckinLists', diff --git a/src/components/TalksUpNext.js b/src/components/TalksUpNext.js index cc4da34..c78623e 100644 --- a/src/components/TalksUpNext.js +++ b/src/components/TalksUpNext.js @@ -87,8 +87,8 @@ export default class TalksUpNext extends React.Component { 0, 3 ), - dateTime: nextTalks[0].startDate, - time: nextTalks[0].startDate + dateTime: nextTalks && nextTalks.length ? nextTalks[0].startDate : '', + time: nextTalks && nextTalks.length ? nextTalks[0].startDate : '' }); } else { that.setState({ nextTalks: [] }); diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js new file mode 100644 index 0000000..0202e6c --- /dev/null +++ b/src/screens/Attendees.js @@ -0,0 +1,9 @@ +import React, { Component } from 'react' + +class Attendees extends Component { + render() { + return
ATTENDEES
+ } +} + +export default Attendees \ No newline at end of file diff --git a/src/screens/index.js b/src/screens/index.js index bebbeac..833dac5 100644 --- a/src/screens/index.js +++ b/src/screens/index.js @@ -9,6 +9,8 @@ import Contacts from "./Contacts"; import TicketInstructions from "./TicketInstructions"; import StaffCheckinLists from "./StaffCheckinLists"; import CheckedInAttendeeInfo from "./CheckedInAttendeeInfo"; +import Attendees from "./Attendees"; + export default { Home, Crew, @@ -20,5 +22,6 @@ export default { Contacts, TicketInstructions, StaffCheckinLists, - CheckedInAttendeeInfo + CheckedInAttendeeInfo, + Attendees, }; From d656d870f6ac151f165ea39e4bc275e3d5f18580 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 10:41:45 +0200 Subject: [PATCH 09/69] add attendeesquery --- src/data/attendeesquery.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/data/attendeesquery.js diff --git a/src/data/attendeesquery.js b/src/data/attendeesquery.js new file mode 100644 index 0000000..070419a --- /dev/null +++ b/src/data/attendeesquery.js @@ -0,0 +1,21 @@ +export const attendeesquery = ` +{ + events(slug: "reacteurope-2018") { + attendees(q:"a", uuid:"f35ad898-fe07-49cc-bd55-c4fbb59ac1b7") { + id + lastName + email + firstName + answers { + id + value + question { + id + title + } + } + + } + } + } +`; \ No newline at end of file From 630fc956cd361075b79f166a5f9dba7fd4195608 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 10:46:23 +0200 Subject: [PATCH 10/69] add react-apollo --- package.json | 1 + yarn.lock | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/package.json b/package.json index 231c3e0..db357c6 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "path": "^0.12.7", "prettier": "^1.11.1", "react": "16.3.1", + "react-apollo": "^2.1.4", "react-native": "https://github.com/expo/react-native/archive/sdk-27.0.0.tar.gz", "react-native-animatable": "^1.2.4", "react-native-autocomplete-input": "^3.5.0", diff --git a/yarn.lock b/yarn.lock index 3ca363d..f2e949f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3974,6 +3974,10 @@ lodash.zipobject@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz#b399f5aba8ff62a746f6979bf20b214f964dbef8" +lodash@4.17.5: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + lodash@^3.5.0: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" @@ -4978,6 +4982,16 @@ rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.1.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-apollo@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/react-apollo/-/react-apollo-2.1.4.tgz#a51059ac56f1a7997cad636a5d36398b9c93ff12" + dependencies: + fbjs "^0.8.16" + hoist-non-react-statics "^2.5.0" + invariant "^2.2.2" + lodash "4.17.5" + prop-types "^15.6.0" + react-clone-referenced-element@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.0.1.tgz#2bba8c69404c5e4a944398600bcc4c941f860682" From 5625d0d6f00bfe7bfc558efde4d56de94c6a1280 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 11:09:07 +0200 Subject: [PATCH 11/69] implement graphql query using react-apollo --- App.js | 21 +++++++- package.json | 4 ++ src/Navigation.js | 2 +- src/data/attendeesquery.js | 42 ++++++++------- src/screens/Attendees.js | 21 ++++++-- yarn.lock | 107 ++++++++++++++++++++++++++++++++++++- 6 files changed, 171 insertions(+), 26 deletions(-) diff --git a/App.js b/App.js index 733d163..b9e7cbe 100644 --- a/App.js +++ b/App.js @@ -1,7 +1,12 @@ import React from "react"; +import { ApolloClient } from 'apollo-client'; +import { ApolloProvider } from 'react-apollo'; +import { HttpLink } from 'apollo-link-http'; +import { InMemoryCache } from 'apollo-cache-inmemory'; import { Asset, AppLoading, Font, Updates } from "expo"; import { AsyncStorage, Alert, Platform, View } from "react-native"; import { Ionicons } from "@expo/vector-icons"; +import { GQL } from './src/constants' import { loadSavedTalksAsync } from "./src/utils/storage"; import { SafeAreaView } from "react-navigation"; import { ScheduleQuery } from "./src/data/schedulequery"; @@ -10,6 +15,15 @@ if (Platform.OS === "android") { SafeAreaView.setStatusBarHeight(0); } +const client = new ApolloClient({ + // By default, this client will send queries to the + // `/graphql` endpoint on the same host + // Pass the configuration option { uri: YOUR_GRAPHQL_API_URL } to the `HttpLink` to connect + // to a different host + link: new HttpLink({ uri: GQL.uri }), + cache: new InMemoryCache(), +}); + import Navigation from "./src/Navigation"; export default class App extends React.Component { @@ -84,7 +98,10 @@ export default class App extends React.Component { /> ); } - - return ; + return ( + + + + ); } } diff --git a/package.json b/package.json index db357c6..264f2c2 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,14 @@ "devtools": "react-devtools" }, "dependencies": { + "apollo-client": "^2.3.1", + "apollo-client-preset": "^1.0.8", "crypto-js": "^3.1.9-1", "expo": "^27.0.0", "fbemitter": "^2.1.1", "global": "^4.3.2", + "graphql": "^0.13.2", + "graphql-tag": "^2.9.2", "hoist-non-react-statics": "^2.3.1", "lodash": "^4.17.4", "moment": "2.21.0", diff --git a/src/Navigation.js b/src/Navigation.js index 456630e..a33ff50 100644 --- a/src/Navigation.js +++ b/src/Navigation.js @@ -370,12 +370,12 @@ class DrawerView extends React.Component { { route: 'Sponsors', title: 'Sponsors' }, { route: 'Profile', title: 'Profile' }, { route: 'Contacts', title: 'Contacts' }, - { route: 'Attendees', title: 'Attendees' }, { route: 'StaffCheckinLists', title: 'StaffCheckinLists', hidden: true, }, + { route: 'Attendees', title: 'Attendees' }, ])}
diff --git a/src/data/attendeesquery.js b/src/data/attendeesquery.js index 070419a..fd12160 100644 --- a/src/data/attendeesquery.js +++ b/src/data/attendeesquery.js @@ -1,21 +1,25 @@ -export const attendeesquery = ` -{ - events(slug: "reacteurope-2018") { - attendees(q:"a", uuid:"f35ad898-fe07-49cc-bd55-c4fbb59ac1b7") { - id - lastName - email - firstName - answers { - id - value - question { - id - title - } +import gql from 'graphql-tag'; + +const GET_ATTENDEES = gql` + { + events(slug: "reacteurope-2018") { + attendees(q:"a", uuid:"f35ad898-fe07-49cc-bd55-c4fbb59ac1b7") { + id + lastName + email + firstName + answers { + id + value + question { + id + title + } + } + + } } - - } } - } -`; \ No newline at end of file +`; + +export default GET_ATTENDEES; \ No newline at end of file diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 0202e6c..8edf8dd 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,9 +1,24 @@ -import React, { Component } from 'react' +import React, { Component } from 'react'; +import { Text } from 'react-native'; +import { Query } from 'react-apollo'; +import GET_ATTENDEES from '../data/attendeesquery' class Attendees extends Component { render() { - return
ATTENDEES
+ return + {({ loading, error, data }) => { + if (loading) return Loading... + if (error) return Error ${error} + + const attendees = data && data.events && data.events[0] ? data.events[0].attendees : [] + console.log('attendees', attendees) + + return ATTENDEES + }} + + + } } -export default Attendees \ No newline at end of file +export default Attendees; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index f2e949f..eaf9da2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -435,6 +435,18 @@ lodash "^4.17.4" react-native-vector-icons "4.5.0" +"@types/async@2.0.49": + version "2.0.49" + resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.49.tgz#92e33d13f74c895cb9a7f38ba97db8431ed14bc0" + +"@types/graphql@0.12.6": + version "0.12.6" + resolved "https://registry.yarnpkg.com/@types/graphql/-/graphql-0.12.6.tgz#3d619198585fcabe5f4e1adfb5cf5f3388c66c13" + +"@types/zen-observable@^0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.5.3.tgz#91b728599544efbb7386d8b6633693a3c2e7ade5" + abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -566,6 +578,75 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +apollo-cache-inmemory@^1.1.7: + version "1.2.1" + resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.2.1.tgz#1f8222270aa7983eb9d2ac30057196378ab3bb01" + dependencies: + apollo-cache "^1.1.8" + apollo-utilities "^1.0.12" + graphql-anywhere "^4.1.10" + +apollo-cache@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.1.8.tgz#b078d33dec876d52b5a81a325d3c254d4e362d3c" + dependencies: + apollo-utilities "^1.0.12" + +apollo-client-preset@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/apollo-client-preset/-/apollo-client-preset-1.0.8.tgz#23bd7176849d0d815f12c648774d009b258a449e" + dependencies: + apollo-cache-inmemory "^1.1.7" + apollo-client "^2.2.2" + apollo-link "^1.0.6" + apollo-link-http "^1.3.1" + graphql-tag "^2.4.2" + +apollo-client@^2.2.2, apollo-client@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.3.1.tgz#64b204779b7e8b21f901529527a9a9c973eb7fd4" + dependencies: + "@types/zen-observable" "^0.5.3" + apollo-cache "^1.1.8" + apollo-link "^1.0.0" + apollo-link-dedup "^1.0.0" + apollo-utilities "^1.0.12" + symbol-observable "^1.0.2" + zen-observable "^0.8.0" + optionalDependencies: + "@types/async" "2.0.49" + +apollo-link-dedup@^1.0.0: + version "1.0.9" + resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.9.tgz#3c4e4af88ef027cbddfdb857c043fd0574051dad" + dependencies: + apollo-link "^1.2.2" + +apollo-link-http-common@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.4.tgz#877603f7904dc8f70242cac61808b1f8d034b2c3" + dependencies: + apollo-link "^1.2.2" + +apollo-link-http@^1.3.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.4.tgz#b80b7b4b342c655b6a5614624b076a36be368f43" + dependencies: + apollo-link "^1.2.2" + apollo-link-http-common "^0.2.4" + +apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.2.tgz#54c84199b18ac1af8d63553a68ca389c05217a03" + dependencies: + "@types/graphql" "0.12.6" + apollo-utilities "^1.0.0" + zen-observable-ts "^0.8.9" + +apollo-utilities@^1.0.0, apollo-utilities@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.12.tgz#9e2b2a34cf89f3bf0d73a664effd8c1bb5d1b7f7" + append-transform@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" @@ -2854,7 +2935,17 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -graphql@^0.13.1: +graphql-anywhere@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.1.10.tgz#247ada0c8d85b9d5d6b37180973442ac68ff15de" + dependencies: + apollo-utilities "^1.0.12" + +graphql-tag@^2.4.2, graphql-tag@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.9.2.tgz#2f60a5a981375f430bf1e6e95992427dc18af686" + +graphql@^0.13.1, graphql@^0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/graphql/-/graphql-0.13.2.tgz#4c740ae3c222823e7004096f832e7b93b2108270" dependencies: @@ -6007,6 +6098,10 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +symbol-observable@^1.0.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -6630,3 +6725,13 @@ yauzl@2.4.1: resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" dependencies: fd-slicer "~1.0.1" + +zen-observable-ts@^0.8.9: + version "0.8.9" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.9.tgz#d3c97af08c0afdca37ebcadf7cc3ee96bda9bab1" + dependencies: + zen-observable "^0.8.0" + +zen-observable@^0.8.0: + version "0.8.8" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.8.tgz#1ea93995bf098754a58215a1e0a7309e5749ec42" From 39d1eeea62726e7b9c4e33adffd93a1cdca4c2a3 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 11:55:50 +0200 Subject: [PATCH 12/69] Attendees SectionList --- src/data/attendeesquery.js | 1 - src/screens/Attendees.js | 78 +++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/data/attendeesquery.js b/src/data/attendeesquery.js index fd12160..4eeef72 100644 --- a/src/data/attendeesquery.js +++ b/src/data/attendeesquery.js @@ -16,7 +16,6 @@ const GET_ATTENDEES = gql` title } } - } } } diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 8edf8dd..b408451 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,9 +1,53 @@ import React, { Component } from 'react'; -import { Text } from 'react-native'; +import { + View, + Text, + SectionList, + StyleSheet, + TouchableOpacity, + } from 'react-native'; +import _ from 'lodash'; +import FadeIn from 'react-native-fade-in-image'; +import { ScrollView } from "react-native-gesture-handler"; import { Query } from 'react-apollo'; import GET_ATTENDEES from '../data/attendeesquery' +import { BoldText, SemiBoldText, RegularText } from '../components/StyledText'; +import CachedImage from '../components/CachedImage'; + + +class ContactRow extends React.Component { + render() { + const { item: attendee } = this.props; + + return ( + + + + + + + + + {attendee.firstName} {attendee.lastName} + + {attendee.role ? {attendee.role} : null} + this._handlePressCrewTwitter(attendee.twitter)}> + @{attendee.twitter} + + + + ); + } +} class Attendees extends Component { + + _renderItem = ({ item }) => ; + render() { return {({ loading, error, data }) => { @@ -13,7 +57,17 @@ class Attendees extends Component { const attendees = data && data.events && data.events[0] ? data.events[0].attendees : [] console.log('attendees', attendees) - return ATTENDEES + return } + stickySectionHeadersEnabled={true} + renderItem={this._renderItem} + renderSectionHeader={this._renderSectionHeader} + sections={[ + {title: 'Title1', data: attendees}, + ]} + keyExtractor={item => item.id} + initialNumToRender={10} + /> }} @@ -21,4 +75,24 @@ class Attendees extends Component { } } +const styles = StyleSheet.create({ + row: { + flex: 1, + padding: 10, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: '#eee', + backgroundColor: '#fff', + flexDirection: 'row', + }, + rowAvatarContainer: { + paddingVertical: 5, + paddingRight: 10, + paddingLeft: 0, + }, + rowData: { + flex: 1, + }, + }); + + export default Attendees; \ No newline at end of file From af50d3fcf3f3d8b015098dbd1b5e95a986236605 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 11:57:38 +0200 Subject: [PATCH 13/69] 2 sections --- src/screens/Attendees.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index b408451..fec966d 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -63,7 +63,8 @@ class Attendees extends Component { renderItem={this._renderItem} renderSectionHeader={this._renderSectionHeader} sections={[ - {title: 'Title1', data: attendees}, + {title: 'Attendees', data: attendees}, + {title: 'Twitter', data: attendees}, ]} keyExtractor={item => item.id} initialNumToRender={10} From ac8488a1049c5261637dc005bfb657be11bbb937 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 12:11:49 +0200 Subject: [PATCH 14/69] Attendees with SectionList --- src/screens/Attendees.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 25a376f..50c6462 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -28,7 +28,7 @@ import MyContacts from '../components/MyContacts'; import NavigationBar from '../components/NavigationBar'; import MenuButton from '../components/MenuButton'; import VideoBackground from '../components/VideoBackground'; -import { BoldText, SemiBoldText } from '../components/StyledText'; +import { BoldText, SemiBoldText, RegularText } from '../components/StyledText'; import { connectDrawerButton } from '../Navigation'; import { Colors, FontSizes, Layout } from '../constants'; import { Speakers, Talks } from '../data'; @@ -39,7 +39,6 @@ import { } from '../utils'; import ContactCard from '../components/ContactCard'; import GET_ATTENDEES from '../data/attendeesquery' -import { BoldText, SemiBoldText, RegularText } from '../components/StyledText'; import CachedImage from '../components/CachedImage'; @@ -388,4 +387,6 @@ const styles = StyleSheet.create({ rowData: { flex: 1, }, -}); \ No newline at end of file +}); + +export default Attendees \ No newline at end of file From cbed7799e771fe3c5b585f9eb114ded6ca442108 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 12:23:45 +0200 Subject: [PATCH 15/69] remve react-native-autocomplete-input and add sectionHeaders to SectionList --- package.json | 1 - src/screens/Attendees.js | 32 ++++++++++++-------------------- yarn.lock | 6 ------ 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 264f2c2..08839d4 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "react-apollo": "^2.1.4", "react-native": "https://github.com/expo/react-native/archive/sdk-27.0.0.tar.gz", "react-native-animatable": "^1.2.4", - "react-native-autocomplete-input": "^3.5.0", "react-native-fade-in-image": "1.3.0", "react-native-gravatar": "^1.0.2", "react-native-paper": "^1.2.6", diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 50c6462..f9a519f 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -174,7 +174,15 @@ class DeferredAttendeesContent extends React.Component { }, 200); } - _renderItem = ({ item }) => ; + _renderSectionHeader = ({ section }) => { + return ( + + {section.title} + + ); + }; + + _renderItem = ({ item }) => ; render() { if (!this.state.ready) { @@ -232,36 +240,20 @@ class DeferredAttendeesContent extends React.Component { console.log('filteredAttendees', filteredAttendees) return ( - this.setState({ query: text })} - placeholder="PLACEHOLDER" - renderItem={({ name }) => ( - this.setState({ query: name })}> - - {name} - - - )} - /> - } stickySectionHeadersEnabled={true} renderItem={this._renderItem} renderSectionHeader={this._renderSectionHeader} sections={[ - {title: 'Attendees', data: attendees}, - {title: 'Twitter', data: attendees}, + {title: 'Name', data: filteredAttendees}, + {title: 'Twitter', data: filteredAttendees}, + {title: 'Email', data: filteredAttendees}, ]} keyExtractor={item => item.id} initialNumToRender={10} /> - ); }}
diff --git a/yarn.lock b/yarn.lock index eaf9da2..21c94dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5137,12 +5137,6 @@ react-native-animatable@^1.2.4: dependencies: prop-types "^15.5.10" -react-native-autocomplete-input@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/react-native-autocomplete-input/-/react-native-autocomplete-input-3.5.0.tgz#2e52e3865abf1ad3e8d04f7e39f5314c03a89e4d" - dependencies: - prop-types "^15.5.10" - react-native-branch@2.0.0-beta.3: version "2.0.0-beta.3" resolved "https://registry.yarnpkg.com/react-native-branch/-/react-native-branch-2.0.0-beta.3.tgz#2167af86bbc9f964bd45bd5f37684e5b54965e32" From f2e40267165a9137bfe64435d343c5b7734c57f9 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 12:30:03 +0200 Subject: [PATCH 16/69] fix import statement --- src/screens/Attendees.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index f9a519f..1cc30b3 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -20,7 +20,6 @@ import FadeIn from 'react-native-fade-in-image'; import { View as AnimatableView } from 'react-native-animatable'; import { Ionicons } from '@expo/vector-icons'; import { withNavigation } from 'react-navigation'; -import Autocomplete from 'react-native-autocomplete-input'; import { Query } from 'react-apollo'; import AnimatedScrollView from '../components/AnimatedScrollView'; From c02de58b086bb44234dfcef5489e8d8257075e34 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 12:55:40 +0200 Subject: [PATCH 17/69] Updated section list with header and contact card --- src/screens/Attendees.js | 188 +++++++++++++-------------------------- 1 file changed, 62 insertions(+), 126 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 1cc30b3..62b2eeb 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import _ from 'lodash'; -import { ScrollView } from "react-native-gesture-handler"; +import { ScrollView } from 'react-native-gesture-handler'; import { Animated, Linking, @@ -11,6 +11,7 @@ import { StyleSheet, AsyncStorage, View, + TextInput, SectionList, } from 'react-native'; import { Asset, LinearGradient, WebBrowser, Video } from 'expo'; @@ -37,39 +38,9 @@ import { ShowWhenConferenceHasEnded, } from '../utils'; import ContactCard from '../components/ContactCard'; -import GET_ATTENDEES from '../data/attendeesquery' +import GET_ATTENDEES from '../data/attendeesquery'; import CachedImage from '../components/CachedImage'; - -class ContactRow extends React.Component { - render() { - const { item: attendee } = this.props; - - return ( - - - - - - - - - {attendee.firstName} {attendee.lastName} - - {attendee.role ? {attendee.role} : null} - this._handlePressCrewTwitter(attendee.twitter)}> - @{attendee.twitter} - - - - ); - } -} - export const Schedule = require('../data/schedule.json'); const Event = Schedule.events[0]; @@ -98,7 +69,8 @@ class Attendees extends React.Component { }, ], { useNativeDriver: true } - )}> + )} + > ( + this.setState({ query: text })} + placeholder="Search a conference attendee here" + /> + ); + _renderSectionHeader = ({ section }) => { return ( @@ -181,14 +142,16 @@ class DeferredAttendeesContent extends React.Component { ); }; - _renderItem = ({ item }) => ; + _renderItem = ({ item: attendee }) => ( + + ); render() { if (!this.state.ready) { return null; } - const { query, tickets } = this.state; - console.log('state (Attendees):', this.state); + const { query } = this.state; + const cleanedQuery = query.toLowerCase().trim(); // // )} - - - // return ( - {({ loading, error, data }) => { - if (loading) return Loading... - if (error) return Error ${error} - - const attendees = data && data.events && data.events[0] ? data.events[0].attendees : [] - const comp = (attendee) => attendee.firstName.toLowerCase().trim().includes(query.toLowerCase().trim()); - const filteredAttendees = attendees.filter(comp); - console.log('filteredAttendees', filteredAttendees) - return ( - - } - stickySectionHeadersEnabled={true} - renderItem={this._renderItem} - renderSectionHeader={this._renderSectionHeader} - sections={[ - {title: 'Name', data: filteredAttendees}, - {title: 'Twitter', data: filteredAttendees}, - {title: 'Email', data: filteredAttendees}, - ]} - keyExtractor={item => item.id} - initialNumToRender={10} - /> - - ); - }} + {({ loading, error, data }) => { + if (loading) { + return Loading...; + } + if (error) { + return Error ${error}; + } + const attendees = data && data.events && data.events[0] ? data.events[0].attendees : []; + const filteredAttendees = attendees.filter(attendee => + attendee.firstName + .toLowerCase() + .trim() + .includes(cleanedQuery) + ); + console.log('filteredAttendees', filteredAttendees); + return ( + + } + stickySectionHeadersEnabled={true} + ListHeaderComponent={this._renderHeader} + renderItem={this._renderItem} + renderSectionHeader={this._renderSectionHeader} + sections={[ + { title: 'Name', data: filteredAttendees }, + { title: 'Twitter', data: filteredAttendees }, + { title: 'Email', data: filteredAttendees }, + ]} + keyExtractor={item => item.id} + initialNumToRender={10} + /> + + ); + }} ); } - - // _handlePressQRButton = () => { - // this.props.navigation.navigate({ - // routeName: 'QRContactScanner', - // key: 'QRContactScanner', - // }); - // }; - // - // _handlePressProfileQRButton = () => { - // this.props.navigation.navigate({ - // routeName: 'QRScanner', - // key: 'QRScanner', - // }); - // }; - - // _handlePressTwitterButton = async () => { - // try { - // await Linking.openURL( - // `twitter://user?screen_name=` + Event.twitterHandle - // ); - // } catch (e) { - // WebBrowser.openBrowserAsync('https://twitter.com/' + Event.twitterHandle); - // } - // }; } const OverscrollView = () => ( @@ -300,11 +239,7 @@ const OverscrollView = () => ( const ClipBorderRadius = ({ children, style }) => { return ( - + {children} ); @@ -360,16 +295,16 @@ const styles = StyleSheet.create({ }, autocompleteContainer: { marginLeft: 10, - marginRight: 10 + marginRight: 10, }, row: { - flex: 1, - padding: 10, - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: '#eee', - backgroundColor: '#fff', - flexDirection: 'row', - }, + flex: 1, + padding: 10, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: '#eee', + backgroundColor: '#fff', + flexDirection: 'row', + }, rowAvatarContainer: { paddingVertical: 5, paddingRight: 10, @@ -378,6 +313,7 @@ const styles = StyleSheet.create({ rowData: { flex: 1, }, + textInput: {}, }); -export default Attendees \ No newline at end of file +export default Attendees; From 703a3771402f297ce92ce3d741f75b0a6f9a0693 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 13:12:41 +0200 Subject: [PATCH 18/69] Updated text input props --- src/screens/Attendees.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 62b2eeb..98d6017 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -131,6 +131,11 @@ class DeferredAttendeesContent extends React.Component { this.setState({ query: text })} placeholder="Search a conference attendee here" + autoCapitalize="none" + autoCorrect={false} + clearButtonMode="while-editing" + returnKeyLabel="Search" + style={styles.textInput} /> ); @@ -313,7 +318,15 @@ const styles = StyleSheet.create({ rowData: { flex: 1, }, - textInput: {}, + textInput: { + backgroundColor: 'white', + margin: 5, + padding: 5, + borderRadius: 4, + borderWidth: 1, + borderColor: 'black', + fontSize: 16, + }, }); export default Attendees; From 44dd45d2281de5430f55b3ce039ec36101c7678d Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 13:41:02 +0200 Subject: [PATCH 19/69] Added proper filtering --- src/screens/Attendees.js | 94 ++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 37 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 98d6017..7178e8b 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -127,6 +127,21 @@ class DeferredAttendeesContent extends React.Component { }, 200); } + getContactTwitter = contact => { + let twitter = ''; + if (contact) { + contact.answers.map(answer => { + if (answer.question && answer.question.title === 'Twitter') { + twitter = answer.value; + } + }); + } + return twitter + .replace('@', '') + .replace('https://twitter.com/', '') + .replace('twitter.com/', ''); + }; + _renderHeader = () => ( this.setState({ query: text })} @@ -157,35 +172,7 @@ class DeferredAttendeesContent extends React.Component { } const { query } = this.state; const cleanedQuery = query.toLowerCase().trim(); - - // - // {tix && tix.length > 0 ? ( - // - // - // - // Scan a contact badge's QR code - // - // - // - // ) : ( - // - // - // - // You need to scan your ticket first - // - // - // - // )} - + console.log('State:', this.state); return ( @@ -196,14 +183,43 @@ class DeferredAttendeesContent extends React.Component { if (error) { return Error ${error}; } + const attendees = data && data.events && data.events[0] ? data.events[0].attendees : []; - const filteredAttendees = attendees.filter(attendee => - attendee.firstName + const filteredNameAttendees = attendees.filter(attendee => { + const fullName = `${attendee.firstName} ${attendee.lastName}`; + return fullName + .toLowerCase() + .trim() + .includes(cleanedQuery); + }); + const filteredEmailAttendees = attendees.filter(attendee => + attendee.email .toLowerCase() .trim() .includes(cleanedQuery) ); - console.log('filteredAttendees', filteredAttendees); + const filteredTwitterAttendees = attendees.filter(attendee => + this.getContactTwitter(attendee) + .toLowerCase() + .trim() + .includes(cleanedQuery) + ); + + const sections = []; + if (filteredNameAttendees.length > 0) { + sections.push({ title: 'Name', data: filteredNameAttendees }); + } + if (filteredEmailAttendees.length > 0) { + sections.push({ title: 'Email', data: filteredEmailAttendees }); + } + if (filteredTwitterAttendees.length > 0) { + sections.push({ title: 'Twitter', data: filteredTwitterAttendees }); + } + + console.log('Attendees (filtered by name): ', filteredNameAttendees); + console.log('Attendees (filtered by email): ', filteredEmailAttendees); + console.log('Attendees (filtered by twitter): ', filteredTwitterAttendees); + return ( item.id} initialNumToRender={10} /> @@ -318,6 +330,14 @@ const styles = StyleSheet.create({ rowData: { flex: 1, }, + sectionHeader: { + paddingHorizontal: 10, + paddingTop: 7, + paddingBottom: 5, + backgroundColor: '#eee', + borderWidth: 1, + borderColor: '#eee', + }, textInput: { backgroundColor: 'white', margin: 5, From 0e2aa414de426bb4521312e2ed5caccc1c73a819 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 13:41:49 +0200 Subject: [PATCH 20/69] remove tickets logic, remove loading render & fix cachedImage error --- src/components/CachedImage.js | 10 +++++- src/screens/Attendees.js | 59 ++++------------------------------- 2 files changed, 15 insertions(+), 54 deletions(-) diff --git a/src/components/CachedImage.js b/src/components/CachedImage.js index f7d8e81..991f58e 100644 --- a/src/components/CachedImage.js +++ b/src/components/CachedImage.js @@ -8,6 +8,8 @@ export default class CachedImage extends React.Component { source: null, }; + unmounting: false + async componentDidMount() { let source = this.props.source; @@ -28,10 +30,16 @@ export default class CachedImage extends React.Component { } catch (e) { console.log(e); } finally { - this.setState({ source }); + if (!this.unmounting) { + this.setState({ source }); + } } } + componentWillUnmount() { + this.unmounting = true + } + render() { if (this.state.source) { return ; diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 98d6017..8f14c2d 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -97,27 +97,11 @@ class Attendees extends React.Component { class DeferredAttendeesContent extends React.Component { state = { ready: Platform.OS === 'android' ? false : true, - tickets: [], attendees: [], query: '', }; - async getTickets() { - try { - const value = await AsyncStorage.getItem('@MySuperStore:tickets'); - this.setState({ tickets: JSON.parse(value) }); - } catch (err) { - console.log(err); - } - } - - constructor(props) { - super(props); - this.tickets = []; - } - componentDidMount() { - this.getTickets(); if (this.state.ready) { return; } @@ -148,7 +132,7 @@ class DeferredAttendeesContent extends React.Component { }; _renderItem = ({ item: attendee }) => ( - + ); render() { @@ -158,52 +142,21 @@ class DeferredAttendeesContent extends React.Component { const { query } = this.state; const cleanedQuery = query.toLowerCase().trim(); - // - // {tix && tix.length > 0 ? ( - // - // - // - // Scan a contact badge's QR code - // - // - // - // ) : ( - // - // - // - // You need to scan your ticket first - // - // - // - // )} - return ( {({ loading, error, data }) => { - if (loading) { - return Loading...; - } if (error) { return Error ${error}; } const attendees = data && data.events && data.events[0] ? data.events[0].attendees : []; - const filteredAttendees = attendees.filter(attendee => + const filteredAttendeesByName = attendees.filter(attendee => attendee.firstName .toLowerCase() .trim() .includes(cleanedQuery) ); - console.log('filteredAttendees', filteredAttendees); + console.log('filteredAttendeesByName', filteredAttendeesByName); return ( item.id} initialNumToRender={10} From 6c0557727961269071e30aad08d3efa8b78f751d Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 13:52:46 +0200 Subject: [PATCH 21/69] Fixed header update bugs --- src/screens/Attendees.js | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 7178e8b..22abd32 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -142,18 +142,6 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; - _renderHeader = () => ( - this.setState({ query: text })} - placeholder="Search a conference attendee here" - autoCapitalize="none" - autoCorrect={false} - clearButtonMode="while-editing" - returnKeyLabel="Search" - style={styles.textInput} - /> - ); - _renderSectionHeader = ({ section }) => { return ( @@ -222,15 +210,24 @@ class DeferredAttendeesContent extends React.Component { return ( + this.setState({ query: text })} + placeholder="Search a conference attendee here" + autoCapitalize="none" + autoCorrect={false} + clearButtonMode="while-editing" + returnKeyLabel="Search" + style={styles.textInput} + /> } stickySectionHeadersEnabled={true} - ListHeaderComponent={this._renderHeader} renderItem={this._renderItem} renderSectionHeader={this._renderSectionHeader} sections={sections} keyExtractor={item => item.id} initialNumToRender={10} + keyboardDismissMode="on-drag" /> ); From 2722d8e37562cd36e56667c279b6b18964b64ef0 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 14:02:53 +0200 Subject: [PATCH 22/69] Replaced sectioned content with flat list --- src/screens/Attendees.js | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 22abd32..bbe832d 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -12,7 +12,7 @@ import { AsyncStorage, View, TextInput, - SectionList, + FlatList, } from 'react-native'; import { Asset, LinearGradient, WebBrowser, Video } from 'expo'; import { BorderlessButton, RectButton } from 'react-native-gesture-handler'; @@ -142,14 +142,6 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; - _renderSectionHeader = ({ section }) => { - return ( - - {section.title} - - ); - }; - _renderItem = ({ item: attendee }) => ( ); @@ -173,6 +165,13 @@ class DeferredAttendeesContent extends React.Component { } const attendees = data && data.events && data.events[0] ? data.events[0].attendees : []; + const filteredAttendees = attendees.filter(attendee => { + const fullName = `${attendee.firstName} ${attendee.lastName}`; + return fullName + .toLowerCase() + .trim() + .includes(cleanedQuery); + }); const filteredNameAttendees = attendees.filter(attendee => { const fullName = `${attendee.firstName} ${attendee.lastName}`; return fullName @@ -204,9 +203,7 @@ class DeferredAttendeesContent extends React.Component { sections.push({ title: 'Twitter', data: filteredTwitterAttendees }); } - console.log('Attendees (filtered by name): ', filteredNameAttendees); - console.log('Attendees (filtered by email): ', filteredEmailAttendees); - console.log('Attendees (filtered by twitter): ', filteredTwitterAttendees); + console.log('Attendees: ', filteredNameAttendees); return ( @@ -219,13 +216,12 @@ class DeferredAttendeesContent extends React.Component { returnKeyLabel="Search" style={styles.textInput} /> - } - stickySectionHeadersEnabled={true} renderItem={this._renderItem} - renderSectionHeader={this._renderSectionHeader} - sections={sections} - keyExtractor={item => item.id} + renderHeader={this._renderHeader} + data={filteredAttendees} + keyExtractor={item => `${item.id}`} initialNumToRender={10} keyboardDismissMode="on-drag" /> From 5620d04bbc1c5f9bc64aaf3e1bcb24f9b16d1b8a Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:09:59 +0200 Subject: [PATCH 23/69] queryThrottle --- src/screens/Attendees.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 8f14c2d..6c52860 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -111,9 +111,16 @@ class DeferredAttendeesContent extends React.Component { }, 200); } + throttleDelayMs = 50 + throttleTimeout = null + queryThrottle = text => { + clearTimeout(this.throttleTimeout); + this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); + } + _renderHeader = () => ( this.setState({ query: text })} + onChangeText={text => this.queryThrottle(text)} placeholder="Search a conference attendee here" autoCapitalize="none" autoCorrect={false} @@ -156,13 +163,14 @@ class DeferredAttendeesContent extends React.Component { .trim() .includes(cleanedQuery) ); + console.log('filteredAttendeesByName', filteredAttendeesByName); return ( + {this._renderHeader()} } stickySectionHeadersEnabled={true} - ListHeaderComponent={this._renderHeader} renderItem={this._renderItem} renderSectionHeader={this._renderSectionHeader} sections={[ From 7f7074e7d1c315be51417ac6aa53eacfd4d85873 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 14:11:07 +0200 Subject: [PATCH 24/69] Updated copy --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index bbe832d..45d3313 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -209,7 +209,7 @@ class DeferredAttendeesContent extends React.Component { this.setState({ query: text })} - placeholder="Search a conference attendee here" + placeholder="Search for conference attendees" autoCapitalize="none" autoCorrect={false} clearButtonMode="while-editing" From f54485b7842350ba5861bf5b5197d4d2abd3b3cf Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:14:43 +0200 Subject: [PATCH 25/69] rebase --- src/components/CachedImage.js | 10 +++++++++- src/screens/Attendees.js | 22 ++-------------------- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/components/CachedImage.js b/src/components/CachedImage.js index f7d8e81..991f58e 100644 --- a/src/components/CachedImage.js +++ b/src/components/CachedImage.js @@ -8,6 +8,8 @@ export default class CachedImage extends React.Component { source: null, }; + unmounting: false + async componentDidMount() { let source = this.props.source; @@ -28,10 +30,16 @@ export default class CachedImage extends React.Component { } catch (e) { console.log(e); } finally { - this.setState({ source }); + if (!this.unmounting) { + this.setState({ source }); + } } } + componentWillUnmount() { + this.unmounting = true + } + render() { if (this.state.source) { return ; diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 45d3313..74f82a8 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -97,27 +97,11 @@ class Attendees extends React.Component { class DeferredAttendeesContent extends React.Component { state = { ready: Platform.OS === 'android' ? false : true, - tickets: [], attendees: [], query: '', }; - async getTickets() { - try { - const value = await AsyncStorage.getItem('@MySuperStore:tickets'); - this.setState({ tickets: JSON.parse(value) }); - } catch (err) { - console.log(err); - } - } - - constructor(props) { - super(props); - this.tickets = []; - } - componentDidMount() { - this.getTickets(); if (this.state.ready) { return; } @@ -143,7 +127,7 @@ class DeferredAttendeesContent extends React.Component { }; _renderItem = ({ item: attendee }) => ( - + ); render() { @@ -153,13 +137,11 @@ class DeferredAttendeesContent extends React.Component { const { query } = this.state; const cleanedQuery = query.toLowerCase().trim(); console.log('State:', this.state); + return ( {({ loading, error, data }) => { - if (loading) { - return Loading...; - } if (error) { return Error ${error}; } From b005c7cf853d534b0af140766d2fa26edc96916a Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:09:59 +0200 Subject: [PATCH 26/69] queryThrottle --- src/screens/Attendees.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 74f82a8..a887651 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -126,6 +126,13 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; + throttleDelayMs = 50 + throttleTimeout = null + queryThrottle = text => { + clearTimeout(this.throttleTimeout); + this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); + } + _renderItem = ({ item: attendee }) => ( ); @@ -190,7 +197,7 @@ class DeferredAttendeesContent extends React.Component { return ( this.setState({ query: text })} + onChangeText={text => this.queryThrottle(text)} placeholder="Search for conference attendees" autoCapitalize="none" autoCorrect={false} From 39fc595b803c42e40ddd7a4e3802e793b79a1bcc Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 14:23:20 +0200 Subject: [PATCH 27/69] Added score rankings to search results --- src/screens/Attendees.js | 61 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 45d3313..98e4b8e 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -163,47 +163,46 @@ class DeferredAttendeesContent extends React.Component { if (error) { return Error ${error}; } - const attendees = data && data.events && data.events[0] ? data.events[0].attendees : []; - const filteredAttendees = attendees.filter(attendee => { + const filteredAttendees = []; + const attendeesSearchRankingScore = {}; + attendees.forEach(attendee => { const fullName = `${attendee.firstName} ${attendee.lastName}`; - return fullName + const matchesName = fullName .toLowerCase() .trim() .includes(cleanedQuery); - }); - const filteredNameAttendees = attendees.filter(attendee => { - const fullName = `${attendee.firstName} ${attendee.lastName}`; - return fullName + const matchesEmail = attendee.email .toLowerCase() .trim() .includes(cleanedQuery); - }); - const filteredEmailAttendees = attendees.filter(attendee => - attendee.email + const matchesTwitter = this.getContactTwitter(attendee) .toLowerCase() .trim() - .includes(cleanedQuery) - ); - const filteredTwitterAttendees = attendees.filter(attendee => - this.getContactTwitter(attendee) - .toLowerCase() - .trim() - .includes(cleanedQuery) - ); - - const sections = []; - if (filteredNameAttendees.length > 0) { - sections.push({ title: 'Name', data: filteredNameAttendees }); - } - if (filteredEmailAttendees.length > 0) { - sections.push({ title: 'Email', data: filteredEmailAttendees }); - } - if (filteredTwitterAttendees.length > 0) { - sections.push({ title: 'Twitter', data: filteredTwitterAttendees }); - } + .includes(cleanedQuery); - console.log('Attendees: ', filteredNameAttendees); + attendeesSearchRankingScore[`${attendee.id}`] = 0; + if (matchesName || matchesEmail || matchesTwitter) { + filteredAttendees.push(attendee); + } + if (matchesName) { + attendeesSearchRankingScore[`${attendee.id}`] += 1; + } + if (matchesEmail) { + attendeesSearchRankingScore[`${attendee.id}`] += 1; + } + if (matchesTwitter) { + attendeesSearchRankingScore[`${attendee.id}`] += 1; + } + }); + const sortedFilteredAttendees = filteredAttendees.sort((attendee1, attendee2) => { + return ( + attendeesSearchRankingScore[`${attendee2.id}`] - + attendeesSearchRankingScore[`${attendee1.id}`] + ); + }); + console.log('Attendees: ', sortedFilteredAttendees); + console.log('Rankings: ', attendeesSearchRankingScore); return ( @@ -220,7 +219,7 @@ class DeferredAttendeesContent extends React.Component { renderScrollComponent={props => } renderItem={this._renderItem} renderHeader={this._renderHeader} - data={filteredAttendees} + data={sortedFilteredAttendees} keyExtractor={item => `${item.id}`} initialNumToRender={10} keyboardDismissMode="on-drag" From a97a3b5b4377eec57f1a1877bd543dece353ca08 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:23:45 +0200 Subject: [PATCH 28/69] Improve throttle time --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index a887651..4b87dc8 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -126,7 +126,7 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; - throttleDelayMs = 50 + throttleDelayMs = 25 throttleTimeout = null queryThrottle = text => { clearTimeout(this.throttleTimeout); From 0cd7a13d8ff1f4fe3e6d21d828d0be7f767022a0 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:45:28 +0200 Subject: [PATCH 29/69] remove duplicate code --- src/screens/Attendees.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 11de521..a669037 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -133,13 +133,6 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; - throttleDelayMs = 25 - throttleTimeout = null - queryThrottle = text => { - clearTimeout(this.throttleTimeout); - this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); - } - _renderItem = ({ item: attendee }) => ( ); From 02ea5e5e7b9a73e31105b2435a33b3b1dfe24169 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 13:41:49 +0200 Subject: [PATCH 30/69] remove tickets logic, remove loading render & fix cachedImage error --- src/components/CachedImage.js | 10 +++++++++- src/screens/Attendees.js | 21 +-------------------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/components/CachedImage.js b/src/components/CachedImage.js index f7d8e81..991f58e 100644 --- a/src/components/CachedImage.js +++ b/src/components/CachedImage.js @@ -8,6 +8,8 @@ export default class CachedImage extends React.Component { source: null, }; + unmounting: false + async componentDidMount() { let source = this.props.source; @@ -28,10 +30,16 @@ export default class CachedImage extends React.Component { } catch (e) { console.log(e); } finally { - this.setState({ source }); + if (!this.unmounting) { + this.setState({ source }); + } } } + componentWillUnmount() { + this.unmounting = true + } + render() { if (this.state.source) { return ; diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 98e4b8e..e57a51d 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -97,27 +97,11 @@ class Attendees extends React.Component { class DeferredAttendeesContent extends React.Component { state = { ready: Platform.OS === 'android' ? false : true, - tickets: [], attendees: [], query: '', }; - async getTickets() { - try { - const value = await AsyncStorage.getItem('@MySuperStore:tickets'); - this.setState({ tickets: JSON.parse(value) }); - } catch (err) { - console.log(err); - } - } - - constructor(props) { - super(props); - this.tickets = []; - } - componentDidMount() { - this.getTickets(); if (this.state.ready) { return; } @@ -143,7 +127,7 @@ class DeferredAttendeesContent extends React.Component { }; _renderItem = ({ item: attendee }) => ( - + ); render() { @@ -157,9 +141,6 @@ class DeferredAttendeesContent extends React.Component { {({ loading, error, data }) => { - if (loading) { - return Loading...; - } if (error) { return Error ${error}; } From f755c3a3fb312977d0cb1f91c9a87dae525cdd8e Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:09:59 +0200 Subject: [PATCH 31/69] queryThrottle --- src/screens/Attendees.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index e57a51d..103cc97 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -126,6 +126,13 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; + throttleDelayMs = 50 + throttleTimeout = null + queryThrottle = text => { + clearTimeout(this.throttleTimeout); + this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); + } + _renderItem = ({ item: attendee }) => ( ); From 33543c39b342dd29b8fea1d30e3867ab5c444f5e Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:14:43 +0200 Subject: [PATCH 32/69] rebase --- src/screens/Attendees.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 103cc97..f05dff0 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -144,6 +144,7 @@ class DeferredAttendeesContent extends React.Component { const { query } = this.state; const cleanedQuery = query.toLowerCase().trim(); console.log('State:', this.state); + return ( From 7e565d5dfa771e14b259435ad2fd93b1d4d494c3 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:09:59 +0200 Subject: [PATCH 33/69] queryThrottle --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index f05dff0..da06574 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -196,7 +196,7 @@ class DeferredAttendeesContent extends React.Component { return ( this.setState({ query: text })} + onChangeText={text => this.queryThrottle(text)} placeholder="Search for conference attendees" autoCapitalize="none" autoCorrect={false} From 98f90dc643c077b17efabf3ab8affb136f455825 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:23:45 +0200 Subject: [PATCH 34/69] Improve throttle time --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index da06574..23ab5f0 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -126,7 +126,7 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; - throttleDelayMs = 50 + throttleDelayMs = 25 throttleTimeout = null queryThrottle = text => { clearTimeout(this.throttleTimeout); From 75e170f924e4ddb732907819dcb17d07a435c1f2 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:45:28 +0200 Subject: [PATCH 35/69] remove duplicate code --- src/screens/Attendees.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 23ab5f0..eecd050 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -126,13 +126,6 @@ class DeferredAttendeesContent extends React.Component { .replace('twitter.com/', ''); }; - throttleDelayMs = 25 - throttleTimeout = null - queryThrottle = text => { - clearTimeout(this.throttleTimeout); - this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); - } - _renderItem = ({ item: attendee }) => ( ); From 1d5c3eed7f0d49854e27ed6af46a6956a1edc70c Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 15:01:22 +0200 Subject: [PATCH 36/69] queryThrottle --- src/screens/Attendees.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index eecd050..656124e 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -111,6 +111,13 @@ class DeferredAttendeesContent extends React.Component { }, 200); } + throttleDelayMs = 50 + throttleTimeout = null + queryThrottle = text => { + clearTimeout(this.throttleTimeout); + this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); + } + getContactTwitter = contact => { let twitter = ''; if (contact) { From 612b70d06069ec14ca76f52013838ffce5969ac2 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 15:50:41 +0200 Subject: [PATCH 37/69] increase timeout use paper searchBar and fix fontSize error --- src/screens/Attendees.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 656124e..390027a 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -19,6 +19,7 @@ import { BorderlessButton, RectButton } from 'react-native-gesture-handler'; import { NavigationActions } from 'react-navigation'; import FadeIn from 'react-native-fade-in-image'; import { View as AnimatableView } from 'react-native-animatable'; +import { Searchbar } from 'react-native-paper'; import { Ionicons } from '@expo/vector-icons'; import { withNavigation } from 'react-navigation'; import { Query } from 'react-apollo'; @@ -111,7 +112,7 @@ class DeferredAttendeesContent extends React.Component { }, 200); } - throttleDelayMs = 50 + throttleDelayMs = 200 throttleTimeout = null queryThrottle = text => { clearTimeout(this.throttleTimeout); @@ -191,17 +192,12 @@ class DeferredAttendeesContent extends React.Component { ); }); console.log('Attendees: ', sortedFilteredAttendees); - console.log('Rankings: ', attendeesSearchRankingScore); return ( - this.queryThrottle(text)} placeholder="Search for conference attendees" - autoCapitalize="none" - autoCorrect={false} - clearButtonMode="while-editing" - returnKeyLabel="Search" style={styles.textInput} /> Date: Sat, 19 May 2018 15:53:33 +0200 Subject: [PATCH 38/69] attendee detail --- src/Navigation.js | 1 + src/components/ContactCard.js | 59 ++------- src/constants/index.js | 1 + src/screens/AttendeeDetail.js | 215 +++++++++++++++++++++++++++++++ src/screens/Attendees.js | 57 +++----- src/screens/QRScreens/Contact.js | 101 ++++----------- src/screens/index.js | 2 + src/utils/index.js | 94 +++++++++++++- 8 files changed, 363 insertions(+), 167 deletions(-) create mode 100644 src/screens/AttendeeDetail.js diff --git a/src/Navigation.js b/src/Navigation.js index a33ff50..db9347a 100644 --- a/src/Navigation.js +++ b/src/Navigation.js @@ -497,6 +497,7 @@ export default StackNavigator( { Primary: { screen: DrawerNavigation }, Details: { screen: Screens.Details }, + AttendeeDetail: { screen: Screens.AttendeeDetail }, TicketInstructions: { screen: Screens.TicketInstructions }, CheckedInAttendeeInfo: { screen: Screens.CheckedInAttendeeInfo }, QRScanner: { screen: QRScannerModalNavigation }, diff --git a/src/components/ContactCard.js b/src/components/ContactCard.js index b3803b9..728d28e 100644 --- a/src/components/ContactCard.js +++ b/src/components/ContactCard.js @@ -7,7 +7,7 @@ import { withNavigation } from "react-navigation"; import GravatarImage from '../components/GravatarImage'; import SaveIconWhenSaved from "./SaveIconWhenSaved"; import { BoldText, RegularText, SemiBoldText } from "./StyledText"; -import { conferenceHasEnded, getSpeakerAvatarURL } from "../utils"; +import { sendEmail, openTwitter, getContactTwitter } from "../utils"; import { Colors, FontSizes } from "../constants"; import { Button, @@ -21,12 +21,12 @@ import { @withNavigation export default class ContactCard extends React.Component { render() { - const { contact } = this.props; + const { contact, onPress } = this.props; const { email } = contact; const bio = this.getContactBio(); - const twitter = this.getContactTwitter(); + const twitter = getContactTwitter(contact); return ( - + onPress({ ...contact, bio, twitter })}> - + ); } - _handlePressTwitterButton = async () => { - const twitter = this.getContactTwitter(); - try { - await Linking.openURL(`twitter://user?screen_name=` + twitter); - } catch (e) { - WebBrowser.openBrowserAsync("https://twitter.com/" + twitter); - } + _handlePressTwitterButton = () => { + const twitter = getContactTwitter(this.props.contact); + openTwitter(twitter); }; _handlePressEmailButton = () => { const contact = this.props.contact; - const email = contact.email; + const emailTo = contact.email; const { tickets } = this.props; - let me = { firstName: "", lastName: "" }; + let fromName = { firstName: "", lastName: "" }; if (tickets && tickets[0] && tickets[0].firstName) { - me = tickets[0]; - } - const emailurl = - "mailto:" + - email + - "?subject=hey it's" + - " " + - me.firstName + - " " + - me.lastName + - " " + - "from ReactEurope&body=ping"; - try { - Platform.OS === "android" - ? WebBrowser.openBrowserAsync(emailurl) - : Linking.openURL(emailurl); - } catch (e) { - WebBrowser.openBrowserAsync("mailto:" + email); + fromName = tickets[0]; } + sendEmail(emailTo, fromName); }; getContactBio = () => { let contact = this.props.contact; @@ -95,21 +75,6 @@ export default class ContactCard extends React.Component { } return bio; }; - getContactTwitter = () => { - let contact = this.props.contact; - let twitter = ""; - if (contact) { - contact.answers.map(answer => { - if (answer.question && answer.question.title === "Twitter") { - twitter = answer.value; - } - }); - } - return twitter - .replace("@", "") - .replace("https://twitter.com/", "") - .replace("twitter.com/", ""); - }; } const styles = StyleSheet.create({ avatarImage: { diff --git a/src/constants/index.js b/src/constants/index.js index a2d82a6..fdfed44 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -24,6 +24,7 @@ export const Layout = { export const Colors = { blue: "#4d5fab", + rose: "#aa4d5e", faint: "#7a7a7a" }; diff --git a/src/screens/AttendeeDetail.js b/src/screens/AttendeeDetail.js new file mode 100644 index 0000000..e720c2c --- /dev/null +++ b/src/screens/AttendeeDetail.js @@ -0,0 +1,215 @@ +import React from 'react'; +import { + Animated, + Platform, + StyleSheet, + TouchableOpacity, + View, +} from 'react-native'; +import { View as AnimatableView } from 'react-native-animatable'; +import { Button } from 'react-native-paper'; +import { Constants } from 'expo'; +import FadeIn from 'react-native-fade-in-image'; +import _ from 'lodash'; + +import AnimatedScrollView from '../components/AnimatedScrollView'; +import NavigationBar from '../components/NavigationBar'; +import { Colors, FontSizes, Layout } from '../constants'; +import { RegularText, SemiBoldText } from '../components/StyledText'; +import GravatarImage from '../components/GravatarImage'; +import CloseButton from '../components/CloseButton'; +export const Schedule = require('../data/schedule.json'); +import { sendEmail, openTwitter, addContact, getContactTwitter } from "../utils"; + + +export default class AttendeeDetail extends React.Component { + state = { + scrollY: new Animated.Value(0), + }; + + _handlePressTwitterButton = () => { + const { attendee } = this.props.navigation.state.params; + const twitter = getContactTwitter(attendee); + openTwitter(twitter); + }; + + _handlePressEmailButton = () => { + const { attendee: { email: emailTo } } = this.props.navigation.state.params; + const { tickets } = this.props; + let fromName = { firstName: "", lastName: "" }; + if (tickets && tickets[0] && tickets[0].firstName) { + fromName = tickets[0]; + } + sendEmail(emailTo, fromName); + }; + + _handleAddToContacts = async () => { + const { navigation } = this.props; + const { attendee } = navigation.state.params; + await addContact(attendee); + navigation.navigate('Contacts'); + }; + + render() { + const params = this.props.navigation.state.params || {}; + const attendee = params.attendee; + + if (!attendee || !_.has(attendee, 'email')) { + this.props.navigation.goBack(); + return null; + } + + const { scrollY } = this.state; + const scale = scrollY.interpolate({ + inputRange: [-300, 0, 1], + outputRange: [2, 1, 1], + extrapolate: 'clamp', + }); + const translateX = 0; + const translateY = scrollY.interpolate({ + inputRange: [-300, 0, 1], + outputRange: [-50, 1, 1], + extrapolate: 'clamp', + }); + + const headerOpacity = scrollY.interpolate({ + inputRange: [0, 30, 200], + outputRange: [0, 0, 1], + }); + + return ( + + {Platform.OS === 'ios' ? ( + + ) : null} + + + + + + + + + {attendee.firstName} {attendee.lastName} + + {attendee && attendee.twitter ? ( + + + @{attendee.twitter} + + + ) : null} + {attendee && attendee.email ? ( + + + {attendee.email} + + + ) : null} + + + + + + + + + ( + 0 ? -5 : 0, + }}> + this.props.navigation.goBack()} + tintColor="#fff" + title={null} + /> + + )} + /> + + ); + } +} + +const styles = StyleSheet.create({ + container: {}, + avatar: { + width: 100, + height: 100, + borderRadius: 50, + marginBottom: 10, + }, + content: { + backgroundColor: '#fff', + paddingTop: 20, + paddingBottom: 20, + paddingHorizontal: 20, + }, + headerContainer: { + backgroundColor: Colors.rose, + paddingTop: Constants.statusBarHeight + Layout.notchHeight + 20, + paddingBottom: 20, + paddingHorizontal: 20, + alignItems: 'center', + justifyContent: 'center', + }, + headerText: { + color: '#fff', + fontSize: FontSizes.subtitle, + }, +}); diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 656124e..588f315 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,48 +1,27 @@ -import React, { Component } from 'react'; -import _ from 'lodash'; +import React from 'react'; import { ScrollView } from 'react-native-gesture-handler'; import { Animated, - Linking, Platform, Text, - Image, - TouchableOpacity, StyleSheet, - AsyncStorage, View, TextInput, FlatList, } from 'react-native'; -import { Asset, LinearGradient, WebBrowser, Video } from 'expo'; -import { BorderlessButton, RectButton } from 'react-native-gesture-handler'; -import { NavigationActions } from 'react-navigation'; -import FadeIn from 'react-native-fade-in-image'; import { View as AnimatableView } from 'react-native-animatable'; -import { Ionicons } from '@expo/vector-icons'; import { withNavigation } from 'react-navigation'; import { Query } from 'react-apollo'; import AnimatedScrollView from '../components/AnimatedScrollView'; -import MyContacts from '../components/MyContacts'; import NavigationBar from '../components/NavigationBar'; import MenuButton from '../components/MenuButton'; -import VideoBackground from '../components/VideoBackground'; -import { BoldText, SemiBoldText, RegularText } from '../components/StyledText'; -import { connectDrawerButton } from '../Navigation'; import { Colors, FontSizes, Layout } from '../constants'; -import { Speakers, Talks } from '../data'; -import { - HideWhenConferenceHasStarted, - HideWhenConferenceHasEnded, - ShowWhenConferenceHasEnded, -} from '../utils'; import ContactCard from '../components/ContactCard'; import GET_ATTENDEES from '../data/attendeesquery'; -import CachedImage from '../components/CachedImage'; +import { getContactTwitter } from '../utils'; export const Schedule = require('../data/schedule.json'); -const Event = Schedule.events[0]; class Attendees extends React.Component { state = { @@ -118,25 +97,19 @@ class DeferredAttendeesContent extends React.Component { this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); } - getContactTwitter = contact => { - let twitter = ''; - if (contact) { - contact.answers.map(answer => { - if (answer.question && answer.question.title === 'Twitter') { - twitter = answer.value; - } - }); - } - return twitter - .replace('@', '') - .replace('https://twitter.com/', '') - .replace('twitter.com/', ''); - }; - _renderItem = ({ item: attendee }) => ( - + ); + _handlePressRow = attendee => { + this.props.navigation.navigate('AttendeeDetail', { attendee }); + }; + render() { if (!this.state.ready) { return null; @@ -144,11 +117,11 @@ class DeferredAttendeesContent extends React.Component { const { query } = this.state; const cleanedQuery = query.toLowerCase().trim(); console.log('State:', this.state); - + return ( - {({ loading, error, data }) => { + {({ error, data }) => { if (error) { return Error ${error}; } @@ -165,7 +138,7 @@ class DeferredAttendeesContent extends React.Component { .toLowerCase() .trim() .includes(cleanedQuery); - const matchesTwitter = this.getContactTwitter(attendee) + const matchesTwitter = getContactTwitter(attendee) .toLowerCase() .trim() .includes(cleanedQuery); diff --git a/src/screens/QRScreens/Contact.js b/src/screens/QRScreens/Contact.js index 7aef88b..bfa8e86 100644 --- a/src/screens/QRScreens/Contact.js +++ b/src/screens/QRScreens/Contact.js @@ -1,9 +1,9 @@ import React from 'react'; import { AsyncStorage } from 'react-native'; -import { BarCodeScanner, Permissions } from 'expo'; import { query } from 'urql'; import { GQL } from '../../constants'; +import { addContact } from '../../utils'; import client from '../../utils/gqlClient'; import QRScreen from './QRScreen'; @@ -29,83 +29,34 @@ query events($slug: String!, $uuid: String!, $q: String!){ `; export default class QRContactScannerModalNavigation extends React.Component { - _handleContactBarCodeRead = data => { + _handleContactBarCodeRead = async data => { let navigation = this.props.navigation; - AsyncStorage.getItem('@MySuperStore:tickets').then(value => { - let tickets = JSON.parse(value) || []; - let uuid = ''; - let contactRef = data.data; - tickets.map(ticket => { - ticket.checkinLists.map(ch => { - if (ch.mainEvent) { - uuid = ticket.uuid; - } - }); + const value = await AsyncStorage.getItem('@MySuperStore:tickets'); + let tickets = JSON.parse(value) || []; + let uuid = ''; + let contactRef = data.data; + tickets.map(ticket => { + ticket.checkinLists.map(ch => { + if (ch.mainEvent) { + uuid = ticket.uuid; + } }); - let variables = { slug: GQL.slug, uuid: uuid, q: contactRef }; - client - .executeQuery(query(qrContactQuery, variables), true) - .then(function(scannedContact) { - if ( - scannedContact && - scannedContact.data && - scannedContact.data.events && - scannedContact.data.events[0] && - scannedContact.data.events[0].attendees && - scannedContact.data.events[0].attendees[0] - ) { - let contact = scannedContact.data.events[0].attendees[0]; - console.log('new contact', contact); - AsyncStorage.getItem('@MySuperStore:contacts').then( - storedContacts => { - let contacts = null; - let newContacts = []; - let found = false; - if (storedContacts === null && contact && contact.firstName) { - contacts = [contact]; - } else { - let existingContacts = JSON.parse(storedContacts) || []; - console.log( - 'how many existing contacts', - existingContacts.length - ); - existingContacts.map((existingContact, i) => { - console.log('existing contact', existingContact); - if ( - existingContact && - existingContact.id && - contact && - contact.id && - existingContact.id === contact.id - ) { - found = true; - newContacts.push(contact); - } else if (existingContact && existingContact.id) { - newContacts.push(existingContact); - } - }); - if (!found && contact && contact.id) { - newContacts.push(contact); - } - contacts = newContacts; - } - if (contacts === [null]) { - contacts = []; - } - let stringifiedContacts = JSON.stringify(contacts); - AsyncStorage.setItem( - '@MySuperStore:contacts', - stringifiedContacts - ) - //AsyncStorage.removeItem('@MySuperStore:tickets') - .then(value => { - navigation.navigate('Contacts'); - }); - } - ); - } - }); }); + let variables = { slug: GQL.slug, uuid: uuid, q: contactRef }; + const scannedContact = await client.executeQuery(query(qrContactQuery, variables), true); + if ( + scannedContact && + scannedContact.data && + scannedContact.data.events && + scannedContact.data.events[0] && + scannedContact.data.events[0].attendees && + scannedContact.data.events[0].attendees[0] + ) { + let contact = scannedContact.data.events[0].attendees[0]; + console.log('new contact', contact); + await addContact(contact); + navigation.navigate('Contacts'); + } }; render() { diff --git a/src/screens/index.js b/src/screens/index.js index 833dac5..f97f32f 100644 --- a/src/screens/index.js +++ b/src/screens/index.js @@ -10,6 +10,7 @@ import TicketInstructions from "./TicketInstructions"; import StaffCheckinLists from "./StaffCheckinLists"; import CheckedInAttendeeInfo from "./CheckedInAttendeeInfo"; import Attendees from "./Attendees"; +import AttendeeDetail from "./AttendeeDetail"; export default { Home, @@ -24,4 +25,5 @@ export default { StaffCheckinLists, CheckedInAttendeeInfo, Attendees, + AttendeeDetail, }; diff --git a/src/utils/index.js b/src/utils/index.js index fdd1bdd..bcb418a 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,5 +1,9 @@ import moment from "moment-timezone"; import _ from "lodash"; +import { Platform, Linking } from "react-native"; +import { WebBrowser } from "expo"; +import { AsyncStorage } from 'react-native'; + export const Schedule = require("../data/schedule.json"); const Event = Schedule.events[0]; @@ -28,9 +32,6 @@ export function convertUtcDateToEventTimezoneDaytime(date) { return moment.tz(d, Event.timezoneId).format("dddd DD MMM, h:mma"); } -const CONFERENCE_START_TIME = convertUtcDateToEventTimezone(Event.startDate); -const CONFERENCE_END_TIME = convertUtcDateToEventTimezone(Event.endDate); - export function conferenceHasStarted() { return Event.status.hasStarted; } @@ -62,3 +63,90 @@ export function ShowWhenConferenceHasEnded({ children }) { return null; } } + +export const sendEmail = (emailTo, fromName = { firstName: "", lastName: "" }) => { + const emailurl = + "mailto:" + + emailTo + + "?subject=hey it's" + + " " + + fromName.firstName + + " " + + fromName.lastName + + " " + + "from ReactEurope&body=ping"; + try { + Platform.OS === "android" + ? WebBrowser.openBrowserAsync(emailurl) + : Linking.openURL(emailurl); + } catch (e) { + WebBrowser.openBrowserAsync("mailto:" + emailTo); + } +}; + +export const openTwitter = async (twitter) => { + try { + await Linking.openURL(`twitter://user?screen_name=` + twitter); + } catch (e) { + WebBrowser.openBrowserAsync("https://twitter.com/" + twitter); + } +} + +export const addContact = async (contact) => { + const storedContacts = await AsyncStorage.getItem('@MySuperStore:contacts'); + + let contacts = null; + let newContacts = []; + let found = false; + if (storedContacts === null && contact && contact.firstName) { + contacts = [contact]; + } else { + let existingContacts = JSON.parse(storedContacts) || []; + console.log( + 'how many existing contacts', + existingContacts.length + ); + existingContacts.map((existingContact) => { + console.log('existing contact', existingContact); + if ( + existingContact && + existingContact.id && + contact && + contact.id && + existingContact.id === contact.id + ) { + found = true; + newContacts.push(contact); + } else if (existingContact && existingContact.id) { + newContacts.push(existingContact); + } + }); + if (!found && contact && contact.id) { + newContacts.push(contact); + } + contacts = newContacts; + } + if (contacts === [null]) { + contacts = []; + } + let stringifiedContacts = JSON.stringify(contacts); + return AsyncStorage.setItem( + '@MySuperStore:contacts', + stringifiedContacts + ); +}; + +export const getContactTwitter = (contact) => { + let twitter = ""; + if (contact) { + contact.answers.map(answer => { + if (answer.question && answer.question.title === "Twitter") { + twitter = answer.value; + } + }); + } + return twitter + .replace("@", "") + .replace("https://twitter.com/", "") + .replace("twitter.com/", ""); +}; From 8df2aa805890d95eb487680307f86e4fe53877b7 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 16:28:12 +0200 Subject: [PATCH 39/69] Searchbar styles --- src/screens/Attendees.js | 51 ++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 390027a..bd159fb 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -48,8 +48,17 @@ const Event = Schedule.events[0]; class Attendees extends React.Component { state = { scrollY: new Animated.Value(0), + attendees: [], + query: '', }; + throttleDelayMs = 200 + throttleTimeout = null + queryThrottle = text => { + clearTimeout(this.throttleTimeout); + this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); + } + render() { const { scrollY } = this.state; const headerOpacity = scrollY.interpolate({ @@ -58,7 +67,14 @@ class Attendees extends React.Component { extrapolate: 'clamp', }); return ( - + + this.queryThrottle(text)} + placeholder="Search for conference attendees" + style={styles.textInput} + /> + {/* + */} - + @@ -98,8 +114,6 @@ class Attendees extends React.Component { class DeferredAttendeesContent extends React.Component { state = { ready: Platform.OS === 'android' ? false : true, - attendees: [], - query: '', }; componentDidMount() { @@ -112,12 +126,7 @@ class DeferredAttendeesContent extends React.Component { }, 200); } - throttleDelayMs = 200 - throttleTimeout = null - queryThrottle = text => { - clearTimeout(this.throttleTimeout); - this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); - } + getContactTwitter = contact => { let twitter = ''; @@ -142,7 +151,7 @@ class DeferredAttendeesContent extends React.Component { if (!this.state.ready) { return null; } - const { query } = this.state; + const { query } = this.props; const cleanedQuery = query.toLowerCase().trim(); console.log('State:', this.state); @@ -195,11 +204,6 @@ class DeferredAttendeesContent extends React.Component { return ( - this.queryThrottle(text)} - placeholder="Search for conference attendees" - style={styles.textInput} - /> } renderItem={this._renderItem} @@ -208,6 +212,7 @@ class DeferredAttendeesContent extends React.Component { keyExtractor={item => `${item.id}`} initialNumToRender={10} keyboardDismissMode="on-drag" + style={styles.list} /> ); @@ -316,13 +321,23 @@ const styles = StyleSheet.create({ borderColor: '#eee', }, textInput: { + height: 60, + position: 'absolute', + top: 90, + left: 0, + right: 0, + marginLeft: 6, + marginRight: 6, + zIndex: 10, backgroundColor: 'white', - margin: 5, padding: 5, borderRadius: 4, - borderWidth: 1, + borderWidth: 0, borderColor: 'black', }, + list: { + marginTop: 80, + } }); export default Attendees; From 650c3f528871a4be058c11908e871b486b93f2b7 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 16:04:14 +0200 Subject: [PATCH 40/69] Added new search results for attendees --- src/components/AttendeesSearchResults.js | 96 ++++++++++++++++++++ src/screens/Attendees.js | 109 +++-------------------- 2 files changed, 108 insertions(+), 97 deletions(-) create mode 100644 src/components/AttendeesSearchResults.js diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js new file mode 100644 index 0000000..7a0e6d5 --- /dev/null +++ b/src/components/AttendeesSearchResults.js @@ -0,0 +1,96 @@ +import React from 'react'; +import { StyleSheet, View, FlatList, Platform } from 'react-native'; +import { ScrollView, RectButton } from 'react-native-gesture-handler'; +import { Entypo, MaterialIcons } from '@expo/vector-icons'; + +import { BoldText, SemiBoldText, RegularText } from './StyledText'; +import LoadingPlaceholder from './LoadingPlaceholder'; +import GravatarImage from './GravatarImage'; +import { getContactTwitter } from '../utils'; + +class AttendeeSearchResultRow extends React.Component { + render() { + const { attendee } = this.props; + return ( + this.props.onPress(attendee)} + activeOpacity={0.05} + style={{ flex: 1, backgroundColor: '#fff' }} + > + + + + + + {`${attendee.firstName} ${attendee.lastName}`} + {attendee.email ? ( + + + {attendee.email} + + ) : null} + {this.getAttendeeTwitter() ? ( + + + @{getContactTwitter(attendee)} + + ) : null} + + + + ); + } +} + +export default class AttendeeSearchResults extends React.Component { + render() { + return ( + + } + renderItem={this._renderItem} + data={this.props.attendees} + keyExtractor={item => `${item.id}`} + initialNumToRender={10} + keyboardDismissMode="on-drag" + /> + + ); + } + + _renderItem = ({ item: attendee }) => { + return ; + }; + + _handlePressRow = attendee => { + this.props.navigation.navigate('AttendeeDetail', { attendee }); + }; +} + +const styles = StyleSheet.create({ + row: { + flex: 1, + padding: 10, + borderBottomWidth: StyleSheet.hairlineWidth, + borderColor: '#eee', + flexDirection: 'row', + }, + rowAvatarContainer: { + paddingVertical: 5, + paddingRight: 10, + paddingLeft: 0, + }, + avatarImage: { + width: 50, + height: 50, + borderRadius: 25, + }, + rowData: { + flex: 1, + }, +}); diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 588f315..141bacc 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -8,6 +8,7 @@ import { View, TextInput, FlatList, + LayoutAnimation, } from 'react-native'; import { View as AnimatableView } from 'react-native-animatable'; import { withNavigation } from 'react-navigation'; @@ -84,27 +85,19 @@ class DeferredAttendeesContent extends React.Component { if (this.state.ready) { return; } - - setTimeout(() => { - this.setState({ ready: true }); - }, 200); + setTimeout(() => this.setState({ ready: true }), 200); } - throttleDelayMs = 50 - throttleTimeout = null + throttleDelayMs = 200; + throttleTimeout = null; queryThrottle = text => { clearTimeout(this.throttleTimeout); - this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); - } - _renderItem = ({ item: attendee }) => ( - - ); + this.throttleTimeout = setTimeout(() => { + LayoutAnimation.easeInEaseOut(); + this.setState({ query: text }); + }, this.throttleDelayMs); + }; _handlePressRow = attendee => { this.props.navigation.navigate('AttendeeDetail', { attendee }); @@ -177,14 +170,9 @@ class DeferredAttendeesContent extends React.Component { returnKeyLabel="Search" style={styles.textInput} /> - } - renderItem={this._renderItem} - renderHeader={this._renderHeader} - data={sortedFilteredAttendees} - keyExtractor={item => `${item.id}`} - initialNumToRender={10} - keyboardDismissMode="on-drag" + ); @@ -219,79 +207,6 @@ const ClipBorderRadius = ({ children, style }) => { const BORDER_RADIUS = 3; const styles = StyleSheet.create({ - headerContent: { - alignItems: 'center', - marginTop: 5, - paddingVertical: 10, - }, - headerVideoLayer: { - ...StyleSheet.absoluteFillObject, - }, - headerVideoOverlay: { - ...StyleSheet.absoluteFillObject, - backgroundColor: Colors.blue, - opacity: 0.8, - }, - headerText: { - color: '#fff', - textAlign: 'center', - fontSize: 17, - lineHeight: 17 * 1.5, - }, - headerSmallText: { - color: '#fff', - textAlign: 'center', - fontSize: 7, - lineHeight: 7 * 1.5, - }, - bigButton: { - backgroundColor: Colors.blue, - paddingHorizontal: 15, - height: 50, - marginHorizontal: 15, - alignItems: 'center', - justifyContent: 'center', - borderRadius: BORDER_RADIUS, - overflow: 'hidden', - flexDirection: 'row', - }, - bigButtonText: { - fontSize: FontSizes.normalButton, - color: '#fff', - textAlign: 'center', - }, - seeAllTalks: { - fontSize: FontSizes.normalButton, - color: Colors.blue, - }, - autocompleteContainer: { - marginLeft: 10, - marginRight: 10, - }, - row: { - flex: 1, - padding: 10, - borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: '#eee', - backgroundColor: '#fff', - flexDirection: 'row', - }, - rowAvatarContainer: { - paddingVertical: 5, - paddingRight: 10, - paddingLeft: 0, - }, - rowData: { - flex: 1, - }, - sectionHeader: { - paddingHorizontal: 10, - paddingTop: 7, - paddingBottom: 5, - backgroundColor: '#eee', - borderWidth: 1, - borderColor: '#eee', - }, textInput: { backgroundColor: 'white', margin: 5, From 4b9390d8bfd95fdd7d20fbad31c40bc4c8126c05 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 16:25:43 +0200 Subject: [PATCH 41/69] Added styling to search result --- src/components/AttendeesSearchResults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index 7a0e6d5..7700d58 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -1,5 +1,5 @@ import React from 'react'; -import { StyleSheet, View, FlatList, Platform } from 'react-native'; +import { StyleSheet, View, FlatList } from 'react-native'; import { ScrollView, RectButton } from 'react-native-gesture-handler'; import { Entypo, MaterialIcons } from '@expo/vector-icons'; From c04d0a41099e2577505e31225092a7ba7386670f Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 13:41:49 +0200 Subject: [PATCH 42/69] remove tickets logic, remove loading render & fix cachedImage error --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 588f315..27c955d 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -121,7 +121,7 @@ class DeferredAttendeesContent extends React.Component { return ( - {({ error, data }) => { + {({ loading, error, data }) => { if (error) { return Error ${error}; } From 7846b619fb0c92ae8e2aa7cc2132c8c5e477f20a Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:09:59 +0200 Subject: [PATCH 43/69] queryThrottle --- src/screens/Attendees.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 27c955d..95b3414 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -97,6 +97,13 @@ class DeferredAttendeesContent extends React.Component { this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); } + throttleDelayMs = 50 + throttleTimeout = null + queryThrottle = text => { + clearTimeout(this.throttleTimeout); + this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); + } + _renderItem = ({ item: attendee }) => ( Date: Sat, 19 May 2018 14:14:43 +0200 Subject: [PATCH 44/69] rebase --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 95b3414..a3a9395 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -124,7 +124,7 @@ class DeferredAttendeesContent extends React.Component { const { query } = this.state; const cleanedQuery = query.toLowerCase().trim(); console.log('State:', this.state); - + return ( From d21e8fb1c4841a6666fc12ce43cbc89eb8aa0f07 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:23:45 +0200 Subject: [PATCH 45/69] Improve throttle time --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index a3a9395..d20ed2f 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -97,7 +97,7 @@ class DeferredAttendeesContent extends React.Component { this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); } - throttleDelayMs = 50 + throttleDelayMs = 25 throttleTimeout = null queryThrottle = text => { clearTimeout(this.throttleTimeout); From 8329d855b3defaa5850e53f09be0dfef1f496cb5 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 14:45:28 +0200 Subject: [PATCH 46/69] remove duplicate code --- src/screens/Attendees.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index d20ed2f..06492be 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -97,13 +97,6 @@ class DeferredAttendeesContent extends React.Component { this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); } - throttleDelayMs = 25 - throttleTimeout = null - queryThrottle = text => { - clearTimeout(this.throttleTimeout); - this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); - } - _renderItem = ({ item: attendee }) => ( Date: Sat, 19 May 2018 15:50:41 +0200 Subject: [PATCH 47/69] increase timeout use paper searchBar and fix fontSize error --- src/screens/Attendees.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 06492be..ebab856 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -10,6 +10,11 @@ import { FlatList, } from 'react-native'; import { View as AnimatableView } from 'react-native-animatable'; +<<<<<<< HEAD +======= +import { Searchbar } from 'react-native-paper'; +import { Ionicons } from '@expo/vector-icons'; +>>>>>>> increase timeout use paper searchBar and fix fontSize error import { withNavigation } from 'react-navigation'; import { Query } from 'react-apollo'; @@ -90,7 +95,7 @@ class DeferredAttendeesContent extends React.Component { }, 200); } - throttleDelayMs = 50 + throttleDelayMs = 200 throttleTimeout = null queryThrottle = text => { clearTimeout(this.throttleTimeout); @@ -164,17 +169,12 @@ class DeferredAttendeesContent extends React.Component { ); }); console.log('Attendees: ', sortedFilteredAttendees); - console.log('Rankings: ', attendeesSearchRankingScore); return ( - this.queryThrottle(text)} placeholder="Search for conference attendees" - autoCapitalize="none" - autoCorrect={false} - clearButtonMode="while-editing" - returnKeyLabel="Search" style={styles.textInput} /> Date: Sat, 19 May 2018 16:28:12 +0200 Subject: [PATCH 48/69] Searchbar styles --- src/screens/Attendees.js | 51 ++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index ebab856..b33b5b5 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -31,8 +31,17 @@ export const Schedule = require('../data/schedule.json'); class Attendees extends React.Component { state = { scrollY: new Animated.Value(0), + attendees: [], + query: '', }; + throttleDelayMs = 200 + throttleTimeout = null + queryThrottle = text => { + clearTimeout(this.throttleTimeout); + this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); + } + render() { const { scrollY } = this.state; const headerOpacity = scrollY.interpolate({ @@ -41,7 +50,14 @@ class Attendees extends React.Component { extrapolate: 'clamp', }); return ( - + + this.queryThrottle(text)} + placeholder="Search for conference attendees" + style={styles.textInput} + /> + {/* + */} - + @@ -81,8 +97,6 @@ class Attendees extends React.Component { class DeferredAttendeesContent extends React.Component { state = { ready: Platform.OS === 'android' ? false : true, - attendees: [], - query: '', }; componentDidMount() { @@ -95,12 +109,7 @@ class DeferredAttendeesContent extends React.Component { }, 200); } - throttleDelayMs = 200 - throttleTimeout = null - queryThrottle = text => { - clearTimeout(this.throttleTimeout); - this.throttleTimeout = setTimeout(() => this.setState({ query: text }), this.throttleDelayMs); - } + _renderItem = ({ item: attendee }) => ( - this.queryThrottle(text)} - placeholder="Search for conference attendees" - style={styles.textInput} - /> } renderItem={this._renderItem} @@ -185,6 +189,7 @@ class DeferredAttendeesContent extends React.Component { keyExtractor={item => `${item.id}`} initialNumToRender={10} keyboardDismissMode="on-drag" + style={styles.list} /> ); @@ -293,13 +298,23 @@ const styles = StyleSheet.create({ borderColor: '#eee', }, textInput: { + height: 60, + position: 'absolute', + top: 90, + left: 0, + right: 0, + marginLeft: 6, + marginRight: 6, + zIndex: 10, backgroundColor: 'white', - margin: 5, padding: 5, borderRadius: 4, - borderWidth: 1, + borderWidth: 0, borderColor: 'black', }, + list: { + marginTop: 80, + } }); export default Attendees; From b3264c95618274625bebea7c657df1901a53d707 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 16:30:04 +0200 Subject: [PATCH 49/69] remove unneeded styles --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index b33b5b5..effa3d9 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -50,7 +50,7 @@ class Attendees extends React.Component { extrapolate: 'clamp', }); return ( - + this.queryThrottle(text)} placeholder="Search for conference attendees" From 7861176db6a145020993372e1be2f003ad196470 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 16:39:15 +0200 Subject: [PATCH 50/69] Fixed twitter util errors --- src/components/AttendeesSearchResults.js | 4 ++-- src/screens/Attendees.js | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index 7700d58..ec3441b 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -34,7 +34,7 @@ class AttendeeSearchResultRow extends React.Component { {attendee.email} ) : null} - {this.getAttendeeTwitter() ? ( + {getContactTwitter(attendee) ? ( @{getContactTwitter(attendee)} @@ -64,7 +64,7 @@ export default class AttendeeSearchResults extends React.Component { } _renderItem = ({ item: attendee }) => { - return ; + return ; }; _handlePressRow = attendee => { diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 141bacc..d25646a 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -17,8 +17,10 @@ import { Query } from 'react-apollo'; import AnimatedScrollView from '../components/AnimatedScrollView'; import NavigationBar from '../components/NavigationBar'; import MenuButton from '../components/MenuButton'; -import { Colors, FontSizes, Layout } from '../constants'; import ContactCard from '../components/ContactCard'; +import AttendeesSearchResults from '../components/AttendeesSearchResults'; + +import { Colors, FontSizes, Layout } from '../constants'; import GET_ATTENDEES from '../data/attendeesquery'; import { getContactTwitter } from '../utils'; From 93277d0ecf25f446d93a29b9bd275ef40d5b616c Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 16:41:17 +0200 Subject: [PATCH 51/69] Searchbar --- src/screens/Attendees.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index effa3d9..4bd8b50 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -10,11 +10,8 @@ import { FlatList, } from 'react-native'; import { View as AnimatableView } from 'react-native-animatable'; -<<<<<<< HEAD -======= import { Searchbar } from 'react-native-paper'; import { Ionicons } from '@expo/vector-icons'; ->>>>>>> increase timeout use paper searchBar and fix fontSize error import { withNavigation } from 'react-navigation'; import { Query } from 'react-apollo'; From 8aac24c2ba29449ac7ed0870d424db52f740fc39 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 16:43:47 +0200 Subject: [PATCH 52/69] Searchbar --- src/screens/Attendees.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index b67c07c..e3f09ae 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -53,8 +53,6 @@ class Attendees extends React.Component { placeholder="Search for conference attendees" style={styles.textInput} /> - {/* - */} Date: Sat, 19 May 2018 17:04:17 +0200 Subject: [PATCH 53/69] Fix searchbar position on non-dank phones --- src/screens/Attendees.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index eb5c2df..3903cab 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -218,7 +218,7 @@ const styles = StyleSheet.create({ textInput: { height: 60, position: 'absolute', - top: 90, + top: 70 + Layout.notchHeight, left: 0, right: 0, marginLeft: 6, From c5a847a2e55900d981c618fa4e1b1415132a5312 Mon Sep 17 00:00:00 2001 From: Jim McGee Date: Sat, 19 May 2018 17:07:23 +0200 Subject: [PATCH 54/69] getting rid of animatedview thing --- src/components/AttendeesSearchResults.js | 3 +- src/screens/Attendees.js | 48 +++++++----------------- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index edf088b..8e23458 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -95,6 +95,7 @@ const styles = StyleSheet.create({ flex: 1, }, list: { - marginTop: 80, + paddingTop: 80, + // marginTop: 80, } }); diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index eb5c2df..3dc398d 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,28 +1,23 @@ import React from 'react'; -import { ScrollView } from 'react-native-gesture-handler'; import { Animated, Platform, Text, StyleSheet, View, - TextInput, - FlatList, LayoutAnimation, } from 'react-native'; import { View as AnimatableView } from 'react-native-animatable'; import { Searchbar } from 'react-native-paper'; -import { Ionicons } from '@expo/vector-icons'; import { withNavigation } from 'react-navigation'; import { Query } from 'react-apollo'; -import AnimatedScrollView from '../components/AnimatedScrollView'; import NavigationBar from '../components/NavigationBar'; import MenuButton from '../components/MenuButton'; import ContactCard from '../components/ContactCard'; import AttendeesSearchResults from '../components/AttendeesSearchResults'; -import { Colors, FontSizes, Layout } from '../constants'; +import { Colors, Layout } from '../constants'; import GET_ATTENDEES from '../data/attendeesquery'; import { getContactTwitter } from '../utils'; @@ -39,7 +34,7 @@ class Attendees extends React.Component { throttleTimeout = null queryThrottle = text => { clearTimeout(this.throttleTimeout); - + this.throttleTimeout = setTimeout(() => { LayoutAnimation.easeInEaseOut(); this.setState({ query: text }); @@ -60,31 +55,16 @@ class Attendees extends React.Component { placeholder="Search for conference attendees" style={styles.textInput} /> - - - - - + + + } @@ -128,7 +108,7 @@ class DeferredAttendeesContent extends React.Component { const { query } = this.props; const cleanedQuery = query.toLowerCase().trim(); console.log('State:', this.state); - + return ( @@ -218,7 +198,7 @@ const styles = StyleSheet.create({ textInput: { height: 60, position: 'absolute', - top: 90, + top: 70 + Layout.notchHeight, left: 0, right: 0, marginLeft: 6, From 5d1425e3222c62c44a9242adbffcd7a8307f07e7 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 17:07:29 +0200 Subject: [PATCH 55/69] Attended special version of highlightable text component --- src/components/HighlightableText.js | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/components/HighlightableText.js diff --git a/src/components/HighlightableText.js b/src/components/HighlightableText.js new file mode 100644 index 0000000..1333b9c --- /dev/null +++ b/src/components/HighlightableText.js @@ -0,0 +1,37 @@ +// Local implementation of 'react-native-highlight-words' +import React from 'react'; +import { Text } from 'react-native'; +import { findAll } from 'highlight-words-core'; + +/** + * Highlights all occurrences of search terms (searchText) within a string (textToHighlight). + * This function returns an array of strings and elements (wrapping highlighted words). + */ +export default function Highlighter({ + TextComponent, + autoEscape, + highlightStyle, + searchWords, + textToHighlight, + sanitize, + style, + ...props +}) { + const chunks = findAll({ textToHighlight, searchWords, sanitize, autoEscape }); + + return ( + + {chunks.map((chunk, index) => { + const text = textToHighlight.substr(chunk.start, chunk.end - chunk.start); + + return !chunk.highlight ? ( + text + ) : ( + + {text} + + ); + })} + + ); +} From 7defa9e08a7c6750fe85f76bbd82ffeeed17c611 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 17:07:44 +0200 Subject: [PATCH 56/69] Supplied query for highlighting to search results --- src/components/AttendeesSearchResults.js | 34 ++++++++++++++++++++---- src/screens/Attendees.js | 1 + 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index ec3441b..11922f5 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -2,15 +2,18 @@ import React from 'react'; import { StyleSheet, View, FlatList } from 'react-native'; import { ScrollView, RectButton } from 'react-native-gesture-handler'; import { Entypo, MaterialIcons } from '@expo/vector-icons'; +import Highlighter from 'react-native-highlight-words'; import { BoldText, SemiBoldText, RegularText } from './StyledText'; import LoadingPlaceholder from './LoadingPlaceholder'; import GravatarImage from './GravatarImage'; +import HighlightableText from './HighlightableText'; + import { getContactTwitter } from '../utils'; class AttendeeSearchResultRow extends React.Component { render() { - const { attendee } = this.props; + const { attendee, searchQuery } = this.props; return ( this.props.onPress(attendee)} @@ -22,7 +25,12 @@ class AttendeeSearchResultRow extends React.Component { - {`${attendee.firstName} ${attendee.lastName}`} + {attendee.email ? ( - {attendee.email} + ) : null} {getContactTwitter(attendee) ? ( - @{getContactTwitter(attendee)} + ) : null} @@ -64,7 +82,13 @@ export default class AttendeeSearchResults extends React.Component { } _renderItem = ({ item: attendee }) => { - return ; + return ( + + ); }; _handlePressRow = attendee => { diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index d25646a..4559952 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -175,6 +175,7 @@ class DeferredAttendeesContent extends React.Component { ); From 3ebf96e06c7f93b839c3ad3f4309de3814614ff1 Mon Sep 17 00:00:00 2001 From: Jim McGee Date: Sat, 19 May 2018 17:10:04 +0200 Subject: [PATCH 57/69] fixing color --- src/components/AttendeesSearchResults.js | 1 - src/constants/index.js | 1 - src/screens/AttendeeDetail.js | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index 8e23458..babf5f3 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -96,6 +96,5 @@ const styles = StyleSheet.create({ }, list: { paddingTop: 80, - // marginTop: 80, } }); diff --git a/src/constants/index.js b/src/constants/index.js index fdfed44..a2d82a6 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -24,7 +24,6 @@ export const Layout = { export const Colors = { blue: "#4d5fab", - rose: "#aa4d5e", faint: "#7a7a7a" }; diff --git a/src/screens/AttendeeDetail.js b/src/screens/AttendeeDetail.js index e720c2c..1ef521c 100644 --- a/src/screens/AttendeeDetail.js +++ b/src/screens/AttendeeDetail.js @@ -201,7 +201,7 @@ const styles = StyleSheet.create({ paddingHorizontal: 20, }, headerContainer: { - backgroundColor: Colors.rose, + backgroundColor: Colors.blue, paddingTop: Constants.statusBarHeight + Layout.notchHeight + 20, paddingBottom: 20, paddingHorizontal: 20, From e631dd893063ba662c033b7e91dcd22fe02164ab Mon Sep 17 00:00:00 2001 From: Jim McGee Date: Sat, 19 May 2018 17:16:41 +0200 Subject: [PATCH 58/69] fixing email and twitter --- src/screens/AttendeeDetail.js | 10 ++++++---- src/screens/Attendees.js | 12 ------------ src/screens/Details.js | 10 +++------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/screens/AttendeeDetail.js b/src/screens/AttendeeDetail.js index 1ef521c..19d8845 100644 --- a/src/screens/AttendeeDetail.js +++ b/src/screens/AttendeeDetail.js @@ -27,13 +27,13 @@ export default class AttendeeDetail extends React.Component { scrollY: new Animated.Value(0), }; - _handlePressTwitterButton = () => { + _handlePressTwitter = () => { const { attendee } = this.props.navigation.state.params; const twitter = getContactTwitter(attendee); openTwitter(twitter); }; - _handlePressEmailButton = () => { + _handlePressEmail = () => { const { attendee: { email: emailTo } } = this.props.navigation.state.params; const { tickets } = this.props; let fromName = { firstName: "", lastName: "" }; @@ -59,6 +59,8 @@ export default class AttendeeDetail extends React.Component { return null; } + const twitter = getContactTwitter(attendee); + const { scrollY } = this.state; const scale = scrollY.interpolate({ inputRange: [-300, 0, 1], @@ -125,10 +127,10 @@ export default class AttendeeDetail extends React.Component { {attendee.firstName} {attendee.lastName} - {attendee && attendee.twitter ? ( + {twitter ? ( - @{attendee.twitter} + @{twitter} ) : null} diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 3dc398d..9c7a59a 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -21,8 +21,6 @@ import { Colors, Layout } from '../constants'; import GET_ATTENDEES from '../data/attendeesquery'; import { getContactTwitter } from '../utils'; -export const Schedule = require('../data/schedule.json'); - class Attendees extends React.Component { state = { scrollY: new Animated.Value(0), @@ -184,16 +182,6 @@ const OverscrollView = () => ( /> ); -const ClipBorderRadius = ({ children, style }) => { - return ( - - {children} - - ); -}; - -const BORDER_RADIUS = 3; - const styles = StyleSheet.create({ textInput: { height: 60, diff --git a/src/screens/Details.js b/src/screens/Details.js index 29bc67f..9f55b8e 100644 --- a/src/screens/Details.js +++ b/src/screens/Details.js @@ -21,7 +21,7 @@ import AnimatedScrollView from '../components/AnimatedScrollView'; import NavigationBar from '../components/NavigationBar'; import { Colors, FontSizes, Icons, Layout } from '../constants'; import { RegularText, BoldText, SemiBoldText } from '../components/StyledText'; -import { getSpeakerTalk, convertUtcDateToEventTimezoneHour } from '../utils'; +import { getSpeakerTalk, convertUtcDateToEventTimezoneHour, openTwitter } from '../utils'; import { findTalkData, findSpeakerData } from '../data'; import SaveButton from '../components/SaveButton'; import CachedImage from '../components/CachedImage'; @@ -300,12 +300,8 @@ export default class Details extends React.Component { this.props.navigation.navigate('Details', { speaker }); }; - _handlePressSpeakerTwitter = async twitter => { - try { - await Linking.openURL(`twitter://user?screen_name=` + twitter); - } catch (e) { - WebBrowser.openBrowserAsync('https://twitter.com/' + twitter); - } + _handlePressSpeakerTwitter = twitter => { + openTwitter(twitter); }; } const markdownStyles = { From 7d6a3d1d3e9a636198da6ba955d8934e6ded383b Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 17:22:25 +0200 Subject: [PATCH 59/69] Updated text input component --- src/screens/Attendees.js | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 637f901..724173d 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -1,12 +1,5 @@ import React from 'react'; -import { - Animated, - Platform, - Text, - StyleSheet, - View, - LayoutAnimation, -} from 'react-native'; +import { Animated, Platform, Text, StyleSheet, View, LayoutAnimation } from 'react-native'; import { View as AnimatableView } from 'react-native-animatable'; import { Searchbar } from 'react-native-paper'; import { withNavigation } from 'react-navigation'; @@ -28,8 +21,8 @@ class Attendees extends React.Component { query: '', }; - throttleDelayMs = 200 - throttleTimeout = null + throttleDelayMs = 200; + throttleTimeout = null; queryThrottle = text => { clearTimeout(this.throttleTimeout); @@ -37,7 +30,7 @@ class Attendees extends React.Component { LayoutAnimation.easeInEaseOut(); this.setState({ query: text }); }, this.throttleDelayMs); - } + }; render() { const { scrollY } = this.state; @@ -52,6 +45,9 @@ class Attendees extends React.Component { onChangeText={text => this.queryThrottle(text)} placeholder="Search for conference attendees" style={styles.textInput} + autoCapitalize="none" + autoCorrect={false} + clearButtonMode="while-editing" /> - + - } animatedBackgroundOpacity={headerOpacity} @@ -86,15 +81,6 @@ class DeferredAttendeesContent extends React.Component { setTimeout(() => this.setState({ ready: true }), 200); } - _renderItem = ({ item: attendee }) => ( - - ); - _handlePressRow = attendee => { this.props.navigation.navigate('AttendeeDetail', { attendee }); }; @@ -198,7 +184,7 @@ const styles = StyleSheet.create({ borderRadius: 4, borderWidth: 0, borderColor: 'black', - } + }, }); export default Attendees; From 13b8663682b1c085b0ce3f862750aa95939bb121 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 17:46:25 +0200 Subject: [PATCH 60/69] Updated sorting logic --- src/screens/Attendees.js | 87 ++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 724173d..a523359 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -4,6 +4,7 @@ import { View as AnimatableView } from 'react-native-animatable'; import { Searchbar } from 'react-native-paper'; import { withNavigation } from 'react-navigation'; import { Query } from 'react-apollo'; +import _ from 'lodash'; import NavigationBar from '../components/NavigationBar'; import MenuButton from '../components/MenuButton'; @@ -100,50 +101,60 @@ class DeferredAttendeesContent extends React.Component { if (error) { return Error ${error}; } + const attendees = data && data.events && data.events[0] ? data.events[0].attendees : []; - const filteredAttendees = []; - const attendeesSearchRankingScore = {}; - attendees.forEach(attendee => { - const fullName = `${attendee.firstName} ${attendee.lastName}`; - const matchesName = fullName - .toLowerCase() - .trim() - .includes(cleanedQuery); - const matchesEmail = attendee.email - .toLowerCase() - .trim() - .includes(cleanedQuery); - const matchesTwitter = getContactTwitter(attendee) - .toLowerCase() - .trim() - .includes(cleanedQuery); - - attendeesSearchRankingScore[`${attendee.id}`] = 0; - if (matchesName || matchesEmail || matchesTwitter) { - filteredAttendees.push(attendee); - } - if (matchesName) { - attendeesSearchRankingScore[`${attendee.id}`] += 1; - } - if (matchesEmail) { - attendeesSearchRankingScore[`${attendee.id}`] += 1; - } - if (matchesTwitter) { - attendeesSearchRankingScore[`${attendee.id}`] += 1; - } - }); - const sortedFilteredAttendees = filteredAttendees.sort((attendee1, attendee2) => { - return ( - attendeesSearchRankingScore[`${attendee2.id}`] - - attendeesSearchRankingScore[`${attendee1.id}`] + let attendeesData; + if (cleanedQuery === '') { + attendeesData = _.orderBy( + attendees, + attendee => `${attendee.firstName} ${attendee.lastName}`, + ['asc'] + ); + } else { + const filteredAttendees = []; + const attendeesSearchRankingScore = {}; + attendees.forEach(attendee => { + const fullName = `${attendee.firstName} ${attendee.lastName}`; + const matchesName = fullName + .toLowerCase() + .trim() + .includes(cleanedQuery); + const matchesEmail = attendee.email + .toLowerCase() + .trim() + .includes(cleanedQuery); + const matchesTwitter = getContactTwitter(attendee) + .toLowerCase() + .trim() + .includes(cleanedQuery); + + attendeesSearchRankingScore[`${attendee.id}`] = 0; + if (matchesName || matchesEmail || matchesTwitter) { + filteredAttendees.push(attendee); + } + if (matchesName) { + attendeesSearchRankingScore[`${attendee.id}`] += 1; + } + if (matchesEmail) { + attendeesSearchRankingScore[`${attendee.id}`] += 1; + } + if (matchesTwitter) { + attendeesSearchRankingScore[`${attendee.id}`] += 1; + } + }); + const sortedFilteredAttendees = _.orderBy( + filteredAttendees, + attendee => attendeesSearchRankingScore[`${attendee.id}`], + ['desc'] ); - }); - console.log('Attendees: ', sortedFilteredAttendees); + attendeesData = sortedFilteredAttendees; + } + console.log('Attendees: ', attendeesData); return ( From 8479528706c40e8e306b1bc6fac3420fb3796722 Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 17:51:03 +0200 Subject: [PATCH 61/69] distinguish speakers from normal attendees and remove console logs --- src/components/AttendeesSearchResults.js | 40 +++++++++++++++++++++--- src/screens/Attendees.js | 3 -- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index edf088b..01391a9 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -1,24 +1,44 @@ import React from 'react'; import { StyleSheet, View, FlatList } from 'react-native'; import { ScrollView, RectButton } from 'react-native-gesture-handler'; -import { Entypo, MaterialIcons } from '@expo/vector-icons'; +import { Entypo, MaterialIcons, MaterialCommunityIcons, Foundation } from '@expo/vector-icons'; +import { Colors } from '../constants' import { BoldText, SemiBoldText, RegularText } from './StyledText'; import LoadingPlaceholder from './LoadingPlaceholder'; import GravatarImage from './GravatarImage'; import { getContactTwitter } from '../utils'; +export const Schedule = require('../data/schedule.json'); +const FullSchedule = Schedule.events[0].groupedSchedule; + +const SpeakersAndTalks = Schedule.events[0].speakers; +const SpeakersData = [{ data: SpeakersAndTalks, title: 'Speakers' }]; + class AttendeeSearchResultRow extends React.Component { render() { const { attendee } = this.props; + + let isSpeaker; + if (SpeakersData && SpeakersData.length) { + isSpeaker = SpeakersData[0].data.filter(speaker => { + return getContactTwitter(attendee) === speaker.twitter + })[0] ? true : false + } + return ( this.props.onPress(attendee)} activeOpacity={0.05} style={{ flex: 1, backgroundColor: '#fff' }} > - - + + {isSpeaker && } + @@ -78,13 +98,14 @@ const styles = StyleSheet.create({ flex: 1, padding: 10, borderBottomWidth: StyleSheet.hairlineWidth, - borderColor: '#eee', + borderBottomColor: '#eee', + borderLeftColor: Colors.blue, flexDirection: 'row', }, rowAvatarContainer: { paddingVertical: 5, paddingRight: 10, - paddingLeft: 0, + paddingLeft: 5, }, avatarImage: { width: 50, @@ -96,5 +117,14 @@ const styles = StyleSheet.create({ }, list: { marginTop: 80, + }, + micIcon: { + position: 'absolute', + right: 24, + alignItems: 'center', + flex: 1, + justifyContent: 'center', + height: '100%', + top: 10, } }); diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 3903cab..70a3751 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -26,8 +26,6 @@ import { Colors, FontSizes, Layout } from '../constants'; import GET_ATTENDEES from '../data/attendeesquery'; import { getContactTwitter } from '../utils'; -export const Schedule = require('../data/schedule.json'); - class Attendees extends React.Component { state = { scrollY: new Animated.Value(0), @@ -127,7 +125,6 @@ class DeferredAttendeesContent extends React.Component { } const { query } = this.props; const cleanedQuery = query.toLowerCase().trim(); - console.log('State:', this.state); return ( From b2bc531972bb0b93e4f8067b39079f876f8b247b Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 17:51:47 +0200 Subject: [PATCH 62/69] remove Foundation import --- src/components/AttendeesSearchResults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index 01391a9..0776901 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -1,7 +1,7 @@ import React from 'react'; import { StyleSheet, View, FlatList } from 'react-native'; import { ScrollView, RectButton } from 'react-native-gesture-handler'; -import { Entypo, MaterialIcons, MaterialCommunityIcons, Foundation } from '@expo/vector-icons'; +import { Entypo, MaterialIcons, MaterialCommunityIcons } from '@expo/vector-icons'; import { Colors } from '../constants' import { BoldText, SemiBoldText, RegularText } from './StyledText'; From 8597bca274f4992a290bf4b6474366dadd62e7fa Mon Sep 17 00:00:00 2001 From: MarkLyck Date: Sat, 19 May 2018 17:54:05 +0200 Subject: [PATCH 63/69] fix conflict --- src/components/AttendeesSearchResults.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index f32b85f..3cb1c32 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -1,12 +1,8 @@ import React from 'react'; import { StyleSheet, View, FlatList } from 'react-native'; import { ScrollView, RectButton } from 'react-native-gesture-handler'; -<<<<<<< HEAD import { Entypo, MaterialIcons, MaterialCommunityIcons } from '@expo/vector-icons'; -======= -import { Entypo, MaterialIcons } from '@expo/vector-icons'; import Highlighter from 'react-native-highlight-words'; ->>>>>>> react-europe-search-attendees import { Colors } from '../constants' import { BoldText, SemiBoldText, RegularText } from './StyledText'; From f11acc79dc9f500073045d65d0498a83dfbbdccb Mon Sep 17 00:00:00 2001 From: Jim McGee Date: Sat, 19 May 2018 17:59:58 +0200 Subject: [PATCH 64/69] placeholder --- src/components/AttendeesSearchResults.js | 84 +++++++++++++++++------- src/screens/Attendees.js | 13 ++-- 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index 3cb1c32..ff03d3f 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -2,23 +2,21 @@ import React from 'react'; import { StyleSheet, View, FlatList } from 'react-native'; import { ScrollView, RectButton } from 'react-native-gesture-handler'; import { Entypo, MaterialIcons, MaterialCommunityIcons } from '@expo/vector-icons'; -import Highlighter from 'react-native-highlight-words'; +import _ from 'lodash'; import { Colors } from '../constants' import { BoldText, SemiBoldText, RegularText } from './StyledText'; -import LoadingPlaceholder from './LoadingPlaceholder'; import GravatarImage from './GravatarImage'; import HighlightableText from './HighlightableText'; import { getContactTwitter } from '../utils'; export const Schedule = require('../data/schedule.json'); -const FullSchedule = Schedule.events[0].groupedSchedule; const SpeakersAndTalks = Schedule.events[0].speakers; const SpeakersData = [{ data: SpeakersAndTalks, title: 'Speakers' }]; -class AttendeeSearchResultRow extends React.Component { +class AttendeesSearchResultRow extends React.Component { render() { const { attendee, searchQuery } = this.props; @@ -85,32 +83,62 @@ class AttendeeSearchResultRow extends React.Component { } } -export default class AttendeeSearchResults extends React.Component { - render() { - return ( - - } - renderItem={this._renderItem} - data={this.props.attendees} - keyExtractor={item => `${item.id}`} - initialNumToRender={10} - keyboardDismissMode="on-drag" - style={styles.list} + +const AttendeesSearchResultPlaceholderRow = () => ( + + + + - - ); - } + + +        + + +         + + + + +); - _renderItem = ({ item: attendee }) => { +export default class AttendeesSearchResults extends React.Component { + render() { + const { attendees, isLoading } = this.props; + const maybeAttendees = isLoading ? + _.times(10).map((id) => ({ id })) : + attendees; + const itemRenderer = isLoading ? this._renderItemPlaceholder : this._renderItem; return ( - } + renderItem={itemRenderer} + data={maybeAttendees} + keyExtractor={item => `${item.id}`} + initialNumToRender={10} + keyboardDismissMode="on-drag" + style={styles.list} /> ); - }; + } + + _renderItem = ({ item: attendee }) => ( + + ); + + _renderItemPlaceholder = () => ( + + ); _handlePressRow = attendee => { this.props.navigation.navigate('AttendeeDetail', { attendee }); @@ -136,6 +164,12 @@ const styles = StyleSheet.create({ height: 50, borderRadius: 25, }, + placeholderAvatarImage: { + width: 50, + height: 50, + borderRadius: 25, + color: '#efefef' + }, rowData: { flex: 1, }, diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index c0c8c85..c2ac760 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -151,13 +151,12 @@ class DeferredAttendeesContent extends React.Component { console.log('Attendees: ', attendeesData); return ( - - - + ); }} From 96f23d58dbe399ae9b4bc99ec190b22129629e28 Mon Sep 17 00:00:00 2001 From: Jim McGee Date: Sat, 19 May 2018 18:02:07 +0200 Subject: [PATCH 65/69] fixing --- src/screens/QRScreens/Contact.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/screens/QRScreens/Contact.js b/src/screens/QRScreens/Contact.js index aefba32..20c97c6 100644 --- a/src/screens/QRScreens/Contact.js +++ b/src/screens/QRScreens/Contact.js @@ -116,7 +116,6 @@ export default class QRContactScannerModalNavigation extends React.Component { scannedContact.data.events[0].attendees[0] ) { let contact = scannedContact.data.events[0].attendees[0]; - console.log('new contact', contact); await addContact(contact); navigation.navigate('Contacts'); } From ecd1880838113df190f13fa248a11beb7a9edc78 Mon Sep 17 00:00:00 2001 From: Jim McGee Date: Sat, 19 May 2018 18:29:51 +0200 Subject: [PATCH 66/69] remove log --- src/screens/Attendees.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index c2ac760..13463f3 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -148,7 +148,6 @@ class DeferredAttendeesContent extends React.Component { ); attendeesData = sortedFilteredAttendees; } - console.log('Attendees: ', attendeesData); return ( Date: Sat, 19 May 2018 18:46:25 +0200 Subject: [PATCH 67/69] removing stuff --- src/components/ContactCard.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/ContactCard.js b/src/components/ContactCard.js index 12cd572..f75cf06 100644 --- a/src/components/ContactCard.js +++ b/src/components/ContactCard.js @@ -1,20 +1,19 @@ import React from "react"; -import { Platform, StyleSheet, View, Linking } from "react-native"; -import { WebBrowser } from "expo"; +import { Platform, StyleSheet, View } from "react-native"; +import { RectButton } from "react-native-gesture-handler"; import { withNavigation } from "react-navigation"; import GravatarImage from '../components/GravatarImage'; -import { BoldText, RegularText, SemiBoldText } from "./StyledText"; import { sendEmail, openTwitter, getContactTwitter } from "../utils"; import { Colors, FontSizes } from "../constants"; import { Button, - Card, CardActions, CardContent, Title, Paragraph } from "react-native-paper"; + @withNavigation export default class ContactCard extends React.Component { render() { From 2b2cebe75477555cc4d9204e6e3faf7f08990f32 Mon Sep 17 00:00:00 2001 From: Simon Ayzman Date: Sat, 19 May 2018 18:58:18 +0200 Subject: [PATCH 68/69] Added highlight words core --- package.json | 1 + yarn.lock | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/package.json b/package.json index 27db860..5f114e3 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "global": "^4.3.2", "graphql": "^0.13.2", "graphql-tag": "^2.9.2", + "highlight-words-core": "^1.2.0", "hoist-non-react-statics": "^2.3.1", "lodash": "^4.17.4", "moment": "2.21.0", diff --git a/yarn.lock b/yarn.lock index d7ca4d5..78afa05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3130,6 +3130,10 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" +highlight-words-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/highlight-words-core/-/highlight-words-core-1.2.0.tgz#232bec301cbf2a4943d335dc748ce70e9024f3b1" + hoek@4.x.x: version "4.2.1" resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" From fa43fed11271f53114bd6b62d4ddd7adab626b44 Mon Sep 17 00:00:00 2001 From: Jim McGee Date: Sat, 19 May 2018 19:00:13 +0200 Subject: [PATCH 69/69] fixing list behind search --- src/components/AttendeesSearchResults.js | 2 +- src/screens/Attendees.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/AttendeesSearchResults.js b/src/components/AttendeesSearchResults.js index ff03d3f..339f38f 100644 --- a/src/components/AttendeesSearchResults.js +++ b/src/components/AttendeesSearchResults.js @@ -174,7 +174,7 @@ const styles = StyleSheet.create({ flex: 1, }, list: { - marginTop: 80, + paddingTop: 80, }, micIcon: { position: 'absolute', diff --git a/src/screens/Attendees.js b/src/screens/Attendees.js index 13463f3..dba4cf9 100644 --- a/src/screens/Attendees.js +++ b/src/screens/Attendees.js @@ -8,7 +8,6 @@ import _ from 'lodash'; import NavigationBar from '../components/NavigationBar'; import MenuButton from '../components/MenuButton'; -import ContactCard from '../components/ContactCard'; import AttendeesSearchResults from '../components/AttendeesSearchResults'; import { Colors, Layout } from '../constants';