348 lines
15 KiB
TypeScript
348 lines
15 KiB
TypeScript
// Metro module 16044 (f16045).
|
|
import { useState, useMemo, useCallback, useRef, useEffect, useContext } from "react";
|
|
import { Easing, TouchableOpacity, View, StyleSheet } from "react-native";
|
|
import ChannelStore from "../../../stores/ChannelStore";
|
|
import MessageStore from "../../../stores/MessageStore";
|
|
import RelationshipStore from "../../../stores/RelationshipStore";
|
|
import UserStore from "../../../stores/UserStore";
|
|
import { AnalyticEvents, MessageFlags, Routes } from "../../../Constants";
|
|
import { SquarePIPReferenceDimensions } from "../../voice_panel/native/pip/VoicePanelPIPConstants";
|
|
import { createStyles } from "../../../design/components/Styles/native/createStyles";
|
|
import Module712 from "../../../_bundle/Module712";
|
|
import { useToken } from "../../../design/tokens/native/useToken";
|
|
import { useStateFromStores } from "../../../_bundle/Module589";
|
|
import { computeChannelName } from "../../channel/useChannelName";
|
|
import getDisplayFilename from "../../messages/getDisplayFilename";
|
|
import { Text } from "../../../design/components/Text/native/Text";
|
|
import { Marquee } from "../../../_bundle/AnimatedChild";
|
|
import Module4611 from "../../../_bundle/Module4611";
|
|
import MessageActionCreators from "../../../actions/MessageActionCreators";
|
|
import safeTransitionTo_native from "../../links/safeTransitionTo.native";
|
|
import ReanimatedRexport, { useAnimatedStyle } from "../../reanimated/ReanimatedRexport";
|
|
import * as _timing from "../../../design/animation/reanimated/timing/timing";
|
|
import { intl, t } from "../../../intl/index.native";
|
|
import { BackgroundBlurFill } from "../../../design/components/experimental/native";
|
|
import { ArrowLargeLeftIcon } from "../../../design/components/Icon/native/redesign/generated/ArrowLargeLeftIcon";
|
|
import { XLargeIcon } from "../../../design/components/Icon/native/redesign/generated/XLargeIcon";
|
|
import AnalyticsUtils from "../../../utils/AnalyticsUtils";
|
|
import MediaPlayerManager, { useMediaPlayerManagerStore } from "../../media/native/MediaPlayerManager";
|
|
import { useShallow } from "../../../_bundle/Module3804";
|
|
import MediaPlaybackPanelStateContext from "./MediaPlaybackPanelStateContext";
|
|
import { PauseIcon } from "../../../design/components/Icon/native/redesign/generated/PauseIcon";
|
|
import { PlayIcon } from "../../../design/components/Icon/native/redesign/generated/PlayIcon";
|
|
import { AnimatedCircularProgress } from "../../../_bundle/Module14084";
|
|
let useStyles, __initData, PiPControls;
|
|
const MediaInfo = function MediaInfo(props) {
|
|
let state, setState, state2, setState2;
|
|
const { message, activeMediaPlayerSource: activeMediaPlayerSource3, isVoiceMessage: isVoiceMessage2, isControlVisible: isControlVisible2 } = props;
|
|
state = void 0;
|
|
setState = void 0;
|
|
state2 = void 0;
|
|
setState2 = void 0;
|
|
const styles = useStyles();
|
|
const token = useToken(Module712.colors.BACKGROUND_SURFACE_HIGH);
|
|
const stateFromStores3 = useStateFromStores([ChannelStore, UserStore, RelationshipStore], () => {
|
|
const channel = ChannelStore.getChannel(message?.channel_id);
|
|
return channel != null ? computeChannelName(channel, UserStore, RelationshipStore, true, true) : null;
|
|
}, [message]);
|
|
[state, setState] = useState(0);
|
|
[state2, setState2] = useState(0);
|
|
const memo = useMemo(() => state2 >= state, [state2, state]);
|
|
const r53 = message == null ? void 0 : message.getContentMessage();
|
|
if (message != null && r53 != null && activeMediaPlayerSource3 != null) {
|
|
const r74 = <Text variant="text-md/semibold" lineClamp={1} ellipsizeMode="clip" onLayout={(event) => setState2(event.nativeEvent.layout.width)}>
|
|
{isVoiceMessage2 ? message.author.username : r53.attachments.length > 0 ? activeMediaPlayerSource3.attachmentIndex != null ? getDisplayFilename(r53.attachments[activeMediaPlayerSource3.attachmentIndex]) : "" : ""}
|
|
</Text>;
|
|
return <View accessibilityElementsHidden={isControlVisible2} style={styles.infoContent} onLayout={(event) => setState(event.nativeEvent.layout.width)}>
|
|
<View style={styles.infoContainer}>
|
|
{memo ? <View style={{
|
|
flex: 1
|
|
}}>
|
|
<Marquee spacing={20} speed={0.2}>{r74}</Marquee>
|
|
<Module4611 start={{
|
|
x: 0,
|
|
y: 0
|
|
}} end={{
|
|
x: 1,
|
|
y: 0
|
|
}} locations={[0, 0.1, 0.2, 0.8, 0.9, 1]} colors={[token, token + "CC", token + "00", token + "00", token + "CC", token]} style={styles.infoContainerGradient} />
|
|
</View> : r74}
|
|
{stateFromStores3 != null && <Text variant="text-xs/medium" color="text-subtle" lineClamp={1}>{stateFromStores3}</Text>}
|
|
</View>
|
|
</View>;
|
|
}
|
|
return null;
|
|
};
|
|
PiPControls = function PiPControls(props) {
|
|
const { message: message2, handleClosePip, visible, isVoiceMessage: isVoiceMessage2 } = props;
|
|
const styles = useStyles();
|
|
const callback3 = useCallback(() => {
|
|
if (message2 != null && message2.channel_id != null && message2.id != null) {
|
|
MessageActionCreators.trackJump(message2.channel_id, message2.id, "Media PIP", {});
|
|
const channel = ChannelStore.getChannel(message2.channel_id);
|
|
safeTransitionTo_native(Routes.CHANNEL(channel == null ? void 0 : channel.getGuildId(), message2.channel_id, message2.id), {
|
|
navigationReplace: true,
|
|
openChannel: true
|
|
});
|
|
}
|
|
}, [message2]);
|
|
const c = function c() {
|
|
return {
|
|
opacity: _timing.withTiming(visible ? 1 : 0, {
|
|
duration: 200
|
|
})
|
|
};
|
|
};
|
|
c.__closure = {
|
|
withTiming: _timing.withTiming,
|
|
visible
|
|
};
|
|
c.__workletHash = 3641278982291;
|
|
c.__initData = __initData;
|
|
return <ReanimatedRexport.View style={[styles.pipControls, useAnimatedStyle(c)]}>
|
|
<BackgroundBlurFill blurAmount={0.05} />
|
|
<TouchableOpacity disabled={!visible} style={[styles.pipButton, styles.backButton]} onPress={callback3} accessible accessibilityRole="button" accessibilityLabel={isVoiceMessage2 ? intl.string(t.KTonHP) : intl.string(t["13/7kX"])}>
|
|
<ArrowLargeLeftIcon size="sm" />
|
|
</TouchableOpacity>
|
|
<TouchableOpacity disabled={!visible} style={[styles.pipButton, styles.dismissButton]} onPress={handleClosePip} accessible accessibilityRole="button" accessibilityLabel={isVoiceMessage2 ? intl.string(t["6rhrVG"]) : intl.string(t.WAI6xu)}>
|
|
<XLargeIcon size="sm" />
|
|
</TouchableOpacity>
|
|
</ReanimatedRexport.View>;
|
|
};
|
|
useStyles = createStyles({
|
|
container: {
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
height: SquarePIPReferenceDimensions.height,
|
|
width: SquarePIPReferenceDimensions.width
|
|
},
|
|
pipControls: {
|
|
...StyleSheet.absoluteFillObject,
|
|
zIndex: 5
|
|
},
|
|
pipButton: {
|
|
position: "absolute",
|
|
top: 8,
|
|
padding: 8,
|
|
borderRadius: Module712.radii.round,
|
|
borderWidth: 1,
|
|
borderColor: Module712.colors.CONTROL_SECONDARY_BORDER_DEFAULT,
|
|
tintColor: Module712.colors.CONTROL_SECONDARY_TEXT_DEFAULT,
|
|
backgroundColor: Module712.colors.CONTROL_SECONDARY_BACKGROUND_DEFAULT,
|
|
...Module712.shadows.SHADOW_LOW_HOVER
|
|
},
|
|
dismissButton: {
|
|
right: 8
|
|
},
|
|
backButton: {
|
|
left: 8
|
|
},
|
|
infoContainer: {
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
marginBottom: 8,
|
|
height: 34
|
|
},
|
|
infoContainerGradient: {
|
|
...StyleSheet.absoluteFillObject
|
|
},
|
|
infoContent: {
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
alignSelf: "stretch",
|
|
marginHorizontal: 4
|
|
},
|
|
actionContainer: {
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
width: 48,
|
|
height: 48,
|
|
zIndex: 100
|
|
},
|
|
playPauseButton: {
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
width: 32,
|
|
height: 32,
|
|
zIndex: 100,
|
|
borderRadius: Module712.radii.round,
|
|
backgroundColor: Module712.colors.BACKGROUND_BRAND
|
|
},
|
|
progressBar: {
|
|
...StyleSheet.absoluteFillObject,
|
|
justifyContent: "center",
|
|
alignItems: "center"
|
|
}
|
|
});
|
|
__initData = {
|
|
code: "function MediaPlaybackPipTsx1(){const{withTiming,visible}=this.__closure;return{opacity:withTiming(visible?1:0,{duration:200})};}"
|
|
};
|
|
export default function MediaPlaybackPip() {
|
|
let isPlaying, activeMediaPlayerSource, closePip, stateFromStores, isVoiceMessage, state3, dismissPanel, callback, isControlVisible;
|
|
const styles = useStyles();
|
|
const ref2 = useRef(null);
|
|
const mediaPlayerManagerStore = useMediaPlayerManagerStore(useShallow((a0) => ({
|
|
isPlaying: a0.isPlaying,
|
|
progress: a0.progress,
|
|
activeMediaPlayerSource: a0.activeMediaPlayerSource,
|
|
mediaSourceMessage: a0.mediaSourceMessage,
|
|
closePip: a0.closePip
|
|
})));
|
|
isPlaying = mediaPlayerManagerStore.isPlaying;
|
|
const progress3 = mediaPlayerManagerStore.progress;
|
|
activeMediaPlayerSource = mediaPlayerManagerStore.activeMediaPlayerSource;
|
|
let mediaSourceMessage = mediaPlayerManagerStore.mediaSourceMessage;
|
|
closePip = mediaPlayerManagerStore.closePip;
|
|
const stateFromStores3 = useStateFromStores([MessageStore], () => {
|
|
const channelId = activeMediaPlayerSource?.channelId;
|
|
const messageId = activeMediaPlayerSource?.messageId;
|
|
return channelId == null ? null : messageId == null ? null : MessageStore.getMessage(channelId, messageId);
|
|
}, [activeMediaPlayerSource]);
|
|
if (stateFromStores3 != null) {
|
|
mediaSourceMessage = stateFromStores3;
|
|
}
|
|
stateFromStores = mediaSourceMessage;
|
|
const r5 = stateFromStores == null;
|
|
let r44 = void 0;
|
|
if (!r5) {
|
|
const contentMessage = stateFromStores.getContentMessage();
|
|
r44 = contentMessage == null ? void 0 : contentMessage.hasFlag(MessageFlags.IS_VOICE_MESSAGE);
|
|
}
|
|
let progress2, callback2;
|
|
isVoiceMessage = !!r44;
|
|
const activeMediaPlayerSource2 = activeMediaPlayerSource;
|
|
const progress = progress3;
|
|
const stateFromStores2 = stateFromStores;
|
|
const ref = useRef(null);
|
|
useEffect(() => {
|
|
if (ref.current == null && activeMediaPlayerSource2 != null && progress != null && stateFromStores2 != null) {
|
|
ref.current = {
|
|
initialProgress: progress,
|
|
activeMediaPlayerSource: activeMediaPlayerSource2,
|
|
message: stateFromStores2
|
|
};
|
|
}
|
|
if (ref.current != null && progress != null) {
|
|
ref.current.finalProgress = progress;
|
|
}
|
|
}, [progress, activeMediaPlayerSource, stateFromStores]);
|
|
useEffect(() => {
|
|
let c30944_0 = new Date();
|
|
return () => {
|
|
let current = ref.current;
|
|
if (current == null) {
|
|
current = {};
|
|
}
|
|
const { activeMediaPlayerSource: activeMediaPlayerSource3, message: message3, initialProgress, finalProgress } = current;
|
|
const r19 = activeMediaPlayerSource3?.attachmentIndex != null;
|
|
let r9 = null;
|
|
if (r19) {
|
|
const r20 = message3 == null;
|
|
let r21 = void 0;
|
|
if (!r20) {
|
|
const contentMessage = message3.getContentMessage();
|
|
r21 = contentMessage == null ? void 0 : contentMessage.attachments[activeMediaPlayerSource3.attachmentIndex];
|
|
}
|
|
r9 = r21;
|
|
}
|
|
const messageId = activeMediaPlayerSource3?.messageId;
|
|
const sender_user_id = message3 == null ? void 0 : message3.author.id;
|
|
const content_type = r9?.content_type;
|
|
const r33 = message3 == null;
|
|
let is_voice_message = void 0;
|
|
if (!r33) {
|
|
const contentMessage2 = message3.getContentMessage();
|
|
is_voice_message = contentMessage2 == null ? void 0 : contentMessage2.hasFlag(MessageFlags.IS_VOICE_MESSAGE);
|
|
}
|
|
const duration = finalProgress?.duration;
|
|
const total_duration_secs = duration != null ? duration / 1000 : void 0;
|
|
const time = initialProgress?.time;
|
|
const pip_playback_start_time_secs = time != null ? time / 1000 : void 0;
|
|
const time2 = finalProgress?.time;
|
|
AnalyticsUtils.track(AnalyticEvents.MEDIA_PIP_ENDED, {
|
|
message_id: messageId,
|
|
sender_user_id,
|
|
type: content_type,
|
|
is_voice_message,
|
|
total_duration_secs,
|
|
pip_playback_start_time_secs,
|
|
pip_playback_end_time_secs: time2 != null ? time2 / 1000 : void 0,
|
|
pip_opened_timestamp: c30944_0.toISOString(),
|
|
pip_closed_timestamp: new Date().toISOString()
|
|
});
|
|
};
|
|
}, []);
|
|
let [state, setState3] = useState(false);
|
|
state3 = state;
|
|
useEffect(() => {
|
|
let c28209_0;
|
|
if (state3) {
|
|
c28209_0 = setTimeout(() => {
|
|
if (isPlaying) {
|
|
setState3(false);
|
|
}
|
|
}, 3000);
|
|
}
|
|
return () => clearTimeout(c28209_0);
|
|
}, [state3, setState3, isPlaying]);
|
|
dismissPanel = useContext(MediaPlaybackPanelStateContext).dismissPanel;
|
|
callback = useCallback(() => {
|
|
dismissPanel();
|
|
closePip();
|
|
MediaPlayerManager.pauseCurrentPlayer();
|
|
}, [dismissPanel, closePip]);
|
|
progress2 = progress;
|
|
callback2 = callback;
|
|
useEffect(() => {
|
|
const isCompleted = progress2?.isCompleted;
|
|
let c30945_0;
|
|
if (isCompleted) {
|
|
c30945_0 = setTimeout(() => {
|
|
callback2();
|
|
}, 2000);
|
|
}
|
|
return () => {
|
|
clearTimeout(c30945_0);
|
|
};
|
|
}, [progress?.isCompleted, callback]);
|
|
if (!state3) {
|
|
state = progress?.isCompleted === true;
|
|
}
|
|
isControlVisible = state;
|
|
const callback3 = useCallback(() => {
|
|
if (isPlaying) {
|
|
MediaPlayerManager.pauseCurrentPlayer();
|
|
setState3(true);
|
|
} else {
|
|
MediaPlayerManager.playCurrentPlayer();
|
|
}
|
|
}, [isPlaying]);
|
|
const memo = useMemo(() => isPlaying ? <PauseIcon color={Module712.colors.WHITE} size="md" /> : <PlayIcon color={Module712.colors.WHITE} size="md" />, [isPlaying]);
|
|
const memo2 = useMemo(() => <MediaInfo message={stateFromStores} activeMediaPlayerSource={activeMediaPlayerSource} isVoiceMessage={isVoiceMessage} isControlVisible={isControlVisible} />, [stateFromStores, activeMediaPlayerSource, isVoiceMessage, isControlVisible]);
|
|
const memo3 = useMemo(() => <PiPControls message={stateFromStores} handleClosePip={callback} visible={isControlVisible} isVoiceMessage={isVoiceMessage} />, [stateFromStores, callback, isControlVisible, isVoiceMessage]);
|
|
let accessibilityLabel = isVoiceMessage ? intl.string(t.AlHqHT) : intl.string(t.RscU7I);
|
|
const r17 = isVoiceMessage ? intl.string(t["3XohGn"]) : intl.string(t.ZcgDJX);
|
|
const prefill = progress == null ? 0 : progress.time / progress.duration * 100;
|
|
const r26 = progress == null ? 0 : progress.duration - progress.time;
|
|
const props = {
|
|
style: styles.container,
|
|
activeOpacity: 1,
|
|
onPress: () => {
|
|
if (!(isPlaying ? !isPlaying : isControlVisible)) {
|
|
setState3(!state3);
|
|
}
|
|
},
|
|
accessible: false,
|
|
children: null
|
|
};
|
|
const children = [memo3, memo2, ,];
|
|
const r170 = [<AnimatedCircularProgress style={styles.progressBar} size={48} width={2} prefill={prefill} easing={Easing.out(Easing.linear)} duration={isPlaying ? r26 : 0} fill={isPlaying ? 100 : prefill} rotation={0} lineCap="round" ref={ref2} tintColor={useToken(Module712.colors.CONTROL_PRIMARY_BACKGROUND_DEFAULT)} backgroundColor={useToken(Module712.colors.BACKGROUND_MOD_MUTED)} />, ,];
|
|
if (isPlaying) {
|
|
accessibilityLabel = r17;
|
|
}
|
|
r170[1] = <TouchableOpacity style={styles.playPauseButton} onPress={callback3} accessibilityRole="button" accessibilityLabel={accessibilityLabel}>{memo}</TouchableOpacity>;
|
|
children[2] = <View style={styles.actionContainer}>{r170}</View>;
|
|
props.children = children;
|
|
return <TouchableOpacity {...props} />;
|
|
};
|