share modal

This commit is contained in:
2025-10-20 12:08:09 +02:00
parent f49a0346a0
commit 8e281e8f78
4 changed files with 257 additions and 78 deletions
+3 -4
View File
@@ -58,7 +58,6 @@
}, },
"package": "com.omedis.musicland", "package": "com.omedis.musicland",
"permissions": [ "permissions": [
"android.permission.RECORD_AUDIO",
"android.permission.CAMERA", "android.permission.CAMERA",
"android.permission.MODIFY_AUDIO_SETTINGS", "android.permission.MODIFY_AUDIO_SETTINGS",
"android.permission.POST_NOTIFICATIONS" "android.permission.POST_NOTIFICATIONS"
@@ -74,7 +73,7 @@
{ {
"photosPermission": "Nous avons besoin d'accéder à votre galerie pour vous permettre d'ajouter des photos à vos tâches.", "photosPermission": "Nous avons besoin d'accéder à votre galerie pour vous permettre d'ajouter des photos à vos tâches.",
"cameraPermission": "Nous avons besoin d'accéder à votre appareil photo pour vous permettre de prendre des photos de vos tâches.", "cameraPermission": "Nous avons besoin d'accéder à votre appareil photo pour vous permettre de prendre des photos de vos tâches.",
"microphonePermission": "Nous avons besoin d'accéder à votre microphone pour vous permettre d'enregistrer des messages vocaux pour vos tâches." "microphonePermission": false
} }
], ],
[ [
@@ -102,8 +101,8 @@
"expo-camera", "expo-camera",
{ {
"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera", "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone", "microphonePermission": false,
"recordAudioAndroid": true "recordAudioAndroid": false
} }
], ],
"expo-audio", "expo-audio",
+6 -12
View File
@@ -1,23 +1,17 @@
import React, {
useCallback,
useEffect,
useRef,
useState,
useGlobal,
} from "reactn";
import { Image, Pressable, Text, View } from "react-native";
import * as ImagePicker from "expo-image-picker";
import moment from "moment";
import { useActionSheet } from "@expo/react-native-action-sheet"; import { useActionSheet } from "@expo/react-native-action-sheet";
import * as DocumentPicker from "expo-document-picker"; import * as DocumentPicker from "expo-document-picker";
import * as ImagePicker from "expo-image-picker";
import moment from "moment";
import { Image, Pressable, Text, View } from "react-native";
import Compressor from "react-native-compressor"; import Compressor from "react-native-compressor";
import useMinuit from "react-native-minuit/src/hooks/useMinuit"; import useMinuit from "react-native-minuit/src/hooks/useMinuit";
import React, { useCallback, useEffect, useRef, useState } from "reactn";
import { arrayUnion } from "../config/firebase"; import { arrayUnion } from "../config/firebase";
import Style, { gutterConstant, mainBorderRadius } from "../styles/Style";
import { Fonts, Palette } from "../styles";
import { icons } from "../assets"; import { icons } from "../assets";
import { Fonts, Palette } from "../styles";
import Style, { gutterConstant, mainBorderRadius } from "../styles/Style";
import { uploadFileToFirebase } from "../helpers/uploadToFirebase"; import { uploadFileToFirebase } from "../helpers/uploadToFirebase";
import useLayoutType from "../hooks/useLayoutType"; import useLayoutType from "../hooks/useLayoutType";
+247 -61
View File
@@ -222,78 +222,151 @@ const ShareModal = ({ payload }) => {
]; ];
}, [encodedShareText, encodedUrl, payload?.options, shareTitle]); }, [encodedShareText, encodedUrl, payload?.options, shareTitle]);
return ( const mobileContent = (
<AppActionSheet id="Share"> <View style={styles.container}>
<View style={styles.container}> <BlurView
<BlurView style={[styles.card, styles.blurCard]}
style={[styles.card, styles.blurCard]} tint="dark"
tint="dark" intensity={40}
intensity={40} {...blurProps}
{...blurProps} >
> <Text style={styles.heading}>{heading}</Text>
{/* <Pressable <View style={styles.linkRow}>
onPress={closeSheet} <Text numberOfLines={1} style={styles.linkText}>
style={styles.closeButton} {linkLabel}
hitSlop={8} </Text>
> <View style={styles.linkActions}>
<Feather name="x" size={18} color={Palette.white} /> <Pressable
</Pressable> */} hitSlop={8}
<Text style={styles.heading}>{heading}</Text> onPress={handleCopy}
<View style={styles.linkRow}> style={styles.iconButton}
<Text numberOfLines={1} style={styles.linkText}> >
{linkLabel} <Feather
</Text> name={copied ? "check" : "copy"}
<View style={styles.linkActions}> size={16}
<Pressable color={Palette.white}
hitSlop={8} />
onPress={handleCopy} </Pressable>
style={styles.iconButton} <Pressable
> hitSlop={8}
<Feather onPress={onSystemShare}
name={copied ? "check" : "copy"} style={styles.iconButton}
size={16} >
color={Palette.white} <Feather name="share-2" size={16} color={Palette.white} />
/> </Pressable>
</Pressable>
<Pressable
hitSlop={8}
onPress={onSystemShare}
style={styles.iconButton}
>
<Feather name="share-2" size={16} color={Palette.white} />
</Pressable>
</View>
</View> </View>
{copied ? <Text style={styles.copiedText}>Lien copié</Text> : null} </View>
</BlurView> {copied ? <Text style={styles.copiedText}>Lien copié</Text> : null}
</BlurView>
<BlurView intensity={40} tint="dark" style={styles.card} {...blurProps}> <BlurView intensity={40} tint="dark" style={styles.card} {...blurProps}>
<Text style={styles.sectionHeading}>{sectionTitle}</Text> <Text style={styles.sectionHeading}>{sectionTitle}</Text>
<View style={styles.optionsList}> <View style={styles.optionsList}>
{shareOptions.map((option, index) => {
const Icon = option?.Icon ?? Feather;
return (
<BlurView
key={option?.key || index}
style={styles.optionBlur}
intensity={100}
{...blurProps}
>
<Pressable
onPress={() => handleShareOption(option)}
style={styles.optionRow}
>
<View style={styles.optionIconWrapper}>
<Icon size={18} color={Palette.white} />
</View>
<Text style={styles.optionLabel}>{option?.label}</Text>
</Pressable>
</BlurView>
);
})}
</View>
</BlurView>
</View>
);
const webContent = (
<View style={styles.webContainer}>
<View style={styles.webHeader}>
<Text style={styles.webHeading}>{heading}</Text>
<Pressable
onPress={closeSheet}
hitSlop={12}
style={styles.webCloseButton}
>
<Feather name="x" size={16} color={Palette.white} />
</Pressable>
</View>
<Text style={styles.webSubheading}>{shareMessage}</Text>
<View style={styles.webContent}>
<View style={styles.webLinkCard}>
<Text style={styles.webLinkLabel}>{linkLabel}</Text>
<View style={styles.webLinkActions}>
<Pressable
onPress={handleCopy}
style={[
styles.webActionButton,
styles.webPrimaryButton,
copied && styles.webActionButtonActive,
]}
>
<Feather
name={copied ? "check" : "copy"}
size={16}
color={Palette.white}
/>
<Text style={styles.webActionLabel}>
{copied ? "Lien copié" : "Copier le lien"}
</Text>
</Pressable>
<Pressable
onPress={onSystemShare}
style={[styles.webActionButton, styles.webSecondaryButton]}
>
<Feather name="share-2" size={16} color={Palette.white} />
<Text style={styles.webActionLabel}>Partager</Text>
</Pressable>
</View>
</View>
<View style={styles.webOptionsCard}>
<Text style={styles.webSectionHeading}>{sectionTitle}</Text>
<View style={styles.webOptionsGrid}>
{shareOptions.map((option, index) => { {shareOptions.map((option, index) => {
const Icon = option?.Icon ?? Feather; const Icon = option?.Icon ?? Feather;
return ( return (
<BlurView <Pressable
key={option?.key || index} key={option?.key || index}
style={styles.optionBlur} onPress={() => handleShareOption(option)}
intensity={100} style={styles.webOptionRow}
{...blurProps}
> >
<Pressable <View style={styles.webOptionIcon}>
onPress={() => handleShareOption(option)} <Icon size={18} color={Palette.white} />
style={styles.optionRow} </View>
> <Text style={styles.webOptionLabel}>{option?.label}</Text>
<View style={styles.optionIconWrapper}> <Feather
<Icon size={18} color={Palette.white} /> name="chevron-right"
</View> size={16}
<Text style={styles.optionLabel}>{option?.label}</Text> color="rgba(255, 255, 255, 0.6)"
</Pressable> />
</BlurView> </Pressable>
); );
})} })}
</View> </View>
</BlurView> </View>
</View> </View>
</View>
);
return (
<AppActionSheet id="Share" webModal={isWeb} onClose={closeSheet}>
{isWeb ? webContent : mobileContent}
</AppActionSheet> </AppActionSheet>
); );
}; };
@@ -405,6 +478,119 @@ const styles = StyleSheet.create({
color: Palette.white, color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium, fontFamily: FONT_FAMILY.InterMedium,
}, },
webContainer: {
gap: 24,
},
webHeader: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
gap: 12,
},
webHeading: {
flex: 1,
fontSize: 24,
color: Palette.white,
fontFamily: FONT_FAMILY.HelveticaNeueMedium,
},
webCloseButton: {
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: "rgba(255, 255, 255, 0.08)",
alignItems: "center",
justifyContent: "center",
},
webSubheading: {
fontSize: 14,
color: "rgba(255, 255, 255, 0.65)",
fontFamily: FONT_FAMILY.InterMedium,
},
webContent: {
gap: 20,
},
webLinkCard: {
backgroundColor: "rgba(255, 255, 255, 0.06)",
borderRadius: 20,
paddingHorizontal: 20,
paddingVertical: 18,
gap: 16,
},
webLinkLabel: {
color: Palette.white,
fontSize: 15,
fontFamily: FONT_FAMILY.InterMedium,
overflow: "hidden",
},
webLinkActions: {
flexDirection: "row",
alignItems: "center",
gap: 12,
flexWrap: "wrap",
},
webActionButton: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
gap: 10,
paddingHorizontal: 18,
paddingVertical: 12,
borderRadius: 16,
},
webPrimaryButton: {
backgroundColor: Palette.primary,
},
webSecondaryButton: {
backgroundColor: "rgba(255, 255, 255, 0.08)",
},
webActionButtonActive: {
backgroundColor: Palette.darkRadioactivGreen,
},
webActionLabel: {
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium,
},
webOptionsCard: {
backgroundColor: "rgba(255, 255, 255, 0.06)",
borderRadius: 20,
paddingHorizontal: 20,
paddingVertical: 22,
gap: 16,
},
webSectionHeading: {
fontSize: 18,
color: Palette.white,
fontFamily: FONT_FAMILY.HelveticaNeueMedium,
},
webOptionsGrid: {
gap: 12,
},
webOptionRow: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
gap: 12,
backgroundColor: "rgba(255, 255, 255, 0.04)",
borderRadius: 16,
paddingHorizontal: 18,
paddingVertical: 14,
},
webOptionIcon: {
width: 36,
height: 36,
borderRadius: 18,
alignItems: "center",
justifyContent: "center",
backgroundColor: "rgba(255, 255, 255, 0.08)",
marginRight: 4,
},
webOptionLabel: {
flex: 1,
fontSize: 15,
color: Palette.white,
fontFamily: FONT_FAMILY.InterMedium,
},
}); });
export default ShareModal; export default ShareModal;
+1 -1
View File
@@ -382,7 +382,7 @@ const RecordPlayback = ({ route }) => {
try { try {
const stream = await navigator.mediaDevices.getUserMedia({ const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: "user" }, video: { facingMode: "user" },
audio: true, audio: false,
}); });
if (cancelled) { if (cancelled) {
stream.getTracks().forEach((track) => track.stop()); stream.getTracks().forEach((track) => track.stop());