be-components 3.4.4 → 3.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/lib/commonjs/Share/index.js +185 -160
  2. package/lib/commonjs/Share/index.js.map +1 -1
  3. package/lib/commonjs/SocialComponents/Contacts/api/index.js +96 -0
  4. package/lib/commonjs/SocialComponents/Contacts/api/index.js.map +1 -0
  5. package/lib/commonjs/SocialComponents/Contacts/useContacts.js +137 -0
  6. package/lib/commonjs/SocialComponents/Contacts/useContacts.js.map +1 -0
  7. package/lib/commonjs/SocialComponents/index.js +7 -0
  8. package/lib/commonjs/SocialComponents/index.js.map +1 -1
  9. package/lib/commonjs/Squares/components/SquareCard.js +47 -1
  10. package/lib/commonjs/Squares/components/SquareCard.js.map +1 -1
  11. package/lib/commonjs/Squares/components/SquaresBoard.js +11 -1
  12. package/lib/commonjs/Squares/components/SquaresBoard.js.map +1 -1
  13. package/lib/commonjs/Squares/index.js +1 -3
  14. package/lib/commonjs/Squares/index.js.map +1 -1
  15. package/lib/module/Share/index.js +127 -102
  16. package/lib/module/Share/index.js.map +1 -1
  17. package/lib/module/SocialComponents/Contacts/api/index.js +90 -0
  18. package/lib/module/SocialComponents/Contacts/api/index.js.map +1 -0
  19. package/lib/module/SocialComponents/Contacts/useContacts.js +129 -0
  20. package/lib/module/SocialComponents/Contacts/useContacts.js.map +1 -0
  21. package/lib/module/SocialComponents/index.js +2 -1
  22. package/lib/module/SocialComponents/index.js.map +1 -1
  23. package/lib/module/Squares/components/SquareCard.js +47 -1
  24. package/lib/module/Squares/components/SquareCard.js.map +1 -1
  25. package/lib/module/Squares/components/SquaresBoard.js +12 -2
  26. package/lib/module/Squares/components/SquaresBoard.js.map +1 -1
  27. package/lib/module/Squares/index.js +1 -3
  28. package/lib/module/Squares/index.js.map +1 -1
  29. package/lib/typescript/lib/commonjs/Share/index.d.ts.map +1 -1
  30. package/lib/typescript/lib/commonjs/SocialComponents/Contacts/api/index.d.ts +11 -0
  31. package/lib/typescript/lib/commonjs/SocialComponents/Contacts/api/index.d.ts.map +1 -0
  32. package/lib/typescript/lib/commonjs/SocialComponents/Contacts/useContacts.d.ts +18 -0
  33. package/lib/typescript/lib/commonjs/SocialComponents/Contacts/useContacts.d.ts.map +1 -0
  34. package/lib/typescript/lib/commonjs/SocialComponents/index.d.ts +16 -0
  35. package/lib/typescript/lib/commonjs/Squares/components/SquareCard.d.ts +2 -15
  36. package/lib/typescript/lib/commonjs/Squares/components/SquareCard.d.ts.map +1 -1
  37. package/lib/typescript/lib/commonjs/Squares/components/SquaresBoard.d.ts.map +1 -1
  38. package/lib/typescript/lib/commonjs/Squares/index.d.ts.map +1 -1
  39. package/lib/typescript/lib/module/Share/index.d.ts +1 -2
  40. package/lib/typescript/lib/module/Share/index.d.ts.map +1 -1
  41. package/lib/typescript/lib/module/SocialComponents/Contacts/api/index.d.ts +10 -0
  42. package/lib/typescript/lib/module/SocialComponents/Contacts/api/index.d.ts.map +1 -0
  43. package/lib/typescript/lib/module/SocialComponents/Contacts/useContacts.d.ts +18 -0
  44. package/lib/typescript/lib/module/SocialComponents/Contacts/useContacts.d.ts.map +1 -0
  45. package/lib/typescript/lib/module/SocialComponents/index.d.ts +2 -1
  46. package/lib/typescript/lib/module/SocialComponents/index.d.ts.map +1 -1
  47. package/lib/typescript/lib/module/Squares/components/SquareCard.d.ts +3 -3
  48. package/lib/typescript/lib/module/Squares/components/SquareCard.d.ts.map +1 -1
  49. package/lib/typescript/lib/module/Squares/components/SquaresBoard.d.ts.map +1 -1
  50. package/lib/typescript/lib/module/Squares/index.d.ts.map +1 -1
  51. package/lib/typescript/src/Share/index.d.ts.map +1 -1
  52. package/lib/typescript/src/SocialComponents/Contacts/api/index.d.ts +15 -0
  53. package/lib/typescript/src/SocialComponents/Contacts/api/index.d.ts.map +1 -0
  54. package/lib/typescript/src/SocialComponents/Contacts/useContacts.d.ts +21 -0
  55. package/lib/typescript/src/SocialComponents/Contacts/useContacts.d.ts.map +1 -0
  56. package/lib/typescript/src/SocialComponents/index.d.ts +2 -1
  57. package/lib/typescript/src/SocialComponents/index.d.ts.map +1 -1
  58. package/lib/typescript/src/Squares/components/SquareCard.d.ts +2 -2
  59. package/lib/typescript/src/Squares/components/SquareCard.d.ts.map +1 -1
  60. package/lib/typescript/src/Squares/components/SquaresBoard.d.ts.map +1 -1
  61. package/lib/typescript/src/Squares/index.d.ts.map +1 -1
  62. package/package.json +4 -1
  63. package/src/Share/index.tsx +99 -76
  64. package/src/SocialComponents/Contacts/api/index.tsx +75 -0
  65. package/src/SocialComponents/Contacts/useContacts.tsx +113 -0
  66. package/src/SocialComponents/index.tsx +3 -1
  67. package/src/Squares/components/SquareCard.tsx +43 -2
  68. package/src/Squares/components/SquaresBoard.tsx +8 -2
  69. package/src/Squares/index.tsx +1 -3
