mirror of
https://github.com/balzack/databag.git
synced 2025-05-05 07:55:15 +00:00
rendering image asset
This commit is contained in:
parent
ce2ffabe9b
commit
219c04e213
@ -44,7 +44,7 @@ export const styles = StyleSheet.create({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
},
|
},
|
||||||
back: {
|
icon: {
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
marginRight: 0,
|
marginRight: 0,
|
||||||
marginLeft: 0,
|
marginLeft: 0,
|
||||||
@ -59,15 +59,14 @@ export const styles = StyleSheet.create({
|
|||||||
header: {
|
header: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
},
|
width: '100%',
|
||||||
iconSpace: {
|
minWidth: 0,
|
||||||
width: '10%',
|
|
||||||
},
|
},
|
||||||
title: {
|
title: {
|
||||||
width: '80%',
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
flexGrow: 1,
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
fontSize: 24,
|
fontSize: 24,
|
||||||
|
@ -19,7 +19,7 @@ export type MediaAsset = {
|
|||||||
export function Conversation({close}: {close: ()=>void}) {
|
export function Conversation({close}: {close: ()=>void}) {
|
||||||
const { state, actions } = useConversation();
|
const { state, actions } = useConversation();
|
||||||
const [ more, setMore ] = useState(false);
|
const [ more, setMore ] = useState(false);
|
||||||
const [ selected, setSelected ] = useState(null);
|
const [ selected, setSelected ] = useState(null as null | string);
|
||||||
const thread = useRef();
|
const thread = useRef();
|
||||||
|
|
||||||
const scrolled = useRef(false);
|
const scrolled = useRef(false);
|
||||||
@ -71,11 +71,7 @@ export function Conversation({close}: {close: ()=>void}) {
|
|||||||
return (
|
return (
|
||||||
<View style={styles.conversation}>
|
<View style={styles.conversation}>
|
||||||
<SafeAreaView style={styles.header}>
|
<SafeAreaView style={styles.header}>
|
||||||
{close && (
|
<IconButton style={styles.icon} compact="true" mode="contained" icon="arrow-left" size={28} onPress={onClose} />
|
||||||
<View style={styles.iconSpace}>
|
|
||||||
<IconButton style={styles.back} compact="true" mode="contained" icon="arrow-left" size={28} onPress={onClose} />
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
<View style={styles.title}>
|
<View style={styles.title}>
|
||||||
{ state.detailSet && state.subject && (
|
{ state.detailSet && state.subject && (
|
||||||
<Text adjustsFontSizeToFit={true} numberOfLines={1} style={styles.label}>{ state.subject }</Text>
|
<Text adjustsFontSizeToFit={true} numberOfLines={1} style={styles.label}>{ state.subject }</Text>
|
||||||
@ -90,7 +86,7 @@ export function Conversation({close}: {close: ()=>void}) {
|
|||||||
<Text adjustsFontSizeToFit={true} numberOfLines={1} style={styles.unknown}>{ `, ${state.strings.unknownContact} (${state.unknownContacts})` }</Text>
|
<Text adjustsFontSizeToFit={true} numberOfLines={1} style={styles.unknown}>{ `, ${state.strings.unknownContact} (${state.unknownContacts})` }</Text>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
{close && <View style={styles.iconSpace} />}
|
<IconButton style={styles.icon} compact="true" mode="contained" icon="cog-outline" size={28} onPress={()=>{}} />
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
<Divider style={styles.border} bold={true} />
|
<Divider style={styles.border} bold={true} />
|
||||||
<View style={styles.thread}>
|
<View style={styles.thread}>
|
||||||
@ -116,7 +112,7 @@ export function Conversation({close}: {close: ()=>void}) {
|
|||||||
card={card}
|
card={card}
|
||||||
profile={profile}
|
profile={profile}
|
||||||
host={host}
|
host={host}
|
||||||
select={(id: string)=>setSelected(id)}
|
select={(id)=>setSelected(id)}
|
||||||
selected={selected}
|
selected={selected}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -79,4 +79,18 @@ export const styles = StyleSheet.create({
|
|||||||
paddingRight: 12,
|
paddingRight: 12,
|
||||||
paddingTop: 4,
|
paddingTop: 4,
|
||||||
},
|
},
|
||||||
|
carousel: {
|
||||||
|
paddingLeft: 8,
|
||||||
|
paddingBottom: 8,
|
||||||
|
},
|
||||||
|
assets: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
gap: 16,
|
||||||
|
},
|
||||||
|
item: {
|
||||||
|
width: 64,
|
||||||
|
height: 64,
|
||||||
|
backgroundColor: 'yellow',
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useRef, useEffect, useState, useCallback } from 'react';
|
import { useRef, useEffect, useState, useCallback } from 'react';
|
||||||
import { avatar } from '../constants/Icons'
|
import { avatar } from '../constants/Icons'
|
||||||
import { Pressable, View, Image } from 'react-native';
|
import { Pressable, ScrollView, View, Image } from 'react-native';
|
||||||
import {Icon, Text, IconButton, Surface, Divider} from 'react-native-paper';
|
import {Icon, Text, IconButton, Surface, Divider} from 'react-native-paper';
|
||||||
import { Topic, Card, Profile } from 'databag-client-sdk';
|
import { Topic, Card, Profile } from 'databag-client-sdk';
|
||||||
import { ImageAsset } from './imageAsset/ImageAsset';
|
import { ImageAsset } from './imageAsset/ImageAsset';
|
||||||
@ -9,8 +9,9 @@ import { VideoAsset } from './videoAsset/VideoAsset';
|
|||||||
import { BinaryAsset } from './binaryAsset/BinaryAsset';
|
import { BinaryAsset } from './binaryAsset/BinaryAsset';
|
||||||
import { useMessage } from './useMessage.hook';
|
import { useMessage } from './useMessage.hook';
|
||||||
import {styles} from './Message.styled';
|
import {styles} from './Message.styled';
|
||||||
|
import { MediaAsset } from '../conversation/Conversatin';
|
||||||
|
|
||||||
export function Message({ topic, card, profile, host, select, selected }: { topic: Topic, card: Card | null, profile: Profile | null, host: boolean, select: (id: string)=>void, selected: string }) {
|
export function Message({ topic, card, profile, host, select, selected }: { topic: Topic, card: Card | null, profile: Profile | null, host: boolean, select: (id: null | string)=>void, selected: string }) {
|
||||||
const { state, actions } = useMessage();
|
const { state, actions } = useMessage();
|
||||||
const { locked, data, created, topicId, status, transform } = topic;
|
const { locked, data, created, topicId, status, transform } = topic;
|
||||||
const { name, handle, node } = profile || card || { name: null, handle: null, node: null }
|
const { name, handle, node } = profile || card || { name: null, handle: null, node: null }
|
||||||
@ -23,13 +24,27 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
|
|||||||
const [editText, setEditText] = useState('');
|
const [editText, setEditText] = useState('');
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
|
|
||||||
|
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} />
|
||||||
|
} else if (asset.audio || asset.encrypted?.type === 'audio') {
|
||||||
|
return <AudioAsset key={index} topicId={topicId} asset={asset as MediaAsset} />
|
||||||
|
} else if (asset.video || asset.encrypted?.type === 'video') {
|
||||||
|
return <VideoAsset key={index} topicId={topicId} asset={asset as MediaAsset} />
|
||||||
|
} else if (asset.binary || asset.encrypted?.type === 'binary') {
|
||||||
|
return <BinaryAsset key={index} topicId={topicId} asset={asset as MediaAsset} />
|
||||||
|
} else {
|
||||||
|
return <View key={index}></View>
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.message}>
|
<View style={styles.message}>
|
||||||
<View style={styles.topic}>
|
<View style={styles.topic}>
|
||||||
<View style={styles.content}>
|
<View style={styles.content}>
|
||||||
<Image style={styles.logo} resizeMode={'contain'} source={{uri: logoUrl}} />
|
<Image style={styles.logo} resizeMode={'contain'} source={{uri: logoUrl}} />
|
||||||
<View style={styles.body}>
|
<View style={styles.body}>
|
||||||
<Pressable style={styles.header} onPress={()=>select(topicId)}>
|
<Pressable style={styles.header} onPress={()=>select(topicId == selected ? null : topicId)}>
|
||||||
<View style={styles.name}>
|
<View style={styles.name}>
|
||||||
{ name && (
|
{ name && (
|
||||||
<Text style={styles.handle}>{ name }</Text>
|
<Text style={styles.handle}>{ name }</Text>
|
||||||
@ -62,6 +77,11 @@ export function Message({ topic, card, profile, host, select, selected }: { topi
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
{ assets?.length > 0 && (
|
||||||
|
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false} style={styles.carousel} contentContainerStyle={styles.assets}>
|
||||||
|
{ media }
|
||||||
|
</ScrollView>
|
||||||
|
)}
|
||||||
{ topicId === selected && (
|
{ topicId === selected && (
|
||||||
<Surface style={styles.options}>
|
<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="share-variant-outline" size={24} onPress={() => {}} />
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Text } from 'react-native'
|
import { Text } from 'react-native-paper'
|
||||||
import { useAudioAsset } from './useAudioAsset.hook';
|
import { useAudioAsset } from './useAudioAsset.hook';
|
||||||
import { MediaAsset } from '../../conversation/Conversation';
|
import { MediaAsset } from '../../conversation/Conversation';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Text } from 'react-native'
|
import { Text } from 'react-native-paper'
|
||||||
import { useBinaryAsset } from './useBinaryAsset.hook';
|
import { useBinaryAsset } from './useBinaryAsset.hook';
|
||||||
import { MediaAsset } from '../../conversation/Conversation';
|
import { MediaAsset } from '../../conversation/Conversation';
|
||||||
|
|
||||||
|
@ -2,4 +2,9 @@ import {StyleSheet} from 'react-native';
|
|||||||
import {Colors} from '../constants/Colors';
|
import {Colors} from '../constants/Colors';
|
||||||
|
|
||||||
export const styles = StyleSheet.create({
|
export const styles = StyleSheet.create({
|
||||||
|
image: {
|
||||||
|
},
|
||||||
|
thumb: {
|
||||||
|
borderRadius: 4,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,37 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import { Text } from 'react-native'
|
import { Animated, View, Image, useAnimatedValue } from 'react-native'
|
||||||
|
import { Text } from 'react-native-paper'
|
||||||
import { useImageAsset } from './useImageAsset.hook';
|
import { useImageAsset } from './useImageAsset.hook';
|
||||||
import { MediaAsset } from '../../conversation/Conversation';
|
import { MediaAsset } from '../../conversation/Conversation';
|
||||||
|
import { styles } from './ImageAsset.styled'
|
||||||
|
|
||||||
export function ImageAsset({ topicId, asset }: { topicId: string, asset: MediaAsset }) {
|
export function ImageAsset({ topicId, asset }: { topicId: string, asset: MediaAsset }) {
|
||||||
const { state, actions } = useImageAsset(topicId, asset);
|
const { state, actions } = useImageAsset(topicId, asset);
|
||||||
|
const fadeAnim = useAnimatedValue(0);
|
||||||
|
|
||||||
return (<Text>IMAGE</Text>);
|
useEffect(() => {
|
||||||
|
if (state.loaded) {
|
||||||
|
Animated.timing(fadeAnim, {
|
||||||
|
toValue: 1,
|
||||||
|
duration: 100,
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}, [state.loaded]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.image}>
|
||||||
|
{ state.thumbUrl && (
|
||||||
|
<Animated.Image
|
||||||
|
style={[styles.thumb,{opacity: fadeAnim,},]}
|
||||||
|
resizeMode="contain"
|
||||||
|
height={92}
|
||||||
|
width={92 * state.ratio}
|
||||||
|
source={{ uri: state.thumbUrl }}
|
||||||
|
onLoad={actions.loaded}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,9 @@ export function useImageAsset(topicId: string, asset: MediaAsset) {
|
|||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
thumbUrl: null,
|
thumbUrl: null,
|
||||||
dataUrl: null,
|
dataUrl: null,
|
||||||
|
ratio: 1,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
loaded: false,
|
||||||
loadPercent: 0,
|
loadPercent: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -36,6 +38,10 @@ export function useImageAsset(topicId: string, asset: MediaAsset) {
|
|||||||
}, [asset]);
|
}, [asset]);
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
loaded: (e) => {
|
||||||
|
const { width, height } = e.nativeEvent.source;
|
||||||
|
updateState({ loaded: true, ratio: width / height });
|
||||||
|
},
|
||||||
unloadImage: () => {
|
unloadImage: () => {
|
||||||
updateState({ dataUrl: null });
|
updateState({ dataUrl: null });
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Text } from 'react-native'
|
import { Text } from 'react-native-paper'
|
||||||
import { useVideoAsset } from './useVideoAsset.hook';
|
import { useVideoAsset } from './useVideoAsset.hook';
|
||||||
import { MediaAsset } from '../../conversation/Conversation';
|
import { MediaAsset } from '../../conversation/Conversation';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user