@magmamath/students-features 0.6.5-rc.2 → 0.6.5-rc.4

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 (63) hide show
  1. package/dist/commonjs/features/gifCelebrations/GifCelebrations.js +2 -1
  2. package/dist/commonjs/features/gifCelebrations/GifCelebrations.js.map +1 -1
  3. package/dist/commonjs/features/gifCelebrations/components/Gif.js +18 -13
  4. package/dist/commonjs/features/gifCelebrations/components/Gif.js.map +1 -1
  5. package/dist/commonjs/features/gifCelebrations/components/Progress.js +6 -3
  6. package/dist/commonjs/features/gifCelebrations/components/Progress.js.map +1 -1
  7. package/dist/commonjs/features/gifCelebrations/constants.js +12 -1
  8. package/dist/commonjs/features/gifCelebrations/constants.js.map +1 -1
  9. package/dist/commonjs/features/gifCelebrations/helpers.js +21 -27
  10. package/dist/commonjs/features/gifCelebrations/helpers.js.map +1 -1
  11. package/dist/commonjs/features/gifCelebrations/model/GifCelebrations.cache.js +18 -5
  12. package/dist/commonjs/features/gifCelebrations/model/GifCelebrations.cache.js.map +1 -1
  13. package/dist/commonjs/features/gifCelebrations/model/GifCelebrations.model.js +11 -40
  14. package/dist/commonjs/features/gifCelebrations/model/GifCelebrations.model.js.map +1 -1
  15. package/dist/module/features/gifCelebrations/GifCelebrations.js +2 -1
  16. package/dist/module/features/gifCelebrations/GifCelebrations.js.map +1 -1
  17. package/dist/module/features/gifCelebrations/components/Gif.js +18 -13
  18. package/dist/module/features/gifCelebrations/components/Gif.js.map +1 -1
  19. package/dist/module/features/gifCelebrations/components/Progress.js +8 -5
  20. package/dist/module/features/gifCelebrations/components/Progress.js.map +1 -1
  21. package/dist/module/features/gifCelebrations/constants.js +11 -0
  22. package/dist/module/features/gifCelebrations/constants.js.map +1 -1
  23. package/dist/module/features/gifCelebrations/helpers.js +19 -25
  24. package/dist/module/features/gifCelebrations/helpers.js.map +1 -1
  25. package/dist/module/features/gifCelebrations/model/GifCelebrations.cache.js +19 -6
  26. package/dist/module/features/gifCelebrations/model/GifCelebrations.cache.js.map +1 -1
  27. package/dist/module/features/gifCelebrations/model/GifCelebrations.model.js +11 -40
  28. package/dist/module/features/gifCelebrations/model/GifCelebrations.model.js.map +1 -1
  29. package/dist/typescript/commonjs/features/gifCelebrations/components/Gif.d.ts +3 -1
  30. package/dist/typescript/commonjs/features/gifCelebrations/components/Gif.d.ts.map +1 -1
  31. package/dist/typescript/commonjs/features/gifCelebrations/components/Progress.d.ts.map +1 -1
  32. package/dist/typescript/commonjs/features/gifCelebrations/constants.d.ts +9 -0
  33. package/dist/typescript/commonjs/features/gifCelebrations/constants.d.ts.map +1 -1
  34. package/dist/typescript/commonjs/features/gifCelebrations/helpers.d.ts +16 -8
  35. package/dist/typescript/commonjs/features/gifCelebrations/helpers.d.ts.map +1 -1
  36. package/dist/typescript/commonjs/features/gifCelebrations/model/GifCelebrations.cache.d.ts +11 -1
  37. package/dist/typescript/commonjs/features/gifCelebrations/model/GifCelebrations.cache.d.ts.map +1 -1
  38. package/dist/typescript/commonjs/features/gifCelebrations/model/GifCelebrations.model.d.ts +1 -1
  39. package/dist/typescript/commonjs/features/gifCelebrations/model/GifCelebrations.model.d.ts.map +1 -1
  40. package/dist/typescript/commonjs/features/gifCelebrations/types/model.types.d.ts +7 -0
  41. package/dist/typescript/commonjs/features/gifCelebrations/types/model.types.d.ts.map +1 -1
  42. package/dist/typescript/module/features/gifCelebrations/components/Gif.d.ts +3 -1
  43. package/dist/typescript/module/features/gifCelebrations/components/Gif.d.ts.map +1 -1
  44. package/dist/typescript/module/features/gifCelebrations/components/Progress.d.ts.map +1 -1
  45. package/dist/typescript/module/features/gifCelebrations/constants.d.ts +9 -0
  46. package/dist/typescript/module/features/gifCelebrations/constants.d.ts.map +1 -1
  47. package/dist/typescript/module/features/gifCelebrations/helpers.d.ts +16 -8
  48. package/dist/typescript/module/features/gifCelebrations/helpers.d.ts.map +1 -1
  49. package/dist/typescript/module/features/gifCelebrations/model/GifCelebrations.cache.d.ts +11 -1
  50. package/dist/typescript/module/features/gifCelebrations/model/GifCelebrations.cache.d.ts.map +1 -1
  51. package/dist/typescript/module/features/gifCelebrations/model/GifCelebrations.model.d.ts +1 -1
  52. package/dist/typescript/module/features/gifCelebrations/model/GifCelebrations.model.d.ts.map +1 -1
  53. package/dist/typescript/module/features/gifCelebrations/types/model.types.d.ts +7 -0
  54. package/dist/typescript/module/features/gifCelebrations/types/model.types.d.ts.map +1 -1
  55. package/package.json +1 -1
  56. package/src/features/gifCelebrations/GifCelebrations.tsx +1 -1
  57. package/src/features/gifCelebrations/components/Gif.tsx +22 -12
  58. package/src/features/gifCelebrations/components/Progress.tsx +2 -3
  59. package/src/features/gifCelebrations/constants.ts +11 -0
  60. package/src/features/gifCelebrations/helpers.ts +28 -33
  61. package/src/features/gifCelebrations/model/GifCelebrations.cache.ts +33 -14
  62. package/src/features/gifCelebrations/model/GifCelebrations.model.ts +13 -37
  63. package/src/features/gifCelebrations/types/model.types.ts +8 -0
