mirror of
https://github.com/balzack/databag.git
synced 2025-04-27 20:15:17 +00:00
open dm thead from contacts
This commit is contained in:
parent
46afdf212a
commit
32de8dab4f
@ -37,18 +37,18 @@ function Action({ icon, color, strings, select }: { icon: ReactNode; color: stri
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Contacts({ openRegistry, openContact }: { openRegistry: () => void; openContact: (params: ProfileParams) => void }) {
|
export function Contacts({ openRegistry, openContact, textContact, callContact }: { openRegistry: ()=>void; openContact: (params: ProfileParams)=>void, textContact: (cardId: string)=>void, callContact: (cardId: string)=>void }) {
|
||||||
const { state, actions } = useContacts()
|
const { state, actions } = useContacts()
|
||||||
|
|
||||||
const cards = state.filtered.map((card, idx) => {
|
const cards = state.filtered.map((card, idx) => {
|
||||||
const getOptions = () => {
|
const getOptions = () => {
|
||||||
const status = card.offsync ? 'offsync' : card.status
|
const status = card.offsync ? 'offsync' : card.status
|
||||||
if (status === 'connected') {
|
if (status === 'connected') {
|
||||||
const call = <IconPhone size={24} />
|
const phone = <IconPhone size={24} />
|
||||||
const text = <IconMessage2 size={24} />
|
const text = <IconMessage2 size={24} />
|
||||||
return [
|
return [
|
||||||
<Action key="call" icon={call} color={Colors.connected} select={() => actions.call(card.cardId)} strings={state.strings} />,
|
<Action key="phone" icon={phone} color={Colors.connected} select={async () => callContact(card.cardId)} strings={state.strings} />,
|
||||||
<Action key="text" icon={text} color={Colors.connected} select={() => actions.text(card.cardId)} strings={state.strings} />,
|
<Action key="text" icon={text} color={Colors.connected} select={async () => textContact(card.cardId)} strings={state.strings} />,
|
||||||
]
|
]
|
||||||
} else if (status === 'offsync') {
|
} else if (status === 'offsync') {
|
||||||
const resync = <IconRefresh size={24} />
|
const resync = <IconRefresh size={24} />
|
||||||
|
@ -70,12 +70,6 @@ export function useContacts() {
|
|||||||
setFilter: (filter: string) => {
|
setFilter: (filter: string) => {
|
||||||
updateState({ filter })
|
updateState({ filter })
|
||||||
},
|
},
|
||||||
call: async (cardId: string) => {
|
|
||||||
console.log('call', cardId)
|
|
||||||
},
|
|
||||||
text: async (cardId: string) => {
|
|
||||||
console.log('text', cardId)
|
|
||||||
},
|
|
||||||
cancel: async (cardId: string) => {
|
cancel: async (cardId: string) => {
|
||||||
const contact = app.state.session?.getContact()
|
const contact = app.state.session?.getContact()
|
||||||
await contact.disconnectCard(cardId)
|
await contact.disconnectCard(cardId)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { useContent } from './useContent.hook'
|
import { useContent } from './useContent.hook'
|
||||||
import { Modal, Text, Switch, TextInput, Button } from '@mantine/core'
|
import { Modal, Text, Switch, TextInput, Button } from '@mantine/core'
|
||||||
import { IconSearch, IconMessagePlus, IconLabel } from '@tabler/icons-react'
|
import { IconSearch, IconMessagePlus, IconLabel } from '@tabler/icons-react'
|
||||||
@ -7,7 +7,7 @@ import { Channel } from '../channel/Channel'
|
|||||||
import { Card } from '../card/Card'
|
import { Card } from '../card/Card'
|
||||||
import { modals } from '@mantine/modals'
|
import { modals } from '@mantine/modals'
|
||||||
|
|
||||||
export function Content() {
|
export function Content({ textCard }: { textCard: { cardId: null|string }}) {
|
||||||
const { state, actions } = useContent()
|
const { state, actions } = useContent()
|
||||||
const [add, setAdd] = useState(false)
|
const [add, setAdd] = useState(false)
|
||||||
const [adding, setAdding] = useState(false)
|
const [adding, setAdding] = useState(false)
|
||||||
@ -16,6 +16,18 @@ export function Content() {
|
|||||||
const [added, setAdded] = useState([] as string[])
|
const [added, setAdded] = useState([] as string[])
|
||||||
const cards = state.sealSet && sealed ? state.sealable : state.connected
|
const cards = state.sealSet && sealed ? state.sealable : state.connected
|
||||||
|
|
||||||
|
const openTopic = async (cardId: string) => {
|
||||||
|
setAdding(true);
|
||||||
|
try {
|
||||||
|
const id = await actions.openTopic(cardId);
|
||||||
|
actions.setFocus(null, id);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
showError();
|
||||||
|
}
|
||||||
|
setAdding(false);
|
||||||
|
}
|
||||||
|
|
||||||
const addTopic = async () => {
|
const addTopic = async () => {
|
||||||
setAdding(true)
|
setAdding(true)
|
||||||
try {
|
try {
|
||||||
@ -87,6 +99,12 @@ export function Content() {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (textCard.cardId) {
|
||||||
|
openTopic(textCard.cardId);
|
||||||
|
}
|
||||||
|
}, [textCard]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.content}>
|
<div className={classes.content}>
|
||||||
<div className={classes.header}>
|
<div className={classes.header}>
|
||||||
|
@ -242,6 +242,26 @@ export function useContent() {
|
|||||||
setFocus: (cardId: string | null, channelId: string) => {
|
setFocus: (cardId: string | null, channelId: string) => {
|
||||||
app.actions.setFocus(cardId, channelId)
|
app.actions.setFocus(cardId, channelId)
|
||||||
},
|
},
|
||||||
|
openTopic: async (cardId: string) => {
|
||||||
|
const content = app.state.session.getContent()
|
||||||
|
const card = state.cards.find(card => card.cardId === cardId)
|
||||||
|
if (!card) {
|
||||||
|
throw new Error('contact not found');
|
||||||
|
}
|
||||||
|
const sealable = card.sealable && state.sealSet;
|
||||||
|
const thread = state.sorted.find(channel => {
|
||||||
|
const { sealed, cardId, members} = channel;
|
||||||
|
if (sealed === sealable && cardId == null && members.length === 1 && members[0].guid === card.guid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
if (thread) {
|
||||||
|
return thread.channelId;
|
||||||
|
}
|
||||||
|
const topic = await content.addChannel(sealable, sealable ? 'sealed' : 'superbasic', {}, [cardId]);
|
||||||
|
return topic.id;
|
||||||
|
},
|
||||||
addTopic: async (sealed: boolean, subject: string, contacts: string[]) => {
|
addTopic: async (sealed: boolean, subject: string, contacts: string[]) => {
|
||||||
const content = app.state.session.getContent()
|
const content = app.state.session.getContent()
|
||||||
if (sealed) {
|
if (sealed) {
|
||||||
|
@ -216,20 +216,28 @@ export function Conversation() {
|
|||||||
<div className={classes.files}>
|
<div className={classes.files}>
|
||||||
{ media }
|
{ media }
|
||||||
</div>
|
</div>
|
||||||
<Textarea className={classes.message} placeholder={state.strings.newMessage} styles={{ input: {color: state.textColorSet ? state.textColor : undefined, fontSize: state.textSizeSet ? state.textSize : undefined }}} value={state.message} onChange={(event) => actions.setMessage(event.currentTarget.value)} disabled={!state.detail || state.detail.locked || sending} onKeyDown={(e) => { console.log(e); keyDown(e.key, e.shiftKey)}} />
|
<Textarea className={classes.message} placeholder={state.strings.newMessage} styles={{ input: {color: state.textColorSet ? state.textColor : undefined, fontSize: state.textSizeSet ? state.textSize : undefined }}} value={state.message} onChange={(event) => actions.setMessage(event.currentTarget.value)} disabled={!state.detail || state.detail.locked || sending} onKeyDown={(e) => { keyDown(e.key, e.shiftKey)}} />
|
||||||
<div className={classes.controls}>
|
<div className={classes.controls}>
|
||||||
|
{ state.detail?.enableImage && (
|
||||||
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachImage.current.click()}>
|
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachImage.current.click()}>
|
||||||
<IconCamera />
|
<IconCamera />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
)}
|
||||||
|
{ state.detail?.enableVideo && (
|
||||||
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachVideo.current.click()}>
|
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachVideo.current.click()}>
|
||||||
<IconVideo />
|
<IconVideo />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
)}
|
||||||
|
{ state.detail?.enableAudio && (
|
||||||
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachAudio.current.click()}>
|
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachAudio.current.click()}>
|
||||||
<IconDisc />
|
<IconDisc />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
)}
|
||||||
|
{ state.detail?.enableBinary && (
|
||||||
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachBinary.current.click()}>
|
<ActionIcon className={classes.attach} variant="light" disabled={!state.detail || state.detail.locked || sending} onClick={() => attachBinary.current.click()}>
|
||||||
<IconFile />
|
<IconFile />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
)}
|
||||||
<Divider size="sm" orientation="vertical" />
|
<Divider size="sm" orientation="vertical" />
|
||||||
<Menu shadow="md" position="top">
|
<Menu shadow="md" position="top">
|
||||||
<Menu.Target>
|
<Menu.Target>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState, useContext } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Drawer } from '@mantine/core'
|
import { Drawer } from '@mantine/core'
|
||||||
import { DisplayContext } from '../context/DisplayContext'
|
import { DisplayContext } from '../context/DisplayContext'
|
||||||
import { ContextType } from '../context/ContextType'
|
import { ContextType } from '../context/ContextType'
|
||||||
@ -23,6 +23,18 @@ export function Session() {
|
|||||||
const [contacts, { open: openContacts, close: closeContacts }] = useDisclosure(false)
|
const [contacts, { open: openContacts, close: closeContacts }] = useDisclosure(false)
|
||||||
const [registry, { open: openRegistry, close: closeRegistry }] = useDisclosure(false)
|
const [registry, { open: openRegistry, close: closeRegistry }] = useDisclosure(false)
|
||||||
const [profile, { open: openProfile, close: closeProfile }] = useDisclosure(false)
|
const [profile, { open: openProfile, close: closeProfile }] = useDisclosure(false)
|
||||||
|
const [textCard, setTextCard] = useState({ cardId: null} as {cardId: null|string});
|
||||||
|
|
||||||
|
const textContact = (cardId: string) => {
|
||||||
|
console.log("MESSAGE: ", cardId);
|
||||||
|
setTextCard({ cardId });
|
||||||
|
closeContacts();
|
||||||
|
setTab('content');
|
||||||
|
}
|
||||||
|
|
||||||
|
const callContact = (cardId: string) => {
|
||||||
|
console.log("CALL: ", cardId);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.session}>
|
<div className={classes.session}>
|
||||||
@ -30,7 +42,7 @@ export function Session() {
|
|||||||
<>
|
<>
|
||||||
<div className={tab === 'content' ? classes.show : classes.hide}>
|
<div className={tab === 'content' ? classes.show : classes.hide}>
|
||||||
<div className={classes.screen}>
|
<div className={classes.screen}>
|
||||||
<Content />
|
<Content textCard={textCard} />
|
||||||
</div>
|
</div>
|
||||||
{state.focus && (
|
{state.focus && (
|
||||||
<div className={classes.screen}>
|
<div className={classes.screen}>
|
||||||
@ -46,6 +58,8 @@ export function Session() {
|
|||||||
<div className={tab === 'contacts' ? classes.show : classes.hide}>
|
<div className={tab === 'contacts' ? classes.show : classes.hide}>
|
||||||
<div className={classes.screen}>
|
<div className={classes.screen}>
|
||||||
<Contacts
|
<Contacts
|
||||||
|
callContact={callContact}
|
||||||
|
textContact={textContact}
|
||||||
openRegistry={openRegistry}
|
openRegistry={openRegistry}
|
||||||
openContact={(params) => {
|
openContact={(params) => {
|
||||||
setProfileParams(params)
|
setProfileParams(params)
|
||||||
@ -111,13 +125,15 @@ export function Session() {
|
|||||||
<div className={classes.left}>
|
<div className={classes.left}>
|
||||||
<Identity settings={openSettings} contacts={openContacts} />
|
<Identity settings={openSettings} contacts={openContacts} />
|
||||||
<div className={classes.content}>
|
<div className={classes.content}>
|
||||||
<Content />
|
<Content textCard={textCard} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.right}>{state.focus && <Conversation />}</div>
|
<div className={classes.right}>{state.focus && <Conversation />}</div>
|
||||||
<Drawer opened={contacts} onClose={closeContacts} withCloseButton={false} size="md" padding="0" position="right">
|
<Drawer opened={contacts} onClose={closeContacts} withCloseButton={false} size="md" padding="0" position="right">
|
||||||
<div style={{ height: '100vh' }}>
|
<div style={{ height: '100vh' }}>
|
||||||
<Contacts
|
<Contacts
|
||||||
|
callContact={callContact}
|
||||||
|
textContact={textContact}
|
||||||
openRegistry={openRegistry}
|
openRegistry={openRegistry}
|
||||||
openContact={(params) => {
|
openContact={(params) => {
|
||||||
setProfileParams(params)
|
setProfileParams(params)
|
||||||
|
13378
app/client/web/yarn.lock
13378
app/client/web/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user