added message options

This commit is contained in:
balzack 2025-01-04 08:39:47 -08:00
parent 91d46432a4
commit 5399213646
11 changed files with 126 additions and 28 deletions

View File

@ -54,9 +54,6 @@ export function Conversation({close}: {close: ()=>void}) {
};
useEffect(() => {
console.log(">>>> ", state.assets.length);
if (state.assets.length > 0) {
Animated.timing(scale, {
toValue: 80,
@ -176,13 +173,13 @@ console.log(">>>> ", state.assets.length);
const media = state.assets.map((asset, index) => {
if (asset.type === 'image') {
return <ImageFile key={index} path={asset.path} disabled={false} remove={()=>actions.removeAsset(index)} />
return <ImageFile key={index} path={asset.path} disabled={sending} remove={()=>actions.removeAsset(index)} />
} else if (asset.type === 'video') {
return <VideoFile key={index} path={asset.path} disabled={false} remove={()=>{}} />
return <VideoFile key={index} path={asset.path} disabled={sending} remove={()=>actions.removeAsset(index)} />
} else if (asset.type === 'audio') {
return <AudioFile key={index} path={asset.path} disabled={false} remove={()=>{}} />
return <AudioFile key={index} path={asset.path} disabled={sending} remove={()=>actions.removeAsset(index)} />
} else {
return <BinaryFile key={index} path={asset.path} disabled={false} remove={()=>{}} />
return <BinaryFile key={index} path={asset.path} disabled={sending} remove={()=>actions.removeAsset(index)} />
}
});

View File

@ -10,4 +10,10 @@ export const styles = StyleSheet.create({
height: 72,
width: 72,
},
icon: {
position: 'absolute',
top: 0,
right: 0,
borderRadius: 4,
},
});

View File

@ -1,5 +1,6 @@
import React, { useEffect } from 'react';
import { View, Image } from 'react-native'
import { IconButton } from 'react-native-paper';
import { useAudioFile } from './useAudioFile.hook';
import {styles} from './AudioFile.styled'
import thumb from '../../images/audio.png';
@ -14,6 +15,7 @@ export function AudioFile({ path, disabled, remove }: {path: string, disabled: b
resizeMode="contain"
source={thumb}
/>
<IconButton style={styles.icon} mode="contained" icon="close" disabled={disabled} size={20} onPress={remove} />
</View>
);
}

View File

@ -10,4 +10,10 @@ export const styles = StyleSheet.create({
height: 72,
width: 72,
},
icon: {
position: 'absolute',
top: 0,
right: 0,
borderRadius: 4,
},
});

View File

@ -1,5 +1,6 @@
import React, { useEffect } from 'react';
import { View, Image } from 'react-native'
import { IconButton } from 'react-native-paper'
import { useBinaryFile } from './useBinaryFile.hook';
import {styles} from './BinaryFile.styled'
import thumb from '../../images/binary.png';
@ -14,6 +15,7 @@ export function BinaryFile({ path, disabled, remove }: {path: string, disabled:
resizeMode="contain"
source={thumb}
/>
<IconButton style={styles.icon} mode="contained" icon="close" disabled={disabled} size={20} onPress={remove} />
</View>
);
}

View File

@ -38,7 +38,7 @@ export function ImageFile({ path, disabled, remove }: {path: string, disabled: b
source={{ uri: path }}
onLoad={actions.loaded}
/>
<IconButton style={styles.icon} mode="contained" icon="close" size={20} onPress={remove} />
<IconButton style={styles.icon} mode="contained" icon="close" disabled={disabled} size={20} onPress={remove} />
</Animated.View>
</View>
);

View File

@ -4,10 +4,14 @@ import {Colors} from '../constants/Colors';
export const styles = StyleSheet.create({
video: {
height: 72,
width: 72,
},
asset: {
height: 72,
width: 72,
},
icon: {
position: 'absolute',
top: 0,
right: 0,
borderRadius: 4,
},
});

View File

@ -1,6 +1,6 @@
import React, { useEffect } from 'react';
import { View, Animated, useAnimatedValue } from 'react-native'
import { Text } from 'react-native-paper';
import { IconButton, Text } from 'react-native-paper';
import { useVideoFile } from './useVideoFile.hook';
import {styles} from './VideoFile.styled'
import Video from 'react-native-video'
@ -19,12 +19,11 @@ export function VideoFile({ path, disabled, remove }: {path: string, disabled: b
}
}, [state.loaded]);
console.log("PATH: ", path);
return (
<View style={styles.video}>
<Animated.View style={[styles.thumb,{opacity},]}>
<Animated.View style={[{...styles.thumb, width: 72 * state.ratio},{opacity},]}>
<Video source={{ uri: path }} height={72} width={72 * state.ratio} paused={true} controls={false} resizeMode="contain" onLoad={actions.loaded} />
<IconButton style={styles.icon} mode="contained" icon="close" disabled={disabled} size={20} onPress={remove} />
</Animated.View>
</View>
);

View File

@ -27,6 +27,65 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
const [confirmParams, setConfirmParams] = useState({});
const [confirmShow, setConfirmShow] = useState(false);
const [removing, setRemoving] = useState(false);
const [blocking, setBlocking] = useState(false);
const [reporting, setReporting] = useState(false);
const block = () => {
setConfirmParams({
title: state.strings.blockMessage,
prompt: state.strings.blockMessagePrompt,
cancel: {
label: state.strings.cancel,
action: () => setConfirmShow(false),
},
confirm: {
label: state.strings.block,
action: async () => {
if (!blocking) {
setBlocking(true);
try {
await actions.block(topicId);
setConfirmShow(false);
} catch (err) {
console.log(err);
showError();
}
setBlocking(false);
}
}
},
});
setConfirmShow(true);
};
const report = () => {
setConfirmParams({
title: state.strings.flagMessage,
prompt: state.strings.flagMessagePrompt,
cancel: {
label: state.strings.cancel,
action: () => setConfirmShow(false),
},
confirm: {
label: state.strings.flag,
action: async () => {
if (!reporting) {
setReporting(true);
try {
await actions.flag(topicId);
setConfirmShow(false);
} catch (err) {
console.log(err);
showError();
}
setReporting(false);
}
}
},
});
setConfirmShow(true);
};
const remove = () => {
setConfirmParams({
@ -45,14 +104,7 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
await actions.remove(topicId);
} catch (err) {
console.log(err);
setConfirmParams({
title: state.strings.operationFailed,
prompt: state.strings.tryAgain,
cancel: {
label: state.strings.cancel,
action: () => setConfirmShow(false),
},
});
showError();
}
setRemoving(false);
}
@ -62,6 +114,18 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
setConfirmShow(true);
};
const showError = () => {
setConfirmParams({
title: state.strings.operationFailed,
prompt: state.strings.tryAgain,
cancel: {
label: state.strings.cancel,
action: () => setConfirmShow(false),
},
});
setConfirmShow(true);
}
const media = !assets ? [] : assets.map((asset: MediaAsset, index: number) => {
if (asset.image || asset.encrypted?.type === 'image') {
return <ImageAsset key={index} topicId={topicId} asset={asset as MediaAsset} />
@ -122,15 +186,25 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
)}
{ topicId === selected && (
<Surface style={styles.options}>
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="share-variant-outline" size={24} onPress={() => {}} />
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="square-edit-outline" size={24} onPress={() => {}} />
<IconButton style={styles.option} loading={removing} compact="true" mode="contained" icon="trash-can-outline" size={24} onPress={remove} />
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="eye-remove-outline" size={24} onPress={() => {}} />
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="alert-octagon-outline" size={24} onPress={() => {}} />
{ !locked && (
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="share-variant-outline" size={24} onPress={() => {}} />
)}
{ !locked && profile && (
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="square-edit-outline" size={24} onPress={() => {}} />
)}
{ (host || profile) && (
<IconButton style={styles.option} loading={removing} compact="true" mode="contained" icon="trash-can-outline" size={24} onPress={remove} />
)}
{ !profile && (
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="eye-remove-outline" size={24} onPress={block} />
)}
{ !profile && (
<IconButton style={styles.option} loading={false} compact="true" mode="contained" icon="alert-octagon-outline" size={24} onPress={report} />
)}
</Surface>
)}
<Divider style={styles.border} />
<Confirm show={confirmShow} busy={removing} params={confirmParams} />
<Confirm show={confirmShow} busy={removing || reporting || blocking} params={confirmParams} />
</View>
);
}

View File

@ -31,6 +31,8 @@ export function useAudioAsset(topicId: string, asset: MediaAsset) {
updateState({ loading: true, loadPercent: 0 });
try {
const dataUrl = await focus.getTopicAssetUrl(topicId, assetId, (loadPercent: number)=>{ updateState({ loadPercent }); return !cancelled.current });
console.log("AUDIO", dataUrl);
updateState({ dataUrl });
} catch (err) {
console.log(err);

View File

@ -120,6 +120,7 @@ export class StreamModule {
private async sync(): Promise<void> {
if (!this.syncing) {
console.log("--- SYNCING!");
this.syncing = true;
const { guid, node, secure, token, channelTypes } = this;
while ((this.unsealAll || this.nextRevision) && !this.closing) {
@ -134,6 +135,7 @@ export class StreamModule {
const entry = await this.getChannelEntry(id);
if (detailRevision !== entry.item.detail.revision) {
console.log("--- SYNCING: detail");
const detail = channelDetail ? channelDetail : await getChannelDetail(node, secure, token, id);
entry.item.detail = {
revision: detailRevision,
@ -174,6 +176,7 @@ export class StreamModule {
}
if (topicRevision !== entry.item.summary.revision) {
console.log("--- SYNCING: summary");
const summary = channelSummary ? channelSummary : await getChannelSummary(node, secure, token, id);
entry.item.summary = {
revision: topicRevision,
@ -201,6 +204,7 @@ export class StreamModule {
await this.focus.setRevision(null, id, topicRevision);
}
} else {
console.log("--- SYNCING: delete");
this.channelEntries.delete(id);
if (this.focus) {
this.focus.disconnect(null, id);
@ -227,6 +231,7 @@ export class StreamModule {
}
if (this.unsealAll) {
console.log("--- SYNCING: unseal");
for (const [channelId, entry] of this.channelEntries.entries()) {
try {
const { item } = entry;
@ -251,6 +256,7 @@ export class StreamModule {
await this.store.setMarker(this.guid, 'first_sync_complete', 'stream', '');
}
this.syncing = false;
console.log("--- SYNCING: DONE");
}
}