@@ -1,19 +1,17 @@
1
1
  import React, { useEffect, useState } from 'react';
2
- import Text from '../Components/Text';
3
- import { View, TouchableOpacity, FlatList, ActivityIndicator, Clipboard, ScrollView, Platform } from 'react-native';
2
+ import { FlatList, ActivityIndicator, ScrollView, Platform } from 'react-native';
3
+ import * as Clipboard from 'expo-clipboard';
4
4
  import { view_styles } from '../constants/styles';
5
- import { Button, Icons, TextInput } from '../Components';
6
- import Colors from '../constants/colors';
5
+ import { Icons } from '../Components';
7
6
  import { ShareApi, ShareHelpers } from './api';
8
- import type { BEEventProps, GeneratedLinkProps } from '../types';
7
+ import type { BEEventProps, GeneratedLinkProps, PublicPlayerProps } from '../types';
9
8
  import EmbedPreview from './components/EmbedPreview';
9
+ import { useColors } from '../constants/useColors';
10
+ import { Button, Text, TextInput, View } from '../Components/Themed';
11
+ import { useContacts } from '../SocialComponents/Contacts/useContacts';
12
+ import * as SMS from 'expo-sms';
13
+
10
14
 
11
- const native_share_options = [
12
- { name: 'twitter', getIcon: () => <Icons.TwitterXIcon size={18}/> },
13
- { name: 'instagram', getIcon: () => <Icons.InstagramIcon size={18}/> },
14
- { name: 'facebook', getIcon:() => <Icons.FacebookIcon size={18} /> },
15
- { name: 'moare', getIcon:() => <Icons.MoreIcon size={18} color={Colors.brand.midnight} /> }
16
- ]
17
15
 
18
16
  type ShareWidgetProps = {
19
17
  redirect_url?:string,
@@ -39,6 +37,8 @@ type ShareWidgetProps = {
39
37
  }
40
38
 
41
39
  const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, maxHeight, generator, allow_edit, player_id, link_type, link_sub_type, type_id, embed, onCancel, onShare }:ShareWidgetProps) => {
40
+ const Colors = useColors();
41
+ const Contacts = useContacts({});
42
42
  const [ preview_embed, setPreviewEmbed ] = useState(false);
43
43
  const [ link_height, setLinkHeight ] = useState(0);
44
44
  const [ active_tab, setActiveTab ] = useState('link');
@@ -62,6 +62,13 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
62
62
  });
63
63
  const { loading, editing, generated_link, draft_generated_link, url, visible_id_valid, update_loading, native_share_allowed } = link_status;
64
64
 
65
+ const native_share_options = [
66
+ { name: 'twitter', getIcon: () => <Icons.TwitterXIcon size={18}/> },
67
+ { name: 'instagram', getIcon: () => <Icons.InstagramIcon size={18}/> },
68
+ { name: 'facebook', getIcon:() => <Icons.FacebookIcon size={18} /> },
69
+ { name: 'more', getIcon:() => <Icons.MoreIcon size={18} color={Colors.text.h1} /> }
70
+ ]
71
+
65
72
  useEffect(() => {
66
73
  if(!redirect_url && !generated_link_id){ return }//Unable to get redirect link
67
74
  ShareApi.setEnvironment();
@@ -111,6 +118,26 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
111
118
  });
112
119
  }
113
120
 
121
+ const handleSelectContact = async():Promise<{ player:PublicPlayerProps, number:string, sms_result:string } | undefined> => {
122
+ if(!Contacts.is_available){ return undefined }
123
+ if(!Contacts.permission){ return undefined }
124
+ if(!Contacts.permission.granted){
125
+ if(Contacts.permission.canAskAgain){
126
+ Contacts.requestPermissions();
127
+ return undefined
128
+ }
129
+ return //We dont have access!!
130
+ }
131
+
132
+ //Ok! Contacts is granted. Lets select a user
133
+ const response = await Contacts.getContact();
134
+ if(!response){ return undefined } // Sorry we failed
135
+ let avail = await SMS.isAvailableAsync()
136
+ if(!avail){ return undefined }
137
+ const { player, number } = response;
138
+ const { result } = await SMS.sendSMSAsync(response.number, `${title} ${url}`, {})
139
+ return { player, number, sms_result: result }
140
+ }
114
141
 
