Application Android et IOS pour l'amicale des élèves https://play.google.com/store/apps/details?id=fr.amicaleinsat.application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MascotSpeechBubble.tsx 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import React from 'react';
  2. import { ScrollView, StyleSheet, View } from 'react-native';
  3. import * as Animatable from 'react-native-animatable';
  4. import { Avatar, Button, Card, Paragraph, useTheme } from 'react-native-paper';
  5. import GENERAL_STYLES from '../../constants/Styles';
  6. import SpeechArrow from './SpeechArrow';
  7. export type MascotSpeechBubbleProps = {
  8. icon: string;
  9. title: string;
  10. message: string;
  11. visible?: boolean;
  12. buttons: {
  13. action?: {
  14. message: string;
  15. icon?: string;
  16. color?: string;
  17. onPress?: () => void;
  18. };
  19. cancel?: {
  20. message: string;
  21. icon?: string;
  22. color?: string;
  23. onPress?: () => void;
  24. };
  25. };
  26. };
  27. type Props = MascotSpeechBubbleProps & {
  28. onDismiss: (callback?: () => void) => void;
  29. speechArrowPos: number;
  30. bubbleMaxHeight: number;
  31. };
  32. const styles = StyleSheet.create({
  33. speechBubbleContainer: {
  34. marginLeft: '10%',
  35. marginRight: '10%',
  36. },
  37. speechBubbleCard: {
  38. borderWidth: 4,
  39. borderRadius: 10,
  40. },
  41. speechBubbleIcon: {
  42. backgroundColor: 'transparent',
  43. },
  44. speechBubbleText: {
  45. marginBottom: 10,
  46. },
  47. actionsContainer: {
  48. marginTop: 10,
  49. marginBottom: 10,
  50. },
  51. button: {
  52. ...GENERAL_STYLES.centerHorizontal,
  53. marginBottom: 10,
  54. },
  55. });
  56. export default function MascotSpeechBubble(props: Props) {
  57. const theme = useTheme();
  58. const getButtons = () => {
  59. const { action, cancel } = props.buttons;
  60. return (
  61. <View style={GENERAL_STYLES.center}>
  62. {action ? (
  63. <Button
  64. style={styles.button}
  65. mode="contained"
  66. icon={action.icon}
  67. color={action.color}
  68. onPress={() => {
  69. props.onDismiss(action.onPress);
  70. }}
  71. >
  72. {action.message}
  73. </Button>
  74. ) : null}
  75. {cancel != null ? (
  76. <Button
  77. style={styles.button}
  78. mode="contained"
  79. icon={cancel.icon}
  80. color={cancel.color}
  81. onPress={() => {
  82. props.onDismiss(cancel.onPress);
  83. }}
  84. >
  85. {cancel.message}
  86. </Button>
  87. ) : null}
  88. </View>
  89. );
  90. };
  91. return (
  92. <Animatable.View
  93. style={styles.speechBubbleContainer}
  94. useNativeDriver={true}
  95. animation={props.visible ? 'bounceInLeft' : 'bounceOutLeft'}
  96. duration={props.visible ? 1000 : 300}
  97. >
  98. <SpeechArrow
  99. style={{ marginLeft: props.speechArrowPos }}
  100. size={20}
  101. color={theme.colors.mascotMessageArrow}
  102. />
  103. <Card
  104. style={{
  105. borderColor: theme.colors.mascotMessageArrow,
  106. ...styles.speechBubbleCard,
  107. }}
  108. >
  109. <Card.Title
  110. title={props.title}
  111. left={
  112. props.icon
  113. ? () => (
  114. <Avatar.Icon
  115. size={48}
  116. style={styles.speechBubbleIcon}
  117. color={theme.colors.primary}
  118. icon={props.icon}
  119. />
  120. )
  121. : undefined
  122. }
  123. />
  124. <Card.Content
  125. style={{
  126. maxHeight: props.bubbleMaxHeight,
  127. }}
  128. >
  129. <ScrollView>
  130. <Paragraph style={styles.speechBubbleText}>
  131. {props.message}
  132. </Paragraph>
  133. </ScrollView>
  134. </Card.Content>
  135. <Card.Actions style={styles.actionsContainer}>
  136. {getButtons()}
  137. </Card.Actions>
  138. </Card>
  139. </Animatable.View>
  140. );
  141. }