mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
refactor add modal for webapp
This commit is contained in:
parent
064ec721af
commit
e405f46330
@ -1,5 +1,5 @@
|
||||
import { Modal, Input, List, Button, Switch } from 'antd';
|
||||
import { ChannelsWrapper, AddFooter } from './Channels.styled';
|
||||
import { Modal, Input, List, Button } from 'antd';
|
||||
import { ChannelsWrapper } from './Channels.styled';
|
||||
import { CommentOutlined, SearchOutlined } from '@ant-design/icons';
|
||||
import { useChannels } from './useChannels.hook';
|
||||
import { ChannelItem } from './channelItem/ChannelItem';
|
||||
@ -9,34 +9,14 @@ export function Channels({ open, active }) {
|
||||
|
||||
const { state, actions } = useChannels();
|
||||
|
||||
const addChannel = async () => {
|
||||
try {
|
||||
const id = await actions.addChannel();
|
||||
const added = (id) => {
|
||||
actions.clearShowAdd();
|
||||
open(id);
|
||||
}
|
||||
catch(err) {
|
||||
Modal.error({
|
||||
title: 'Failed to Create Topic',
|
||||
content: 'Please try again.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const addFooter = (
|
||||
<AddFooter>
|
||||
<div class="seal">
|
||||
{ state.sealable && (
|
||||
<>
|
||||
<Switch checked={state.seal} onChange={actions.setSeal} size="small" />
|
||||
<span class="sealText">Sealed Channel</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<Button key="back" onClick={actions.clearShowAdd}>Cancel</Button>
|
||||
<Button key="save" type="primary" loading={state.busy} onClick={addChannel}>Save</Button>
|
||||
</AddFooter>
|
||||
);
|
||||
const cancelled = () => {
|
||||
actions.clearShowAdd();
|
||||
}
|
||||
|
||||
return (
|
||||
<ChannelsWrapper>
|
||||
@ -69,9 +49,8 @@ export function Channels({ open, active }) {
|
||||
<Button type="primary" icon={<CommentOutlined />} onClick={actions.setShowAdd}>New Topic</Button>
|
||||
</div>
|
||||
)}
|
||||
<Modal title="New Topic" centered visible={state.showAdd} footer={addFooter}
|
||||
onCancel={actions.clearShowAdd}>
|
||||
<AddChannel state={state} actions={actions} />
|
||||
<Modal title="New Topic" centered visible={state.showAdd} footer={null}>
|
||||
<AddChannel added={added} cancelled={cancelled} />
|
||||
</Modal>
|
||||
</ChannelsWrapper>
|
||||
);
|
||||
|
@ -87,22 +87,3 @@ export const ChannelsWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export const AddFooter = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.seal {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.sealText {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -1,11 +1,30 @@
|
||||
import { Input } from 'antd';
|
||||
import { AddChannelWrapper } from './AddChannel.styled';
|
||||
import { Input, Space, Modal, Switch, Button } from 'antd';
|
||||
import { AddChannelWrapper, AddFooter } from './AddChannel.styled';
|
||||
import { CardSelect } from '../../cardSelect/CardSelect';
|
||||
import { useAddChannel } from './useAddChannel.hook';
|
||||
|
||||
export function AddChannel({ state, actions }) {
|
||||
export function AddChannel({ added, cancelled }) {
|
||||
|
||||
const [ modal, modalContext ] = Modal.useModal();
|
||||
const { state, actions } = useAddChannel();
|
||||
|
||||
const addChannel = async () => {
|
||||
try {
|
||||
const id = await actions.addChannel();
|
||||
added(id);
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
modal.error({
|
||||
title: 'Failed to Create Topic',
|
||||
content: 'Please try again.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<AddChannelWrapper>
|
||||
{ modalContext }
|
||||
<Input placeholder="Subject (optional)" spellCheck="false" autocapitalize="word"
|
||||
value={state.subject} onChange={(e) => actions.setSubject(e.target.value)} />
|
||||
<div class="members">
|
||||
@ -23,6 +42,20 @@ export function AddChannel({ state, actions }) {
|
||||
unknown={0}
|
||||
/>
|
||||
</div>
|
||||
<AddFooter>
|
||||
<div class="seal">
|
||||
{ state.sealable && (
|
||||
<>
|
||||
<Switch checked={state.seal} onChange={actions.setSeal} size="small" />
|
||||
<span class="sealText">Sealed Channel</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<Space>
|
||||
<Button key="back" onClick={cancelled}>Cancel</Button>
|
||||
<Button key="save" type="primary" loading={state.busy} onClick={addChannel}>Save</Button>
|
||||
</Space>
|
||||
</AddFooter>
|
||||
</AddChannelWrapper>
|
||||
);
|
||||
}
|
||||
|
@ -23,4 +23,23 @@ export const AddChannelWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export const AddFooter = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-top: 8px;
|
||||
|
||||
.seal {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.sealText {
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
|
105
net/web/src/session/channels/addChannel/useAddChannel.hook.js
Normal file
105
net/web/src/session/channels/addChannel/useAddChannel.hook.js
Normal file
@ -0,0 +1,105 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { ChannelContext } from 'context/ChannelContext';
|
||||
import { CardContext } from 'context/CardContext';
|
||||
import { AccountContext } from 'context/AccountContext';
|
||||
|
||||
export function useAddChannel() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
sealable: false,
|
||||
busy: false,
|
||||
|
||||
showAdd: false,
|
||||
subject: null,
|
||||
members: new Set(),
|
||||
seal: false,
|
||||
});
|
||||
|
||||
const card = useContext(CardContext);
|
||||
const channel = useContext(ChannelContext);
|
||||
const account = useContext(AccountContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const { seal, sealKey } = account.state;
|
||||
if (seal?.publicKey && sealKey?.public && sealKey?.private && seal.publicKey === sealKey.public) {
|
||||
updateState({ seal: false, sealable: true });
|
||||
}
|
||||
else {
|
||||
updateState({ seal: false, sealable: false });
|
||||
}
|
||||
}, [account.state]);
|
||||
|
||||
const actions = {
|
||||
addChannel: async () => {
|
||||
let conversation;
|
||||
if (!state.busy) {
|
||||
try {
|
||||
updateState({ busy: true });
|
||||
const cards = Array.from(state.members.values());
|
||||
if (state.seal) {
|
||||
const keys = [ account.state.sealKey.public ];
|
||||
cards.forEach(id => {
|
||||
keys.push(card.state.cards.get(id).data.cardProfile.seal);
|
||||
});
|
||||
|
||||
throw new Error("TODO");
|
||||
}
|
||||
else {
|
||||
conversation = await channel.actions.addChannel('superbasic', state.subject, cards);
|
||||
}
|
||||
updateState({ busy: false });
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
updateState({ busy: false });
|
||||
throw new Error("failed to create new channel");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("operation in progress");
|
||||
}
|
||||
return conversation.id;
|
||||
},
|
||||
setSeal: (seal) => {
|
||||
if (seal) {
|
||||
const cards = Array.from(state.members.values());
|
||||
const members = new Set(state.members);
|
||||
cards.forEach(id => {
|
||||
if (!(card.state.cards.get(id)?.data?.cardProfile?.seal)) {
|
||||
members.delete(id);
|
||||
}
|
||||
});
|
||||
updateState({ seal: true, members });
|
||||
}
|
||||
else {
|
||||
updateState({ seal: false });
|
||||
}
|
||||
},
|
||||
onMember: (string) => {
|
||||
const members = new Set(state.members);
|
||||
if (members.has(string)) {
|
||||
members.delete(string);
|
||||
}
|
||||
else {
|
||||
members.add(string);
|
||||
}
|
||||
updateState({ members });
|
||||
},
|
||||
setSubject: (subject) => {
|
||||
updateState({ subject });
|
||||
},
|
||||
cardFilter: (card) => {
|
||||
if (state.seal) {
|
||||
return card?.data?.cardDetail?.status === 'connected' && card?.data?.cardProfile?.seal;
|
||||
}
|
||||
return card?.data?.cardDetail?.status === 'connected';
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -15,13 +15,7 @@ export function useChannels() {
|
||||
const [state, setState] = useState({
|
||||
display: null,
|
||||
channels: [],
|
||||
sealable: false,
|
||||
busy: false,
|
||||
|
||||
showAdd: false,
|
||||
subject: null,
|
||||
members: new Set(),
|
||||
seal: false,
|
||||
});
|
||||
|
||||
const profile = useContext(ProfileContext);
|
||||
@ -172,16 +166,6 @@ export function useChannels() {
|
||||
item.topicRevision = channelValue.data.topicRevision;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const { seal, sealKey } = account.state;
|
||||
if (seal?.publicKey && sealKey?.public && sealKey?.private && seal.publicKey === sealKey.public) {
|
||||
updateState({ seal: false, sealable: true });
|
||||
}
|
||||
else {
|
||||
updateState({ seal: false, sealable: false });
|
||||
}
|
||||
}, [account.state]);
|
||||
|
||||
useEffect(() => {
|
||||
const login = store.state['login:timestamp'];
|
||||
const conversations = new Map();
|
||||
@ -278,78 +262,15 @@ export function useChannels() {
|
||||
}, [viewport]);
|
||||
|
||||
const actions = {
|
||||
addChannel: async () => {
|
||||
let added;
|
||||
if (!state.busy) {
|
||||
try {
|
||||
updateState({ busy: true });
|
||||
const cards = Array.from(state.members.values());
|
||||
if (state.seal) {
|
||||
const keys = [ account.state.sealKey.public ];
|
||||
cards.forEach(id => {
|
||||
keys.push(card.state.cards.get(id).data.cardProfile.seal);
|
||||
});
|
||||
added = await channel.actions.addSealedChannel(cards, state.subject, keys);
|
||||
}
|
||||
else {
|
||||
added = await channel.actions.addBasicChannel(cards, state.subject);
|
||||
}
|
||||
updateState({ busy: false });
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
updateState({ busy: false });
|
||||
throw new Error("failed to create new channel");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error("operation in progress");
|
||||
}
|
||||
return added.id;
|
||||
},
|
||||
setSeal: (seal) => {
|
||||
if (seal) {
|
||||
const cards = Array.from(state.members.values());
|
||||
const members = new Set(state.members);
|
||||
cards.forEach(id => {
|
||||
if (!(card.state.cards.get(id)?.data?.cardProfile?.seal)) {
|
||||
members.delete(id);
|
||||
}
|
||||
});
|
||||
updateState({ seal: true, members });
|
||||
}
|
||||
else {
|
||||
updateState({ seal: false });
|
||||
}
|
||||
},
|
||||
onFilter: (value) => {
|
||||
setFilter(value?.toUpperCase());
|
||||
},
|
||||
setShowAdd: () => {
|
||||
updateState({ showAdd: true, seal: false, members: new Set(), subject: null });
|
||||
updateState({ showAdd: true });
|
||||
},
|
||||
clearShowAdd: () => {
|
||||
updateState({ showAdd: false });
|
||||
},
|
||||
onMember: (string) => {
|
||||
const members = new Set(state.members);
|
||||
if (members.has(string)) {
|
||||
members.delete(string);
|
||||
}
|
||||
else {
|
||||
members.add(string);
|
||||
}
|
||||
updateState({ members });
|
||||
},
|
||||
setSubject: (subject) => {
|
||||
updateState({ subject });
|
||||
},
|
||||
cardFilter: (card) => {
|
||||
if (state.seal) {
|
||||
return card?.data?.cardDetail?.status === 'connected' && card?.data?.cardProfile?.seal;
|
||||
}
|
||||
return card?.data?.cardDetail?.status === 'connected';
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
Loading…
Reference in New Issue
Block a user