115
142
 
116
143
  const renderNativeOptions = (data:{ item:any, index:number }) => {
@@ -125,24 +152,21 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
125
152
  const needs_verification = link_is_changed && !visible_id_valid
126
153
  return (
127
154
  <View style={{ ...view_styles.section, minWidth:250, maxWidth, maxHeight }}>
128
- <View style={{ ...view_styles.section_header, borderBottomWidth:1, borderColor:Colors.shades.shade600 }}>
155
+ <View type='header' style={{ flexDirection:'row', alignItems:'center', padding:10 }}>
129
156
  <View style={{ flex:1 }}>
130
- <Text theme='header'>Share Modal</Text>
131
- <Text style={{ marginTop:3 }} theme='body'>{title}</Text>
157
+ <Text theme='h1'>Share Modal</Text>
158
+ <Text style={{ marginTop:3 }} theme='description'>{title}</Text>
132
159
  </View>
133
160
  <Button
134
161
  title='X'
135
- title_weight='regular'
136
- borderRadius={100}
137
- backgroundColor={Colors.shades.shade100}
138
- padding={5}
162
+ type='close'
139
163
  onPress={() => onCancel()}
140
164
  />
141
165
  </View>
142
166
  <ScrollView>
143
167
  {loading || !generated_link ?
144
168
  <View>
145
- <ActivityIndicator style={{ padding:20, alignSelf:'center' }} color={Colors.brand.midnight} size={'large'} />
169
+ <ActivityIndicator style={{ padding:20, alignSelf:'center' }} color={Colors.text.h1} size={'large'} />
146
170
  </View>
147
171
  : active_tab == 'link' ?
148
172
  <View>
@@ -150,16 +174,16 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
150
174
  <View style={{ ...view_styles.section_body }}>
151
175
  <View style={{ ...view_styles.body_row }}>
152
176
  <View style={{ flex:1 }}>
153
- <Text size={16} color={Colors.brand.midnight} weight='regular'>Edit This Link</Text>
154
- <Text style={{ marginTop:3 }} theme='body'>Edit the visible Id and query parameters below</Text>
177
+ <Text size={16} theme='description' weight='regular'>Edit This Link</Text>
178
+ <Text style={{ marginTop:3 }} theme='description'>Edit the visible Id and query parameters below</Text>
155
179
  </View>
156
180
  </View>
157
- <View style={{ backgroundColor:Colors.shades.shade100, padding:10 }}>
181
+ <View style={{ padding:10 }}>
158
182
  <View style={{ ...view_styles.body_row }}>
159
183
  <View style={{ flex:1 }}>
160
- <Text theme='header_2'>Short Link</Text>
184
+ <Text theme='h2'>Short Link</Text>
161
185
  <View style={{ flexDirection:'row', alignItems:'center' }}>
162
- <Text style={{ marginTop:3 }} theme='body'>https://share.mybe.app/id/</Text>
186
+ <Text style={{ marginTop:3 }} theme='description'>https://share.mybe.app/id/</Text>
163
187
  <TextInput
164
188
  value={draft_generated_link.visible_id}
165
189
  style={{ ...view_styles.input, flex:1, maxWidth:150 }}
@@ -176,7 +200,7 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
176
200
  </View>
177
201
  <View style={{ ...view_styles.body_row }}>
178
202
  <View style={{ flex:1 }}>
179
- <Text theme='header_2'>Link Destination</Text>
203
+ <Text theme='h1'>Link Destination</Text>
180
204
  <TextInput
181
205
  value={draft_generated_link.redirect_url}
182
206
  multiline={true}
@@ -203,20 +227,16 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
203
227
  <View style={{ ...view_styles.section_footer }}>
204
228
  <Button
205
229
  title='Cancel'
206
- title_color={Colors.shades.white}
207
- borderRadius={4}
208
- backgroundColor={Colors.utility.error}
230
+ type='error'
209
231
  onPress={() => setLinkStatus({ ...link_status, editing: false, draft_generated_link: generated_link })}
210
232
  />
211
233
  <View style={{ flex:1 }}/>
212
234
  {needs_verification ?
213
235
  <Button
214
236
  title='Check Link Availability'
215
- title_color={Colors.shades.white}
216
237
  style={{ opacity:update_loading?0.5:1 }}
217
- borderRadius={4}
218
238
  loading={update_loading}
219
- backgroundColor={Colors.brand.electric}
239
+ type='info'
220
240
  onPress={async() => {
221
241
  setLinkStatus({ ...link_status, update_loading: true })
222
242
  const is_available = await ShareApi.isGeneratedLinkAvailable(draft_generated_link);
@@ -237,9 +257,7 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
237
257
  style={{ opacity:link_is_changed && !update_loading?1:0.5 }}
238
258
  disabled={!link_is_changed}
239
259
  loading={update_loading}
240
- title_color={Colors.shades.white}
241
- borderRadius={4}
242
- backgroundColor={Colors.utility.success}
260
+ type='success'
243
261
  onPress={async() => {
244
262
  setLinkStatus({ ...link_status, update_loading: true });
245
263
  const new_link = await ShareApi.updateGeneratedLink(draft_generated_link);
@@ -261,16 +279,17 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
261
279
  <View style={{ ...view_styles.section_body }}>
262
280
  <View style={{ paddingBottom:0 }}>
263
281
  <View style={{ ...view_styles.body_row }}>
264
- <Text size={16} color={Colors.brand.midnight} weight='regular'>Share this link via</Text>
282
+ <Text size={16} color={Colors.text.h1} weight='regular'>Share this link via</Text>
265
283
  </View>
284
+ <View style={{ flexDirection:'row', alignItems:'center' }}>
266
285
  {native_share_allowed ?
267
- <TouchableOpacity style={{ ...view_styles.body_row }} onPress={async() => {
286
+ <Button style={{ flex:1, flexDirection:'row' }} onPress={async() => {
268
287
  const share_event = await ShareApi.share(title, body, link_status.url, generated_link.generated_link_id);
269
288
  if(onShare && share_event){ onShare(share_event) }
270
289
  }}>
271
- <View style={{ flexDirection:'row', alignItems:'center', padding:3, paddingRight:10, borderWidth:1, borderRadius:22, borderColor:Colors.highlights.highlight400Faded, backgroundColor: Colors.shades.white, ...view_styles.float }}>
272
- <View style={{ height:36, width:36, marginRight:10, backgroundColor:Colors.brand.electric, borderRadius:100, justifyContent:'center', alignItems:'center' }}>
273
- <Icons.ShareIcon size={14} color={Colors.shades.white} />
290
+ <View float style={{ flexDirection:'row', alignItems:'center', padding:3, paddingRight:10, borderWidth:1, borderRadius:22 }}>
291
+ <View style={{ height:36, width:36, marginRight:10, borderRadius:100, justifyContent:'center', alignItems:'center' }}>
292
+ <Icons.ShareIcon size={14} color={Colors.text.h1} />
274
293
  </View>
275
294
  <FlatList
276
295
  horizontal
@@ -279,25 +298,31 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
279
298
  renderItem={renderNativeOptions}
280
299
  />
281
300
  </View>
282
- </TouchableOpacity>
301
+ </Button>
302
+ :<></>}
303
+ {Platform.OS != 'web' && Contacts.is_available ?
304
+ <Button onPress={() => handleSelectContact()}>
305
+ <Text>Contacts!</Text>
306
+ </Button>
283
307
  :<></>}
308
+ </View>
284
309
  </View>
285
310
  <View style={{ paddingTop:0, }}>
286
311
  <View style={{ ...view_styles.body_row }}>
287
- <Text selectable size={16} color={Colors.brand.midnight} weight='regular'>Copy link</Text>
312
+ <Text selectable size={16} color={Colors.text.h1} weight='regular'>Copy link</Text>
288
313
  </View>
289
- <View style={{ ...view_styles.body_row, padding:10, borderRadius:4, borderWidth:1, borderColor:Colors.shades.shade600 }}>
314
+ <View type='row' style={{ padding:10 }}>
290
315
  {url ?
291
- <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', backgroundColor:Colors.brand.electric, padding:10, borderRadius:4 }} onPress={() => Clipboard.setString(url)}>
292
- <Icons.LinkIcon size={18} color={Colors.shades.white} />
293
- <Text style={{ marginLeft:4 }} size={12} color={Colors.shades.white} textAlign='left'>Copy</Text>
294
- </TouchableOpacity>
316
+ <Button style={{ flexDirection:'row', alignItems:'center', padding:10, borderRadius:4 }} onPress={() => Clipboard.setStringAsync(url)}>
317
+ <Icons.LinkIcon size={18} color={Colors.text.h1} />
318
+ <Text style={{ marginLeft:4 }} size={12} color={Colors.text.h1} textAlign='left'>Copy</Text>
319
+ </Button>
295
320
  :<></>}
296
- <Text style={{ marginLeft:5, flex:1 }} theme='body'>{url}</Text>
321
+ <Text style={{ marginLeft:5, flex:1 }} theme='description'>{url}</Text>
297
322
  {allow_edit ?
298
- <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', backgroundColor:Colors.brand.electric, padding:10, borderRadius:4 }} onPress={() => setLinkStatus({ ...link_status, editing: true })}>
299
- <Icons.EditIcon size={18} color={Colors.shades.white} />
300
- </TouchableOpacity>
323
+ <Button style={{ flexDirection:'row', alignItems:'center', padding:10, borderRadius:4 }} onPress={() => setLinkStatus({ ...link_status, editing: true })}>
324
+ <Icons.EditIcon size={18} color={Colors.text.h1} />
325
+ </Button>
301
326
  :<></>}
302
327
  </View>
303
328
  </View>
@@ -308,27 +333,25 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
308
333
  <View style={{ ...view_styles.section_body, paddingTop:0 }}>
309
334
  <View style={{ ...view_styles.body_row }}>
310
335
  <View style={{ flex:1 }}>
311
- <Text size={16} color={Colors.brand.midnight} weight='regular'>Embed this in your website</Text>
312
- <Text style={{ marginTop:3 }} theme='body_2'>Copy and past the code snippet below into the 'body' tag</Text>
336
+ <Text size={16} theme='description'>Embed this in your website</Text>
337
+ <Text style={{ marginTop:3 }} theme='light'>Copy and past the code snippet below into the 'body' tag</Text>
313
338
  </View>
314
339
  </View>
315
- <View style={{ backgroundColor:Colors.shades.shade100, padding:10 }}>
316
- <Text selectable size={14} color={Colors.brand.midnight}>{embed.embed_code}</Text>
340
+ <View style={{ padding:10 }}>
341
+ <Text selectable size={14} theme='description'>{embed.embed_code}</Text>
317
342
  <View style={{ ...view_styles.body_row }}>
318
- <TouchableOpacity style={{ flexDirection:'row', alignItems:'center', backgroundColor:Colors.brand.electric, padding:10, borderRadius:4 }}
319
- onPress={() => Clipboard.setString(embed.embed_code)}>
320
- <Icons.LinkIcon size={18} color={Colors.shades.white} />
321
- <Text style={{ marginLeft:4 }} size={12} color={Colors.shades.white} textAlign='left'>Copy</Text>
322
- </TouchableOpacity>
343
+ <Button style={{ flexDirection:'row', alignItems:'center', padding:10, borderRadius:4 }}
344
+ onPress={() => Clipboard.setStringAsync(embed.embed_code)}>
345
+ <Icons.LinkIcon size={18} color={Colors.text.h1} />
346
+ <Text style={{ marginLeft:4 }} size={12} color={Colors.text.h1} textAlign='left'>Copy</Text>
347
+ </Button>
323
348
  <View style={{ flex:1 }} />
324
349
  {embed.widget_element && embed.script_source && embed.div_id && Platform.OS == 'web' ?
325
350
  <Button
326
351
  title={preview_embed ? 'Hide Preview' : 'Show Preview'}
327
- title_color={Colors.shades.white}
328
- borderRadius={4}
329
- padding={10}
352
+ title_color={Colors.text.white}
330
353
  disabled={Platform.OS != 'web' ? true : false}
331
- backgroundColor={preview_embed ? Colors.utility.error : Colors.brand.cyan}
354
+ backgroundColor={preview_embed ? Colors.text.error : Colors.text.action}
332
355
  onPress={() => setPreviewEmbed(!preview_embed)}
333
356
  />
334
357
  :<></>}
@@ -336,7 +359,7 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
336
359
  </View>
337
360
 
338
361
  {preview_embed && embed.widget_element && embed.script_source && embed.div_id ?
339
- <View style={{ borderWidth:1, borderRadius:4, borderColor:Colors.brand.slate }}>
362
+ <View style={{ borderWidth:1, borderRadius:4 }}>
340
363
  <EmbedPreview
341
364
  script_source={embed.script_source}
342
365
  widget_element={embed.widget_element}
@@ -348,25 +371,25 @@ const ShareWidget = ({ generated_link_id, title, body, redirect_url, maxWidth, m
348
371
  </View>
349
372
  :<></>}
350
373
  {active_tab == 'embed' ?
351
- <TouchableOpacity style={{ ...view_styles.section_footer }} onPress={() => setActiveTab('link')}>
374
+ <Button style={{ ...view_styles.section_footer }} onPress={() => setActiveTab('link')}>
352
375
  <View style={{ flex:1, marginRight:10 }}>
353
- <Text theme='header'>Share Link Options</Text>
354
- <Text style={{ marginTop:3 }} theme='body'>Customize the link and share</Text>
376
+ <Text theme='h1'>Share Link Options</Text>
377
+ <Text style={{ marginTop:3 }} theme='description'>Customize the link and share</Text>
355
378
  </View>
356
- <View style={{ height:30, width:30, borderRadius:100, backgroundColor:Colors.shades.white, justifyContent:'center', alignItems:'center' }}>
357
- <Icons.LinkIcon color={Colors.brand.midnight} size={18}/>
379
+ <View style={{ height:30, width:30, borderRadius:100, justifyContent:'center', alignItems:'center' }}>
380
+ <Icons.LinkIcon color={Colors.text.h1} size={18}/>
358
381
  </View>
359
- </TouchableOpacity>
382
+ </Button>
360
383
  : active_tab == 'link' && embed?.embed_code ?
361
- <TouchableOpacity style={{ ...view_styles.section_footer }} onPress={() => setActiveTab('embed')}>
384
+ <Button style={{ ...view_styles.section_footer }} onPress={() => setActiveTab('embed')}>
362
385
  <View style={{ flex:1, marginRight:10 }}>
363
- <Text theme='header'>Available For Embed</Text>
364
- <Text style={{ marginTop:3 }} theme='body'>Copy code snippet and paste into the html of your website</Text>
386
+ <Text theme='h1'>Available For Embed</Text>
387
+ <Text style={{ marginTop:3 }} theme='description'>Copy code snippet and paste into the html of your website</Text>
365
388
  </View>
366
- <View style={{ height:30, width:30, borderRadius:100, backgroundColor:Colors.shades.white, justifyContent:'center', alignItems:'center' }}>
367
- <Icons.EmbedIcon color={Colors.brand.midnight} size={18}/>
389
+ <View style={{ height:30, width:30, borderRadius:100, justifyContent:'center', alignItems:'center' }}>
390
+ <Icons.EmbedIcon color={Colors.text.h1} size={18}/>
368
391
  </View>
369
- </TouchableOpacity>
392
+ </Button>
370
393
  :<></>}
371
394
  </ScrollView>
372
395
  </View>
@@ -0,0 +1,75 @@
1
+ import axios from "axios";
2
+ import { APIOverrides } from "../../../ApiOverrides";
3
+ import type { PublicPlayerProps } from "../../../types";
4
+ import type { Contact } from "expo-contacts";
5
+
6
+ let AUTH_SVC_API = '';
7
+
8
+
9
+ export { ContactsApi, ContactsHelpers }
10
+
11
+ const ContactsApi = {
12
+ setEnvironment: () => {
13
+ const endpoints = APIOverrides.getEndpoints();
14
+ AUTH_SVC_API = endpoints['AUTH_SVC_API'] as string;
15
+ },
16
+ getPlayerByPhone: async(phone:string):Promise<PublicPlayerProps | undefined> => {
17
+ try {
18
+ console.log('getting playerby phone now!!!')
19
+ const resp = await axios.post(`${AUTH_SVC_API}/v1/players/player/search/phone`, { phone });
20
+ console.log(resp.data)
21
+ return resp.data.player
22
+ } catch (e) {
23
+ console.log('WE HIT AN ERROR!!!!!')
24
+ return undefined
25
+ }
26
+ },
27
+ generatePlayerByPhone: async( phone:string, referral_code?:string ):Promise<{ player_id:string } | undefined> => {
28
+ try {
29
+ const resp = await axios.post(`${AUTH_SVC_API}/v1/players/player/phone/authenticate`, { phone, silent:true, referral_code });
30
+ return resp.data.player_id
31
+ } catch (e) {
32
+ return undefined
33
+ }
34
+ },
35
+ getPlayerById: async(player_id:string):Promise<PublicPlayerProps | undefined> => {
36
+ try {
37
+ const resp = await axios.get(`${AUTH_SVC_API}/v1/players/player/${player_id}`);
38
+ return resp.data.player
39
+ } catch (e) {
40
+ return undefined
41
+ }
42
+ }
43
+ }
44
+
45
+
46
+ const ContactsHelpers = {
47
+ formatContactPhoneNumber: (contact:Contact):string | undefined => {
48
+ if(!contact.phoneNumbers){ return undefined }
49
+ let us_phone_numbers = contact.phoneNumbers.filter(p => p.countryCode?.toLowerCase() == 'us');
50
+ if(us_phone_numbers.length == 0){ return undefined }
51
+ //Ok, we have some US numbers!. Lets format them
52
+ let us_phone_number = us_phone_numbers.find(n => n.isPrimary);
53
+ if(!us_phone_number){
54
+ us_phone_number = us_phone_numbers.find(n => n.label?.toLowerCase() == 'mobile');
55
+ }
56
+ if(!us_phone_number){
57
+ us_phone_number = us_phone_numbers[0]
58
+ }
59
+ if(!us_phone_number){ return undefined }
60
+ if(!us_phone_number.digits){ return undefined }
61
+ let split_num = us_phone_number.digits.split('+')
62
+ //Now check the split for the number
63
+ let number = ''
64
+ if(split_num.length == 1){ if(split_num[0]){ number = split_num[0] } }
65
+ if(split_num[1]){ number = split_num[1] }
66
+
67
+ //If it is ten digits - lets add to array
68
+ if(number.length == 11){
69
+ //Drop the first 1
70
+ number = number.substring(1);
71
+ }
72
+ if(number.length != 10){ return undefined }
73
+ return number
74
+ }
75
+ }
@@ -0,0 +1,113 @@
1
+ import { useEffect, useState } from 'react';
2
+ import * as Contacts from 'expo-contacts';
3
+ import type { PublicPlayerProps } from '../../types';
4
+ import { ContactsApi, ContactsHelpers } from './api';
5
+
6
+ type UseContactProps = {
7
+ referral_code?:string
8
+ }
9
+
10
+ const useContacts = ({ referral_code }:UseContactProps) => {
11
+ const [ permission_state, setPermissionState ] = useState<{
12
+ permission_checked:boolean,
13
+ permission?:Contacts.PermissionResponse
14
+ }>({
15
+ permission_checked:false
16
+ });
17
+ const [ contact_loading, setContactLoading ] = useState(false);
18
+ const { permission_checked, permission } = permission_state;
19
+ const [ available_state, setAvailableState ] = useState<{
20
+ is_available_checked:boolean,
21
+ is_available: boolean
22
+ }>({
23
+ is_available_checked: false,
24
+ is_available: false
25
+ });
26
+ const { is_available_checked, is_available } = available_state;
27
+
28
+ useEffect(() => {
29
+ ContactsApi.setEnvironment()
30
+ launch()
31
+ },[]);
32
+
33
+ const launch = async() => {
34
+ if(is_available_checked){ return } //Already checked!
35
+ let avail = await checkAvailable();
36
+ if(!avail){ return }
37
+ await checkPermissions();
38
+ }
39
+
40
+ const checkAvailable = async():Promise<boolean> => {
41
+ try {
42
+ const available = await Contacts.isAvailableAsync();
43
+ setAvailableState({
44
+ is_available_checked: true,
45
+ is_available: available
46
+ })
47
+ return available
48
+ } catch (e) {
49
+ setAvailableState({ is_available_checked:false, is_available: false });
50
+ return false
51
+ }
52
+ }
53
+
54
+ const checkPermissions = async():Promise<Contacts.PermissionResponse | undefined> => {
55
+ try {
56
+ const response = await Contacts.getPermissionsAsync();
57
+ setPermissionState({
58
+ permission_checked:true,
59
+ permission: response
60
+ });
61
+ return response
62
+ } catch (e) {
63
+ setPermissionState({ permission_checked: true });
64
+ return undefined
65
+ }
66
+ }
67
+
68
+ const requestPermissions = async():Promise<Contacts.PermissionResponse | undefined> => {
69
+ try {
70
+ const response = await Contacts.requestPermissionsAsync();
71
+ setPermissionState({
72
+ permission_checked: true,
73
+ permission: response
74
+ });
75
+ return response
76
+ } catch (e) {
77
+ return undefined
78
+ }
79
+ }
80
+
81
+ const getContact = async():Promise<{ player:PublicPlayerProps, number:string } | undefined> => {
82
+ try {
83
+ if(!permission?.granted){ return undefined } //We do not have permission
84
+ setContactLoading(true);
85
+ const contact = await Contacts.presentContactPickerAsync();
86
+ if(!contact){
87
+ setContactLoading(false);
88
+ return undefined
89
+ }
90
+ let number = ContactsHelpers.formatContactPhoneNumber(contact);
91
+
92
+ if(!number){ return undefined }
93
+ //Lets check for the player by phone!
94
+ let player = await ContactsApi.getPlayerByPhone(number);
95
+ if(!player){
96
+ //ok we need to save the number so we can grab a player id for it
97
+ const gen_response = await ContactsApi.generatePlayerByPhone(number, referral_code);
98
+ if(!gen_response){ return undefined } //We failed!
99
+ player = await ContactsApi.getPlayerById(gen_response.player_id);
100
+ if(!player){ return undefined }
101
+ }
102
+ return { player, number }
103
+
104
+ } catch (e) {
105
+ return undefined
106
+ }
107
+ }
108
+
109
+ return { is_available_checked, is_available, permission_checked, permission, contact_loading, checkPermissions, checkAvailable, requestPermissions, getContact }
110
+
111
+ }
112
+
113
+ export { useContacts }
@@ -4,11 +4,13 @@ import PlayerProfile from "./PlayerProfile";
4
4
  import CompanyProfile from './CompanyProfile';
5
5
  import PodcastModule from './PodcastModule';
6
6
  import AudioPlayer from "./AudioPlayer";
7
+ import { useContacts } from "./Contacts/useContacts";
7
8
  export {
8
9
  PlayerCard,
9
10
  PlayerList,
10
11
  PlayerProfile,
11
12
  CompanyProfile,
12
13
  PodcastModule,
13
- AudioPlayer
14
+ AudioPlayer,
15
+ useContacts
14
16
  }
@@ -23,7 +23,7 @@ type SquareCardProps = {
23
23
  const SquareCard = ({ player_id, square, player_square, event, event_status, market_type, draft_player_square, square_offer, draft_square_offer, outbid_player_square, square_state_override, onSquareSelect }:SquareCardProps) => {
24
24
 
25
25
  const cl = market_type == 'FOR_MONEY' ? '$' : 'E';
26
-
26
+ if(square.square_score_x == 0 && square.square_score_y == 0){ console.log('Hey this is updating') }
27
27
  const getStateOfSquare = ():SquareStateProps => {
28
28
  if(square_state_override){ return square_state_override }
29
29
  if(event_status === 'not_started'){
@@ -189,4 +189,45 @@ const SquareCard = ({ player_id, square, player_square, event, event_status, mar
189
189
  )
190
190
  }
191
191
 
192
- export default SquareCard
192
+ export default React.memo(SquareCard, (left, right) => {
193
+ if(JSON.stringify(left) != JSON.stringify(right)){ return false }
194
+ /*
195
+ if(left.square.last_update_datetime != right.square.last_update_datetime){ console.log('sqare'); return false }
196
+ if(left.player_square?.last_update_datetime != right.player_square?.last_update_datetime){ console.log('playersquare'); return false }
197
+ if(left.player_id != right.player_id){ console.log('player_id'); return false }
198
+ if(left.event_status != right.event_status){ console.log('event_status'); return false }
199
+ if(left.market_type != right.market_type){ console.log('market_type'); return false }
200
+ if(left.square_result?.squares_result_id != right.square_result?.squares_result_id){ console.log('result'); return false }
201
+ if(left.draft_player_square?.purchase_price != right.draft_player_square?.purchase_price){
202
+ return false }
203
+ if(left.square_offer?.last_update_datetime != right.square_offer?.last_update_datetime){
204
+
205
+ return false
206
+ }
207
+ if(left.draft_square_offer?.amount != right.draft_square_offer?.amount){
208
+ if(left.square.square_score_x == 0 && left.square.square_score_y == 0){
209
+ console.log('draft offer!')
210
+ }
211
+ return false
212
+ }
213
+ if(left.outbid_player_square?.sq_player_square_id != right.outbid_player_square?.sq_player_square_id){
214
+ if(left.square.square_score_x == 0 && left.square.square_score_y == 0){
215
+ console.log('outbid square!')
216
+ }
217
+ return false
218
+ }
219
+ if(left.square_state_override != right.square_state_override){
220
+ if(left.square.square_score_x == 0 && left.square.square_score_y == 0){
221
+ console.log('square state override!')
222
+ }
223
+ return false
224
+ }
225
+ if(left.ip_result != right.ip_result){
226
+ return false
227
+ }
228
+ */
229
+
230
+ return true
231
+ //if(left.draft_player_square?.purchase_price != right?.draft_player_square?.purchase_price){ return false }
232
+ //return true
233
+ })
@@ -4,7 +4,7 @@ import { FlatList, Image, ScrollView, Platform } from 'react-native';
4
4
  import SquareCard from "./SquareCard";
5
5
  import Countdown from './Countdown';
6
6
  import { SqauresHelpers } from "../api";
7
- import React, { useState } from "react";
7
+ import React, { useEffect, useState } from "react";
8
8
  import moment from "moment-mini";
9
9
  import { Button, Text, View } from "../../Components/Themed";
10
10
  import { useColors } from "../../constants/useColors";
@@ -32,6 +32,12 @@ const SquaresBoard = ({
32
32
  const [ expanded, setExpanded ] = useState(true);
33
33
  const [ times_up, setTimesUp ] = useState(false);
34
34
  const [ refresh_allowed, setRefreshAllowed ] = useState(false);
35
+ const [ square_bid, setSquareBid ] = useState<{square?:SquareProps, action?:'remove'|'add'}>({});
36
+
37
+ useEffect(() => {
38
+ if(!square_bid.square || !square_bid.action){ return }
39
+ handleSquareSelect(square_bid.square, square_bid.action)
40
+ },[square_bid.action, square_bid.square])
35
41
 
36
42
  const comp_status = SqauresHelpers.getCompStatus(event, squares_competition);
37
43
  const unique_score_y = [ ...new Set(squares.map(s => s.square_score_y)) ].sort((a,b) => a - b)
@@ -70,7 +76,7 @@ const SquaresBoard = ({
70
76
  square_offer={square_offer}
71
77
  event={event}
72
78
  event_status={event_status}
73
- onSquareSelect={(square, action) => handleSquareSelect(square, action)}
79
+ onSquareSelect={(square, action) => setSquareBid({square, action})}
74
80
  />
75
81
  </View>
76
82
  )
@@ -88,8 +88,7 @@ const SquaresModule = ({ sq_comp_id, insets, player_id, distinct_id, onRequestAu
88
88
  const my_squares = player_squares.filter(ps => ps.status == 'active' && ps.player_id == player_id);
89
89
  const home_abbr = event?.home?.abbr??squares_competition?.event_backup?.home?.abbr
90
90
  const away_abbr = event?.away?.abbr??squares_competition?.event_backup?.away?.abbr
91
- const joined = SqauresHelpers.amIParticipating(player_squares, player_square_history, player_id);
92
- console.log(joined)
91
+ //const joined = SqauresHelpers.amIParticipating(player_squares, player_square_history, player_id);
93
92
  useEffect(() => {
94
93
  if(!sq_comp_id){ return }
95
94
  if(!loaded){ SquaresApi.setEnvironment(); }
@@ -408,7 +407,6 @@ const SquaresModule = ({ sq_comp_id, insets, player_id, distinct_id, onRequestAu
408
407
  )
409
408
  case 'my_squares':
410
409
  if(my_squares.length == 0){ return <></> }
411
- console.log(squares.length)
412
410
  return (
413
411
  <MySquaresCard
414
412
  player_squares={my_squares}