From df2769dd457355e34c9da34337a88c239272ce19 Mon Sep 17 00:00:00 2001 From: Supertiger Date: Sat, 21 Feb 2026 19:40:36 +0000 Subject: [PATCH] Add custom button component and enhance video overlay functionality --- package-lock.json | 161 ++++++++++++++++++++++++++++++ package.json | 2 + src/components/ui/Button.tsx | 28 ++++++ src/components/ui/CustomVideo.tsx | 96 +++++++++++++++--- 4 files changed, 274 insertions(+), 13 deletions(-) create mode 100644 src/components/ui/Button.tsx diff --git a/package-lock.json b/package-lock.json index aad83b6..4de065a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "dependencies": { "@bicycle-codes/url-pattern": "^1.0.3", + "@material-symbols-react-native/rounded-300": "^1.0.0", "@notifee/react-native": "^7.8.0", "@react-native-clipboard/clipboard": "^1.14.1", "@react-native-firebase/app": "^20.1.0", @@ -16,6 +17,7 @@ "react": "18.2.0", "react-native": "0.74.3", "react-native-encrypted-storage": "^4.0.3", + "react-native-svg": "15.8", "react-native-track-player": "^4.1.1", "react-native-url-polyfill": "^2.0.0", "react-native-video": "^6.4.2", @@ -3374,6 +3376,12 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@material-symbols-react-native/rounded-300": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material-symbols-react-native/rounded-300/-/rounded-300-1.0.0.tgz", + "integrity": "sha512-Hs3l2p5JchQNLyAZfqMpfwuYwv8HMzMrft9komIjTY84ECm2qcCCUAK5iRsZGxIlDHO9q81UeIQsqm0isqaYUg==", + "license": "Apache-2.0" + }, "node_modules/@microsoft/applicationinsights-web-snippet": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-web-snippet/-/applicationinsights-web-snippet-1.2.0.tgz", @@ -7793,6 +7801,12 @@ "readable-stream": "^3.4.0" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -8525,6 +8539,47 @@ "node": ">= 8" } }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -8831,6 +8886,61 @@ "node": ">=0.10.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -8904,6 +9014,18 @@ "once": "^1.4.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/envinfo": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", @@ -13943,6 +14065,12 @@ "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", "license": "Apache-2.0" }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, "node_modules/mem": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", @@ -15238,6 +15366,18 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nullthrows": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", @@ -17327,6 +17467,21 @@ "async-limiter": "~1.0.0" } }, + "node_modules/react-native-svg": { + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.8.0.tgz", + "integrity": "sha512-KHJzKpgOjwj1qeZzsBjxNdoIgv2zNCO9fVcoq2TEhTRsVV5DGTZ9JzUZwybd7q4giT/H3RdtqC3u44dWdO0Ffw==", + "license": "MIT", + "dependencies": { + "css-select": "^5.1.0", + "css-tree": "^1.1.3", + "warn-once": "0.1.1" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-track-player": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/react-native-track-player/-/react-native-track-player-4.1.1.tgz", @@ -20542,6 +20697,12 @@ "makeerror": "1.0.12" } }, + "node_modules/warn-once": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz", + "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==", + "license": "MIT" + }, "node_modules/wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", diff --git a/package.json b/package.json index dfc74d9..185ffad 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@bicycle-codes/url-pattern": "^1.0.3", + "@material-symbols-react-native/rounded-300": "^1.0.0", "@notifee/react-native": "^7.8.0", "@react-native-clipboard/clipboard": "^1.14.1", "@react-native-firebase/app": "^20.1.0", @@ -19,6 +20,7 @@ "react": "18.2.0", "react-native": "0.74.3", "react-native-encrypted-storage": "^4.0.3", + "react-native-svg": "15.8", "react-native-track-player": "^4.1.1", "react-native-url-polyfill": "^2.0.0", "react-native-video": "^6.4.2", diff --git a/src/components/ui/Button.tsx b/src/components/ui/Button.tsx new file mode 100644 index 0000000..45b1733 --- /dev/null +++ b/src/components/ui/Button.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import {StyleProp, StyleSheet, TouchableOpacity, ViewStyle} from 'react-native'; + +interface ButtonProps { + onPress: () => void; + children: React.ReactNode; + padding?: number; + style?: StyleProp; +} +export const Button = (props: ButtonProps) => { + return ( + + {props.children} + + ); +}; + +const styles = StyleSheet.create({ + button: { + backgroundColor: '#ffffff14', + borderRadius: 5, + + borderWidth: 1, + borderColor: 'rgba(255,255,255,0.1)', + }, +}); diff --git a/src/components/ui/CustomVideo.tsx b/src/components/ui/CustomVideo.tsx index c374fd2..131b0cc 100644 --- a/src/components/ui/CustomVideo.tsx +++ b/src/components/ui/CustomVideo.tsx @@ -1,6 +1,11 @@ import React, {forwardRef, useImperativeHandle, useRef} from 'react'; -import {StyleSheet} from 'react-native'; +import {StyleSheet, Text, View} from 'react-native'; import Video, {VideoRef} from 'react-native-video'; +import {Button} from './Button'; + +import {msKeyboardArrowLeft} from '@material-symbols-react-native/rounded-300'; +import {SvgXml} from 'react-native-svg'; +import Colors from '../Colors'; export interface CustomVideoProps { videoUrl: string; @@ -14,33 +19,98 @@ export interface CustomVideoRef { export const CustomVideo = forwardRef( (props, ref) => { const videoRef = useRef(null); + const [showOverlay, setShowOverlay] = React.useState(true); + const hideOverlayTimeout = useRef(null); + + const stopVideo = () => { + videoRef.current?.setFullScreen(false); + props.onVideoEnd(); + }; useImperativeHandle(ref, () => ({ - stopVideo: () => { - videoRef.current?.setFullScreen(false); - props.onVideoEnd(); - }, + stopVideo, })); + const handleTouchEnd = () => { + setShowOverlay(true); + if (hideOverlayTimeout.current) { + clearTimeout(hideOverlayTimeout.current); + } + hideOverlayTimeout.current = setTimeout(() => { + setShowOverlay(false); + }, 5000); + }; return ( -