SuperAdModal.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { Image } from "expo-image";
  2. import { useRouter } from "expo-router";
  3. import React, { useState } from "react";
  4. import {
  5. Dimensions,
  6. Modal,
  7. Pressable,
  8. StyleSheet,
  9. TouchableOpacity,
  10. View,
  11. } from "react-native";
  12. const { width: SCREEN_WIDTH } = Dimensions.get("window");
  13. export interface AdElement {
  14. cover: string;
  15. path?: { schema?: string; url?: string; params?: any };
  16. title?: string;
  17. subtitle?: string;
  18. }
  19. interface Props {
  20. elements: AdElement[];
  21. onClose: () => void;
  22. }
  23. export function SuperAdModal({ elements, onClose }: Props) {
  24. const router = useRouter();
  25. const [index, setIndex] = useState(0);
  26. if (!elements || elements.length === 0) return null;
  27. const current = elements[index];
  28. if (!current) return null;
  29. const handleClose = () => {
  30. if (index < elements.length - 1) {
  31. setIndex(index + 1);
  32. } else {
  33. setIndex(0);
  34. onClose();
  35. }
  36. };
  37. const handleImagePress = () => {
  38. const url = current.path?.url;
  39. if (!url) return;
  40. if (url.startsWith("http")) {
  41. return;
  42. }
  43. router.push(url as any);
  44. };
  45. return (
  46. <Modal
  47. visible
  48. transparent
  49. animationType="fade"
  50. onRequestClose={handleClose}
  51. >
  52. <View style={styles.overlay}>
  53. <Pressable style={StyleSheet.absoluteFill} onPress={handleClose} />
  54. <Pressable onPress={handleImagePress}>
  55. <Image
  56. source={{ uri: current.cover }}
  57. style={styles.image}
  58. contentFit="contain"
  59. />
  60. </Pressable>
  61. <TouchableOpacity
  62. style={styles.closeBtn}
  63. onPress={handleClose}
  64. activeOpacity={0.8}
  65. hitSlop={16}
  66. >
  67. <View style={[styles.closeLine, styles.closeLineA]} />
  68. <View style={[styles.closeLine, styles.closeLineB]} />
  69. </TouchableOpacity>
  70. </View>
  71. </Modal>
  72. );
  73. }
  74. const styles = StyleSheet.create({
  75. overlay: {
  76. flex: 1,
  77. backgroundColor: "rgba(0,0,0,0.6)",
  78. justifyContent: "center",
  79. alignItems: "center",
  80. },
  81. image: {
  82. width: SCREEN_WIDTH,
  83. height: SCREEN_WIDTH * 1.2,
  84. },
  85. closeBtn: {
  86. position: "absolute",
  87. bottom: 80,
  88. alignSelf: "center",
  89. width: 32,
  90. height: 32,
  91. borderRadius: 16,
  92. backgroundColor: "#d8d8d8",
  93. justifyContent: "center",
  94. alignItems: "center",
  95. },
  96. closeLine: {
  97. position: "absolute",
  98. width: 14,
  99. height: 1.5,
  100. backgroundColor: "#000",
  101. },
  102. closeLineA: {
  103. transform: [{ rotate: "45deg" }],
  104. },
  105. closeLineB: {
  106. transform: [{ rotate: "-45deg" }],
  107. },
  108. });