@@ -1 +1 @@
1
- {"version":3,"file":"GifCelebrations.cache.d.ts","sourceRoot":"","sources":["../../../../../../src/features/gifCelebrations/model/GifCelebrations.cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEhE,qBAAa,oBAAoB;IAC/B,SAAgB,UAAU,+CAA4B;IACtD,SAAgB,GAAG,kDAA+B;IAClD,SAAgB,KAAK,yCAAgB;IAErC,SAAgB,KAAK,yDAca;CACnC"}
1
+ {"version":3,"file":"GifCelebrations.cache.d.ts","sourceRoot":"","sources":["../../../../../../src/features/gifCelebrations/model/GifCelebrations.cache.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,aAAa,EACb,oBAAoB,EACpB,wBAAwB,EACzB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEpC,KAAK,yBAAyB,GAAG;IAC/B,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C,wBAAwB,CAAC,EAAE,wBAAwB,CAAA;CACpD,CAAA;AAED,qBAAa,oBAAoB;IAC/B,SAAgB,UAAU,+CAA4B;IACtD,SAAgB,GAAG,kDAA+B;IAClD,SAAgB,KAAK,yCAAgB;IAErC,SAAgB,cAAc,EAAE,oBAAoB,GAAG,OAAO,KAAK,CAAC,QAAQ,CAAA;IAC5E,SAAgB,kBAAkB,CAAC,EAAE,wBAAwB,CAAA;IAE7D,SAAgB,YAAY,qDAQ1B;IAEF,SAAgB,KAAK,yDAGa;gBAEtB,EAAE,oBAAoB,EAAE,wBAAwB,EAAE,EAAE,yBAAyB;CAI1F"}
@@ -15,7 +15,7 @@ export declare class GifCelebrationsModel {
15
15
  readonly $activeGif: import("effector").StoreWritable<GifObject | null>;
16
16
  readonly initialize: import("effector").EventCallable<void>;
17
17
  readonly resetGroupGifs: import("effector").EventCallable<string>;
18
- constructor({ api, totalProblems, resolvedProblems }: GifCelebrationsModelProps);
18
+ constructor({ api, totalProblems, resolvedProblems, customPrefetchMethod, customGetCachePathMethod, }: GifCelebrationsModelProps);
19
19
  private setupEventHandlers;
20
20
  private readonly handleGifSelection;
21
21
  private findGroupForPercentage;
@@ -1 +1 @@
1
- {"version":3,"file":"GifCelebrations.model.d.ts","sourceRoot":"","sources":["../../../../../../src/features/gifCelebrations/model/GifCelebrations.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,EAAE,MAAM,UAAU,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EACL,yBAAyB,EACzB,SAAS,EAGT,uBAAuB,EACxB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAiB9D,qBAAa,oBAAoB;IAC/B,SAAgB,GAAG,EAAE,kBAAkB,CAAA;IACvC,SAAgB,KAAK,EAAE,oBAAoB,CAAA;IAE3C,SAAgB,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC7C,SAAgB,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAEhD,SAAgB,WAAW,yCAAgB;IAC3C,SAAgB,IAAI,yCAAgB;IAEpC,SAAgB,oBAAoB,yCAAgB;IACpD,SAAgB,wBAAwB,mEAEN;IAElC,SAAgB,YAAY,8CAA2B;IACvD,SAAgB,UAAU,qDAEe;IAEzC,SAAgB,UAAU,yCAAgB;IAC1C,SAAgB,cAAc,2CAAwB;gBAE1C,EAAE,GAAG,EAAE,aAAa,EAAE,gBAAgB,EAAE,EAAE,yBAAyB;IAU/E,OAAO,CAAC,kBAAkB;IAmD1B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAyDlC;IAED,OAAO,CAAC,sBAAsB;CAK/B"}
1
+ {"version":3,"file":"GifCelebrations.model.d.ts","sourceRoot":"","sources":["../../../../../../src/features/gifCelebrations/model/GifCelebrations.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkD,KAAK,EAAE,MAAM,UAAU,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EACL,yBAAyB,EACzB,SAAS,EAET,uBAAuB,EACxB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AAU9D,qBAAa,oBAAoB;IAC/B,SAAgB,GAAG,EAAE,kBAAkB,CAAA;IACvC,SAAgB,KAAK,EAAE,oBAAoB,CAAA;IAE3C,SAAgB,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC7C,SAAgB,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAEhD,SAAgB,WAAW,yCAAgB;IAC3C,SAAgB,IAAI,yCAAgB;IAEpC,SAAgB,oBAAoB,yCAAgB;IACpD,SAAgB,wBAAwB,mEAEN;IAElC,SAAgB,YAAY,8CAA2B;IACvD,SAAgB,UAAU,qDAEe;IAEzC,SAAgB,UAAU,yCAAgB;IAC1C,SAAgB,cAAc,2CAAwB;gBAE1C,EACV,GAAG,EACH,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,GACzB,EAAE,yBAAyB;IAU5B,OAAO,CAAC,kBAAkB;IAuC1B,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CA+ClC;IAED,OAAO,CAAC,sBAAsB;CAK/B"}
@@ -1,11 +1,18 @@
1
1
  import { Store } from 'effector';
2
+ export type CustomPrefetchMethod = (gifs: string[] | string) => Promise<unknown>;
3
+ export type CustomGetCachePathMethod = (uri: string) => Promise<string | null>;
2
4
  export type GifCelebrationApiRequests = {
3
5
  getGifs: () => Promise<GifResponse>;
4
6
  };
7
+ export type GifCelebrationCache = {
8
+ prefetchMethod?: CustomPrefetchMethod;
9
+ };
5
10
  export type GifCelebrationsModelProps = {
6
11
  api: GifCelebrationApiRequests;
7
12
  totalProblems: Store<number>;
8
13
  resolvedProblems: Store<number>;
14
+ customPrefetchMethod?: CustomPrefetchMethod;
15
+ customGetCachePathMethod?: CustomGetCachePathMethod;
9
16
  };
10
17
  export type GifsGroup = string[];
11
18
  export type GifsGroups = Record<`group${number}`, GifsGroup>;
@@ -1 +1 @@
1
- {"version":3,"file":"model.types.d.ts","sourceRoot":"","sources":["../../../../../../src/features/gifCelebrations/types/model.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAEhC,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,yBAAyB,CAAA;IAC9B,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC5B,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,EAAE,CAAA;AAChC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,SAAS,CAAC,CAAA;AAE5D,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,QAAQ,MAAM,EAAE,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;AACjE;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,EAAE,EAAE,OAAO,CAAA;CACZ,CAAA;AACD,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AACD,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA"}
1
+ {"version":3,"file":"model.types.d.ts","sourceRoot":"","sources":["../../../../../../src/features/gifCelebrations/types/model.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAEhC,MAAM,MAAM,oBAAoB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;AAChF,MAAM,MAAM,wBAAwB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;AAE9E,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC,CAAA;AACD,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,CAAC,EAAE,oBAAoB,CAAA;CACtC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,yBAAyB,CAAA;IAC9B,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC5B,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC/B,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C,wBAAwB,CAAC,EAAE,wBAAwB,CAAA;CACpD,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,EAAE,CAAA;AAChC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,SAAS,CAAC,CAAA;AAE5D,MAAM,MAAM,SAAS,GAAG;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,QAAQ,MAAM,EAAE,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;AACjE;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,UAAU,CAAA;IAChB,EAAE,EAAE,OAAO,CAAA;CACZ,CAAA;AACD,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AACD,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magmamath/students-features",
3
- "version": "0.6.5-rc.2",
3
+ "version": "0.6.5-rc.4",
4
4
  "description": "Magmamath features library",
5
5
  "source": "src/index.ts",
6
6
  "main": "src/index.ts",
@@ -63,7 +63,7 @@ export const GifCelebrations = ({ model }: GifCelebrationsProps) => {
63
63
  return (
64
64
  <Backdrop progress={progress}>
65
65
  <ContentContainer progress={progress}>
66
- <Gif uri={activeGif.url} />
66
+ <Gif uri={activeGif.url} getCachePathMethod={model.cache.getCachePathMethod} />
67
67
  <Progress progress={progress} completedPercent={completedPercent} />
68
68
  </ContentContainer>
69
69
  </Backdrop>
@@ -1,12 +1,12 @@
1
1
  import { StyleSheet, View, Image } from 'react-native'
2
2
  import React, { useLayoutEffect, useState } from 'react'
3
3
  import { BORDER_RADIUS, COLORS, SPACING } from '@magmamath/react-native-ui'
4
-
5
- const mock =
6
- 'https://media3.giphy.com/media/v1.Y2lkPWZhYjgxNWZhN3lucHRuYjZtMzRiNTZkeXo3NTBrNzIwejcwdXp0Y3g1c2k2ODA2eiZlcD12MV9naWZzX3NlYXJjaCZjdD1n/lCSABZRhMw6pW/giphy.gif'
4
+ import { CustomGetCachePathMethod } from '../types/model.types'
5
+ import { MAX_GIF_SIZE } from '../constants'
7
6
 
8
7
  type GifProps = {
9
8
  uri: string
9
+ getCachePathMethod?: CustomGetCachePathMethod
10
10
  }
11
11
 
12
12
  type Size = {
@@ -14,24 +14,35 @@ type Size = {
14
14
  height: number
15
15
  }
16
16
 
17
- export const Gif = ({ uri }: GifProps) => {
17
+ export const Gif = ({ uri, getCachePathMethod }: GifProps) => {
18
18
  const [size, setSize] = useState<Size | null>(null)
19
- console.log('size: ', size)
19
+ const [pathOrUri, setPathOrUri] = useState<string>('')
20
20
 
21
21
  useLayoutEffect(() => {
22
- Image.getSize(uri, (width, height) => {
23
- setSize({ width: width > 480 ? 480 : width, height: height > 300 ? 300 : height })
24
- })
22
+ const loadImageSize = async () => {
23
+ const path = getCachePathMethod ? (await getCachePathMethod(uri)) || uri : uri
24
+
25
+ Image.getSize(path, (width, height) => {
26
+ setSize({
27
+ width: Math.min(width, MAX_GIF_SIZE.WIDTH),
28
+ height: Math.min(height, MAX_GIF_SIZE.HEIGHT),
29
+ })
30
+
31
+ setPathOrUri(path)
32
+ })
33
+ }
34
+
35
+ loadImageSize()
25
36
  }, [uri])
26
37
 
27
38
  return (
28
39
  <View style={styles.backgroundContainer}>
29
40
  <View style={styles.container}>
30
- {size && (
41
+ {size && pathOrUri && (
31
42
  <Image
32
- alt="Celebration GIF"
43
+ alt="Funny celebration animated image"
33
44
  source={{
34
- uri,
45
+ uri: pathOrUri,
35
46
  }}
36
47
  width={size.width}
37
48
  height={size.height}
@@ -56,6 +67,5 @@ const styles = StyleSheet.create({
56
67
  },
57
68
  image: {
58
69
  borderRadius: BORDER_RADIUS[100],
59
- backgroundColor: 'orange',
60
70
  },
61
71
  })
@@ -1,4 +1,4 @@
1
- import { StyleSheet, View } from 'react-native'
1
+ import { StyleSheet, View, Image } from 'react-native'
2
2
  import React from 'react'
3
3
  import {
4
4
  BORDER_RADIUS,
@@ -8,7 +8,6 @@ import {
8
8
  Typography,
9
9
  } from '@magmamath/react-native-ui'
10
10
  import Animated, { useAnimatedStyle, SharedValue, interpolate } from 'react-native-reanimated'
11
- import { Image } from 'react-native'
12
11
 
13
12
  const MIN_WIDTH_FOR_ONE_DIGIT = 12
14
13
  const MIN_WIDTH_FOR_TWO_DIGITS = 15
@@ -54,7 +53,7 @@ export const Progress = ({ progress, completedPercent }: ProgressProps) => {
54
53
  </Typography>
55
54
  </Animated.View>
56
55
  </View>
57
- {/* <Image source={require('../assets/confetti.webp')} style={styles.confetti} /> */}
56
+ <Image source={require('../assets/confetti.webp')} style={styles.confetti} />
58
57
  </View>
59
58
  </View>
60
59
  )
@@ -11,3 +11,14 @@ export const CONTENT_CONTAINER = {
11
11
 
12
12
  export const ANIMATION_DURATION = 1750
13
13
  export const MIN_PROBLEMS_TO_SHOW_GIF = 6
14
+
15
+ export const MAX_GIF_SIZE = {
16
+ WIDTH: 480,
17
+ HEIGHT: 300,
18
+ }
19
+
20
+ export const GROUPS_PERCENTAGES = {
21
+ group1: [15, 20, 25, 30], // Early celebrations
22
+ group2: [33, 40, 45, 50], // Mid celebrations
23
+ group3: [60, 66, 75, 80], // Party
24
+ }
@@ -1,36 +1,19 @@
1
- import { GifsGroups } from './types/model.types'
2
-
3
- type GifSelectProps = {
4
- gifsGroups: GifsGroups
5
- resolvedProblem: number
6
- totalProblems: number
7
- }
8
-
9
- // Number of problems When we show gif
10
- // <6 Never
11
- // 7-12 50% completion
12
- // 13-18 33%, 66% completion
13
- // 19-24 25%, 50%, 75 completion
14
- // 25-30 20%, 40%, 60%, 80% completion
15
- // .>30 15%, 30%, 45%, 60%, 75% completion
16
-
17
- // We are also going to have different buckets with different gifs. The logic is as follows:
18
- // Group 1: 15%, 20%, 25%, 30% - Early celebrations
19
- // Group 2: 33%, 40%, 45%, 50% - Mid celebrations
20
- // Group 3: 60%, 66%, 75%, 80% - Party
21
-
22
- export const gifSelect = ({ gifsGroups, resolvedProblem, totalProblems }: GifSelectProps) => {
23
- if (totalProblems < 7) return null
24
-
25
- const group = Math.ceil((resolvedProblem / totalProblems) * 100)
26
-
27
- if (group <= 20) return gifsGroups.group1[Math.floor(Math.random() * gifsGroups.group1.length)]
28
- if (group <= 40) return gifsGroups.group2[Math.floor(Math.random() * gifsGroups.group2.length)]
29
- if (group <= 60) return gifsGroups.group3[Math.floor(Math.random() * gifsGroups.group3.length)]
30
-
31
- return null
32
- }
33
-
1
+ import { GifsGroups, GifsStructure } from './types/model.types'
2
+
3
+ /**
4
+ * Number of problems When we show gif
5
+ * <6 Never
6
+ * 7-12 50% completion
7
+ * 13-18 33%, 66% completion
8
+ * 19-24 25%, 50%, 75 completion
9
+ * 25-30 20%, 40%, 60%, 80% completion
10
+ * .>30 15%, 30%, 45%, 60%, 75% completion
11
+ *
12
+ * We are also going to have different buckets with different gifs. The logic is as follows:
13
+ * Group 1: 15%, 20%, 25%, 30% - Early celebrations
14
+ * Group 2: 33%, 40%, 45%, 50% - Mid celebrations
15
+ * Group 3: 60%, 66%, 75%, 80% - Party
16
+ */
34
17
  export const calculatePercentageTable = (totalProblems: number) => {
35
18
  if (totalProblems <= 12) return { 50: Math.ceil(totalProblems * 0.5) }
36
19
 
@@ -66,3 +49,15 @@ export const calculatePercentageTable = (totalProblems: number) => {
66
49
  75: Math.ceil(totalProblems * 0.75),
67
50
  }
68
51
  }
52
+
53
+ export const generateGifsStructure = (gifs: GifsGroups): GifsStructure =>
54
+ Object.fromEntries(
55
+ Object.entries(gifs).map(([key, value]) => [
56
+ key,
57
+ value.map((url) => ({
58
+ url,
59
+ isShown: false,
60
+ group: key as `group${number}`,
61
+ })),
62
+ ]),
63
+ )
@@ -1,24 +1,43 @@
1
- import { createEvent, createStore } from 'effector'
2
- import { GifsGroups, GifsStructure } from '../types/model.types'
1
+ import { createEffect, createEvent, createStore } from 'effector'
2
+ import {
3
+ GifsGroups,
4
+ GifsStructure,
5
+ CustomPrefetchMethod,
6
+ CustomGetCachePathMethod,
7
+ } from '../types/model.types'
8
+ import { generateGifsStructure } from '../helpers'
9
+ import { Image } from 'react-native'
10
+
11
+ type GifCelebrationsCacheProps = {
12
+ customPrefetchMethod?: CustomPrefetchMethod
13
+ customGetCachePathMethod?: CustomGetCachePathMethod
14
+ }
3
15
 
4
16
  export class GifCelebrationsCache {
5
17
  public readonly initialSet = createEvent<GifsGroups>()
6
18
  public readonly set = createEvent<GifsStructure>()
7
19
  public readonly reset = createEvent()
8
20
 
21
+ public readonly prefetchMethod: CustomPrefetchMethod | typeof Image.prefetch
22
+ public readonly getCachePathMethod?: CustomGetCachePathMethod
23
+
24
+ public readonly prefetchGifs = createEffect<GifsGroups, void>((data) => {
25
+ Object.values(data).forEach((group) => {
26
+ group.forEach((gifUrl) => {
27
+ Image.prefetch(gifUrl)
28
+ })
29
+ })
30
+
31
+ this.initialSet(data)
32
+ })
33
+
9
34
  public readonly $gifs = createStore<GifsStructure | null>(null)
10
35
  .reset(this.reset)
11
- .on(this.initialSet, (_, gifs) =>
12
- Object.fromEntries(
13
- Object.entries(gifs).map(([key, value]) => [
14
- key,
15
- value.map((url) => ({
16
- url,
17
- isShown: false,
18
- group: key as `group${number}`,
19
- })),
20
- ]),
21
- ),
22
- )
36
+ .on(this.initialSet, (_, gifs) => generateGifsStructure(gifs))
23
37
  .on(this.set, (_, gifs) => gifs)
38
+
39
+ constructor({ customPrefetchMethod, customGetCachePathMethod }: GifCelebrationsCacheProps) {
40
+ this.prefetchMethod = customPrefetchMethod || Image.prefetch
41
+ this.getCachePathMethod = customGetCachePathMethod
42
+ }
24
43
  }
@@ -3,20 +3,12 @@ import { GifCelebrationsApi } from './GifCelebrationsApi'
3
3
  import {
4
4
  GifCelebrationsModelProps,
5
5
  GifObject,
6
- GifsGroups,
7
6
  GifsStructure,
8
7
  ProblemsPercentageTable,
9
8
  } from '../types/model.types'
10
9
  import { GifCelebrationsCache } from './GifCelebrations.cache'
11
10
  import { calculatePercentageTable } from '../helpers'
12
- import { Image } from 'react-native'
13
- import { MIN_PROBLEMS_TO_SHOW_GIF } from '../constants'
14
-
15
- const GROUPS_PERCENTAGES = {
16
- group1: [15, 20, 25, 30], // Early celebrations
17
- group2: [33, 40, 45, 50], // Mid celebrations
18
- group3: [60, 66, 75, 80], // Party
19
- }
11
+ import { GROUPS_PERCENTAGES, MIN_PROBLEMS_TO_SHOW_GIF } from '../constants'
20
12
 
21
13
  type HandleGifSelectionProps = {
22
14
  gifsGroups: GifsStructure
@@ -47,9 +39,15 @@ export class GifCelebrationsModel {
47
39
  public readonly initialize = createEvent()
48
40
  public readonly resetGroupGifs = createEvent<string>()
49
41
 
50
- constructor({ api, totalProblems, resolvedProblems }: GifCelebrationsModelProps) {
42
+ constructor({
43
+ api,
44
+ totalProblems,
45
+ resolvedProblems,
46
+ customPrefetchMethod,
47
+ customGetCachePathMethod,
48
+ }: GifCelebrationsModelProps) {
51
49
  this.api = new GifCelebrationsApi(api)
52
- this.cache = new GifCelebrationsCache()
50
+ this.cache = new GifCelebrationsCache({ customPrefetchMethod, customGetCachePathMethod })
53
51
 
54
52
  this.$totalProblems = totalProblems
55
53
  this.$resolvedProblems = resolvedProblems
@@ -60,21 +58,9 @@ export class GifCelebrationsModel {
60
58
  private setupEventHandlers() {
61
59
  sample({
62
60
  source: this.api.getGifsFx.doneData,
63
- fn: (response) =>
64
- response.ok
65
- ? response.data
66
- : (() => {
67
- throw new Error('Failed to fetch GIFs')
68
- })(),
69
- target: createEffect((data: GifsGroups) => {
70
- Object.values(data).forEach((group) => {
71
- group.forEach((gifUrl) => {
72
- Image.prefetch(gifUrl)
73
- })
74
- })
75
-
76
- this.cache.initialSet(data)
77
- }),
61
+ filter: (response) => response.ok,
62
+ fn: (response) => response.data,
63
+ target: this.cache.prefetchGifs,
78
64
  })
79
65
 
80
66
  sample({
@@ -110,34 +96,28 @@ export class GifCelebrationsModel {
110
96
 
111
97
  private readonly handleGifSelection = createEffect(
112
98
  ({ gifsGroups, resolvedProblem, problemsPercentageTable }: HandleGifSelectionProps) => {
113
- // Find which percentage milestone this resolved problem represents
114
99
  const percentageMilestone = Object.keys(problemsPercentageTable).find(
115
100
  (key) => problemsPercentageTable[Number(key)] === resolvedProblem,
116
101
  )
102
+
117
103
  if (!percentageMilestone) return null
118
104
 
119
- // Find which group this percentage belongs to
120
105
  const groupName = this.findGroupForPercentage(Number(percentageMilestone)) as
121
106
  | `group${number}`
122
107
  | undefined
123
108
  if (!groupName) return null
124
109
 
125
- // Get available gifs for this group
126
110
  const gifsForGroup = gifsGroups[groupName]
127
111
  if (!gifsForGroup || gifsForGroup.length === 0) return null
128
112
 
129
- // Find the first gif that hasn't been shown yet
130
113
  const unusedGifIndex = gifsForGroup.findIndex((gif) => !gif.isShown)
131
114
 
132
- // If all gifs have been shown, reset the group and start from the beginning
133
115
  if (unusedGifIndex === -1) {
134
- // Reset the group by setting all gifs to isShown: false
135
116
  const updatedGifsGroups = { ...gifsGroups }
136
117
  updatedGifsGroups[groupName] = gifsGroups[groupName].map((gif) => ({
137
118
  ...gif,
138
119
  isShown: false,
139
120
  }))
140
- // Select the first gif from the group
141
121
  const gifObject: GifObject = {
142
122
  ...updatedGifsGroups[groupName][0],
143
123
  isShown: true,
@@ -145,20 +125,16 @@ export class GifCelebrationsModel {
145
125
  updatedGifsGroups[groupName][0].isShown = true
146
126
 
147
127
  this.setActiveGif(gifObject)
148
- // Update the cache with the shown gif
149
128
  this.cache.set(updatedGifsGroups)
150
129
  }
151
130
 
152
- // Otherwise, use the first unused gif
153
131
  const selectedGif = gifsForGroup[unusedGifIndex]
154
132
 
155
- // Create a new gif object with isShown set to true
156
133
  const gifObject: GifObject = {
157
134
  ...selectedGif,
158
135
  isShown: true,
159
136
  }
160
137
 
161
- // Update the cache with the shown gif
162
138
  const updatedGifsGroups = { ...gifsGroups }
163
139
  updatedGifsGroups[groupName][unusedGifIndex].isShown = true
164
140
  this.cache.set(updatedGifsGroups)
@@ -1,13 +1,21 @@
1
1
  import { Store } from 'effector'
2
2
 
3
+ export type CustomPrefetchMethod = (gifs: string[] | string) => Promise<unknown>
4
+ export type CustomGetCachePathMethod = (uri: string) => Promise<string | null>
5
+
3
6
  export type GifCelebrationApiRequests = {
4
7
  getGifs: () => Promise<GifResponse>
5
8
  }
9
+ export type GifCelebrationCache = {
10
+ prefetchMethod?: CustomPrefetchMethod
11
+ }
6
12
 
7
13
  export type GifCelebrationsModelProps = {
8
14
  api: GifCelebrationApiRequests
9
15
  totalProblems: Store<number>
10
16
  resolvedProblems: Store<number>
17
+ customPrefetchMethod?: CustomPrefetchMethod
18
+ customGetCachePathMethod?: CustomGetCachePathMethod
11
19
  }
12
20
 
13
21
  export type GifsGroup = string[]