mirror of
https://github.com/balzack/databag.git
synced 2025-04-23 01:55:17 +00:00
decrypting image media
This commit is contained in:
parent
032217cefb
commit
68e4492402
@ -1193,6 +1193,8 @@ PODS:
|
||||
- React-utils (= 0.74.3)
|
||||
- RNCClipboard (1.15.0):
|
||||
- React-Core
|
||||
- RNFS (2.20.0):
|
||||
- React-Core
|
||||
- RNGestureHandler (2.21.2):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
@ -1420,6 +1422,7 @@ DEPENDENCIES:
|
||||
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)"
|
||||
- RNFS (from `../node_modules/react-native-fs`)
|
||||
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
|
||||
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||
@ -1551,6 +1554,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
RNCClipboard:
|
||||
:path: "../node_modules/@react-native-clipboard/clipboard"
|
||||
RNFS:
|
||||
:path: "../node_modules/react-native-fs"
|
||||
RNGestureHandler:
|
||||
:path: "../node_modules/react-native-gesture-handler"
|
||||
RNImageCropPicker:
|
||||
@ -1625,6 +1630,7 @@ SPEC CHECKSUMS:
|
||||
React-utils: a06061b3887c702235d2dac92dacbd93e1ea079e
|
||||
ReactCommon: f00e436b3925a7ae44dfa294b43ef360fbd8ccc4
|
||||
RNCClipboard: 69ab8e51324d5b351f6ba72bbdb72478087a2c64
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNGestureHandler: 6fee3422fd8c81c5ee756fa72e3d1780e9943d9d
|
||||
RNImageCropPicker: a536bb88eade8336e1d18fdeafa77dc893fbc42e
|
||||
RNReanimated: 30ed0985f2b8dc16a76c23362cabe8dd5166b64f
|
||||
|
@ -23,6 +23,7 @@
|
||||
"react": "18.2.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-native": "0.74.3",
|
||||
"react-native-fs": "^2.20.0",
|
||||
"react-native-gesture-handler": "^2.19.0",
|
||||
"react-native-image-crop-picker": "^0.41.2",
|
||||
"react-native-keyboard-aware-scroll-view": "^0.9.5",
|
||||
|
31
app/client/mobile/src/MediaFiles.ts
Normal file
31
app/client/mobile/src/MediaFiles.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { Media } from 'databag-client-sdk'
|
||||
import RNFS from 'react-native-fs';
|
||||
|
||||
export class MediaFiles implements Media {
|
||||
|
||||
public async read(source: any): Promise<{ size: number, getData: (position: number, length: number)=>Promise<string>, close: ()=>Promise<void> }> {
|
||||
const path = source;
|
||||
const stat = await RNFS.stat(path);
|
||||
const size = state.size;
|
||||
const getData = async (position: number, length: number) => {
|
||||
return await RNFS.read(path, length, position, 'base64');
|
||||
}
|
||||
const close = async ()=>{}
|
||||
return { size, getData, close };
|
||||
}
|
||||
|
||||
public async write(): Promise<{ setData: (data: string)=>Promise<void>, getUrl: ()=>Promise<string>, close: ()=>Promise<void> }> {
|
||||
const path = RNFS.DocumentDirectoryPath + `/${Date.now()}.dat`
|
||||
const setData = async (data: string) => {
|
||||
await RNFS.appendFile(path, data, 'base64');
|
||||
}
|
||||
const getUrl = async () => {
|
||||
return `${path}`
|
||||
}
|
||||
const close = async () => {
|
||||
await RNFS.unlink(path);
|
||||
}
|
||||
return { setData, getUrl };
|
||||
}
|
||||
}
|
||||
|
@ -226,8 +226,8 @@ export function useContent() {
|
||||
setTopic: (topic: string) => {
|
||||
updateState({topic});
|
||||
},
|
||||
setFocus: (cardId: string | null, channelId: string) => {
|
||||
app.actions.setFocus(cardId, channelId);
|
||||
setFocus: async (cardId: string | null, channelId: string) => {
|
||||
await app.actions.setFocus(cardId, channelId);
|
||||
},
|
||||
addTopic: async (sealed: boolean, subject: string, contacts: string[]) => {
|
||||
const content = app.state.session.getContent()
|
||||
|
@ -3,7 +3,8 @@ import {DatabagSDK, Session, Focus} from 'databag-client-sdk';
|
||||
import {SessionStore} from '../SessionStore';
|
||||
import {NativeCrypto} from '../NativeCrypto';
|
||||
import {LocalStore} from '../LocalStore';
|
||||
const DATABAG_DB = 'db_v237.db';
|
||||
import { MediaFiles } from '../MediaFiles'
|
||||
const DATABAG_DB = 'db_v239.db';
|
||||
const SETTINGS_DB = 'ls_v001.db';
|
||||
|
||||
const databag = new DatabagSDK(
|
||||
@ -14,6 +15,7 @@ const databag = new DatabagSDK(
|
||||
channelTypes: ['sealed', 'superbasic'],
|
||||
},
|
||||
new NativeCrypto(),
|
||||
new MediaFiles(),
|
||||
);
|
||||
|
||||
export function useAppContext() {
|
||||
@ -117,9 +119,9 @@ export function useAppContext() {
|
||||
const session = await sdk.current.access(node, secure, token, params);
|
||||
updateState({session});
|
||||
},
|
||||
setFocus: (cardId: string | null, channelId: string) => {
|
||||
setFocus: async (cardId: string | null, channelId: string) => {
|
||||
if (state.session) {
|
||||
const focus = state.session.setFocus(cardId, channelId);
|
||||
const focus = await state.session.setFocus(cardId, channelId);
|
||||
updateState({ focus });
|
||||
}
|
||||
},
|
||||
|
@ -21,4 +21,24 @@ export const styles = StyleSheet.create({
|
||||
thumb: {
|
||||
borderRadius: 4,
|
||||
},
|
||||
full: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
close: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
},
|
||||
closeIcon: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
progress: {
|
||||
position: 'absolute',
|
||||
bottom: '10%',
|
||||
width: '50%',
|
||||
},
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Modal, Pressable, Animated, View, Image, useAnimatedValue } from 'react-native'
|
||||
import { Text } from 'react-native-paper'
|
||||
import { SafeAreaView, Modal, Pressable, Animated, View, Image, useAnimatedValue } from 'react-native'
|
||||
import { ProgressBar, IconButton } from 'react-native-paper'
|
||||
import { useImageAsset } from './useImageAsset.hook';
|
||||
import { MediaAsset } from '../../conversation/Conversation';
|
||||
import { styles } from './ImageAsset.styled'
|
||||
@ -21,10 +21,20 @@ export function ImageAsset({ topicId, asset }: { topicId: string, asset: MediaAs
|
||||
}
|
||||
}, [state.loaded]);
|
||||
|
||||
const showImage = () => {
|
||||
setModal(true);
|
||||
actions.loadImage();
|
||||
};
|
||||
|
||||
const hideImage = () => {
|
||||
setModal(false);
|
||||
actions.unloadImage();
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.image}>
|
||||
{ state.thumbUrl && (
|
||||
<Pressable onPress={()=>setModal(true)}>
|
||||
<Pressable onPress={showImage}>
|
||||
<Animated.Image
|
||||
style={[styles.thumb,{opacity},]}
|
||||
resizeMode="contain"
|
||||
@ -35,10 +45,30 @@ export function ImageAsset({ topicId, asset }: { topicId: string, asset: MediaAs
|
||||
/>
|
||||
</Pressable>
|
||||
)}
|
||||
<Modal animationType="fade" transparent={true} supportedOrientations={['portrait', 'landscape']} visible={modal} onRequestClose={() => setModal(false)}>
|
||||
<Modal animationType="fade" transparent={true} supportedOrientations={['portrait', 'landscape']} visible={modal} onRequestClose={hideImage}>
|
||||
<View style={styles.modal}>
|
||||
<BlurView style={styles.blur} blurType="dark" blurAmount={2} reducedTransparencyFallbackColor="dark" />
|
||||
<View style={{ width: 200, height: 200, backgroundColor: 'yellow' }} />
|
||||
<BlurView style={styles.blur} blurType="dark" blurAmount={16} reducedTransparencyFallbackColor="dark" />
|
||||
<Image
|
||||
style={styles.full}
|
||||
resizeMode="contain"
|
||||
source={{ uri: state.thumbUrl }}
|
||||
/>
|
||||
{ state.dataUrl && (
|
||||
<Image
|
||||
style={styles.full}
|
||||
resizeMode="contain"
|
||||
onError={(err)=>console.log(err)}
|
||||
source={{ uri: state.dataUrl }}
|
||||
/>
|
||||
)}
|
||||
{ state.loading && (
|
||||
<View style={styles.progress}>
|
||||
<ProgressBar progress={state.loadPercent / 100} />
|
||||
</View>
|
||||
)}
|
||||
<SafeAreaView style={styles.close}>
|
||||
<IconButton style={styles.closeIcon} icon="close" compact="true" mode="contained" size={28} onPress={hideImage} />
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
</Modal>
|
||||
</View>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -245,8 +245,8 @@ export function useContent() {
|
||||
setTopic: (topic: string) => {
|
||||
updateState({ topic })
|
||||
},
|
||||
setFocus: (cardId: string | null, channelId: string) => {
|
||||
app.actions.setFocus(cardId, channelId)
|
||||
setFocus: async (cardId: string | null, channelId: string) => {
|
||||
await app.actions.setFocus(cardId, channelId)
|
||||
},
|
||||
openTopic: async (cardId: string) => {
|
||||
const content = app.state.session.getContent()
|
||||
|
@ -82,9 +82,9 @@ export function useAppContext() {
|
||||
const session = await sdk.current.access(node, secure, token, params)
|
||||
updateState({ session })
|
||||
},
|
||||
setFocus: (cardId: string | null, channelId: string) => {
|
||||
setFocus: async (cardId: string | null, channelId: string) => {
|
||||
if (state.session) {
|
||||
const focus = state.session.setFocus(cardId, channelId);
|
||||
const focus = async state.session.setFocus(cardId, channelId);
|
||||
updateState({ focus });
|
||||
}
|
||||
},
|
||||
|
@ -9,7 +9,7 @@ export interface Session {
|
||||
getContent(): Content;
|
||||
getRing(): Ring;
|
||||
|
||||
setFocus(cardId: string | null, channelId: string): Focus;
|
||||
setFocus(cardId: string | null, channelId: string): Promise<Focus>;
|
||||
clearFocus(): void;
|
||||
|
||||
addStatusListener(ev: (status: string) => void): void;
|
||||
|
@ -682,7 +682,7 @@ export class ContactModule implements Contact {
|
||||
this.emitter.emit('channel', { cardId, channels });
|
||||
}
|
||||
|
||||
public setFocus(cardId: string, channelId: string): Focus {
|
||||
public async setFocus(cardId: string, channelId: string): Promise<Focus> {
|
||||
if (this.focus) {
|
||||
this.focus.close();
|
||||
}
|
||||
@ -713,7 +713,7 @@ export class ContactModule implements Contact {
|
||||
const guid = cardEntry.item.profile.guid;
|
||||
const token = cardEntry.item.detail.token;
|
||||
const revision = channelEntry.item.summary.revision;
|
||||
const channelKey = channelEntry.item.channelKey;
|
||||
const channelKey = await this.setChannelKey(channelEntry.item);
|
||||
const sealEnabled = Boolean(this.seal);
|
||||
const insecure = /^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|:\d+$|$)){4}$/.test(node);
|
||||
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, cardId, channelId, this.guid, { node, secure: !insecure, token: `${guid}.${token}` }, channelKey, sealEnabled, revision, markRead, flagTopic);
|
||||
@ -741,7 +741,7 @@ export class ContactModule implements Contact {
|
||||
return this.focus;
|
||||
}
|
||||
|
||||
public async clearFocus() {
|
||||
public clearFocus() {
|
||||
if (this.focus) {
|
||||
this.focus.close();
|
||||
this.focus = null;
|
||||
@ -1095,6 +1095,18 @@ export class ContactModule implements Contact {
|
||||
return null;
|
||||
}
|
||||
|
||||
private async setChannelKey(item: ChannelItem) {
|
||||
if (!item.channelKey && item.detail.dataType === 'sealed' && this.seal && this.crypto) {
|
||||
try {
|
||||
const { seals } = JSON.parse(item.detail.data);
|
||||
item.channelKey = await this.getChannelKey(seals);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
return item.channelKey;
|
||||
}
|
||||
|
||||
private async unsealChannelDetail(cardId: string, channelId: string, item: ChannelItem): Promise<boolean> {
|
||||
if (item.unsealedDetail == null && item.detail.dataType === 'sealed' && this.seal && this.crypto) {
|
||||
try {
|
||||
|
@ -941,6 +941,8 @@ export class FocusModule implements Focus {
|
||||
}
|
||||
|
||||
public async setChannelKey(cardId: string | null, channelId: string, channelKey: string | null) {
|
||||
console.log("!!!! SET CHANNEL KEY", cardId, channelId, channelKey);
|
||||
|
||||
if (cardId === this.cardId && channelId === this.channelId) {
|
||||
this.channelKey = channelKey;
|
||||
this.unsealAll = true;
|
||||
|
@ -155,15 +155,15 @@ export class SessionModule implements Session {
|
||||
return this.ring;
|
||||
}
|
||||
|
||||
public setFocus(cardId: string | null, channelId: string): Focus {
|
||||
public async setFocus(cardId: string | null, channelId: string): Promise<Focus> {
|
||||
if (cardId) {
|
||||
return this.contact.setFocus(cardId, channelId);
|
||||
return await this.contact.setFocus(cardId, channelId);
|
||||
} else {
|
||||
return this.stream.setFocus(channelId);
|
||||
return await this.stream.setFocus(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
public async clearFocus() {
|
||||
public clearFocus() {
|
||||
this.contact.clearFocus();
|
||||
this.stream.clearFocus();
|
||||
}
|
||||
|
@ -426,7 +426,7 @@ export class StreamModule {
|
||||
}
|
||||
}
|
||||
|
||||
public setFocus(channelId: string): Focus {
|
||||
public async setFocus(channelId: string): Promise<Focus> {
|
||||
const { node, secure, token, focus } = this;
|
||||
if (focus) {
|
||||
focus.close();
|
||||
@ -446,7 +446,7 @@ export class StreamModule {
|
||||
}
|
||||
|
||||
const entry = this.channelEntries.get(channelId);
|
||||
const channelKey = entry ? entry.item.channelKey : null;
|
||||
const channelKey = entry ? await this.setChannelKey(entry.item) : null;
|
||||
const revision = entry ? entry.item.summary.revision : 0;
|
||||
const sealEnabled = Boolean(this.seal);
|
||||
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, null, channelId, this.guid, { node, secure, token }, channelKey, sealEnabled, revision, markRead, flagTopic);
|
||||
@ -602,6 +602,18 @@ export class StreamModule {
|
||||
return channelEntry;
|
||||
}
|
||||
|
||||
private async setChannelKey(item: ChannelItem) {
|
||||
if (!item.channelKey && item.detail.dataType === 'sealed' && this.seal && this.crypto) {
|
||||
try {
|
||||
const { seals } = JSON.parse(item.detail.data);
|
||||
item.channelKey = await this.getChannelKey(seals);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
return item.channelKey;
|
||||
}
|
||||
|
||||
private async unsealChannelDetail(channelId: string, item: ChannelItem): Promise<boolean> {
|
||||
if (item.unsealedDetail == null && item.detail.dataType === 'sealed' && this.seal && this.crypto) {
|
||||
try {
|
||||
|
Loading…
x
Reference in New Issue
Block a user