mirror of
https://github.com/balzack/databag.git
synced 2025-02-11 19:19:16 +00:00
providing server side config for key size and asset type support
This commit is contained in:
parent
fd372187bc
commit
58a2984dbc
19
doc/api.oa3
19
doc/api.oa3
@ -3271,8 +3271,6 @@ components:
|
||||
type: object
|
||||
required:
|
||||
- domain
|
||||
- openAccess
|
||||
- accountLimit
|
||||
- accountStorage
|
||||
properties:
|
||||
domain:
|
||||
@ -3280,11 +3278,14 @@ components:
|
||||
accountStorage:
|
||||
type: integer
|
||||
format: int64
|
||||
openAccess:
|
||||
enableImage:
|
||||
type: boolean
|
||||
accountLimit:
|
||||
type: integer
|
||||
format: int64
|
||||
enableAudio:
|
||||
type: boolean
|
||||
enableVideo:
|
||||
type: boolean
|
||||
keyType:
|
||||
type: string
|
||||
|
||||
AccountStatus:
|
||||
type: object
|
||||
@ -3627,6 +3628,12 @@ components:
|
||||
updated:
|
||||
type: integer
|
||||
format: int64
|
||||
enableImage:
|
||||
type: boolean
|
||||
enableAudio:
|
||||
type: boolean
|
||||
enableVideo:
|
||||
type: video
|
||||
contacts:
|
||||
$ref: '#/components/schemas/ChannelContacts'
|
||||
members:
|
||||
|
@ -80,5 +80,9 @@ func AddChannel(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(account, card)
|
||||
}
|
||||
WriteResponse(w, getChannelModel(slot, true, true))
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
WriteResponse(w, getChannelModel(slot, true, true, image, audio, video))
|
||||
}
|
||||
|
@ -89,5 +89,9 @@ func ClearChannelCard(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(account, &card)
|
||||
}
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true))
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true, image, audio, video))
|
||||
}
|
||||
|
@ -83,5 +83,9 @@ func ClearChannelGroup(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(account, &card)
|
||||
}
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true))
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true, image, audio, video))
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ func GetAccountAvailable(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func getAvailableAccounts() (available int64, err error) {
|
||||
|
||||
open := getBoolConfigValue(CNFOpenAccess, true)
|
||||
limit := getNumConfigValue(CNFAccountLimit, 16)
|
||||
open := getBoolConfigValue(CNFOpenAccess, false)
|
||||
limit := getNumConfigValue(CNFAccountLimit, 0)
|
||||
|
||||
var count int64
|
||||
if err = store.DB.Model(&store.Account{}).Count(&count).Error; err != nil {
|
||||
|
@ -49,15 +49,19 @@ func GetChannelDetail(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
|
||||
// return model data
|
||||
if guid != "" {
|
||||
if isChannelShared(guid, slot.Channel) {
|
||||
WriteResponse(w, getChannelDetailModel(&slot, false))
|
||||
WriteResponse(w, getChannelDetailModel(&slot, false, image, audio, video))
|
||||
} else {
|
||||
ErrResponse(w, http.StatusNotFound, errors.New("channel not shared with requestor"))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
WriteResponse(w, getChannelDetailModel(&slot, true))
|
||||
WriteResponse(w, getChannelDetailModel(&slot, true, image, audio, video))
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,10 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
|
||||
response := []*Channel{}
|
||||
tokenType := ParamTokenType(r)
|
||||
if tokenType == APPTokenAgent {
|
||||
@ -80,7 +84,7 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
|
||||
if channelRevisionSet {
|
||||
response = append(response, getChannelRevisionModel(&slot, true))
|
||||
} else if slot.Channel != nil {
|
||||
response = append(response, getChannelModel(&slot, true, true))
|
||||
response = append(response, getChannelModel(&slot, true, true, image, audio, video))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -124,7 +128,7 @@ func GetChannels(w http.ResponseWriter, r *http.Request) {
|
||||
if channelRevisionSet {
|
||||
response = append(response, getChannelRevisionModel(&slot, shared))
|
||||
} else if shared {
|
||||
response = append(response, getChannelModel(&slot, true, false))
|
||||
response = append(response, getChannelModel(&slot, true, false, image, audio, video))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,11 @@ func GetNodeConfig(w http.ResponseWriter, r *http.Request) {
|
||||
// get node config fields
|
||||
var config NodeConfig
|
||||
config.Domain = getStrConfigValue(CNFDomain, "")
|
||||
config.AccountLimit = getNumConfigValue(CNFAccountLimit, 16)
|
||||
config.OpenAccess = getBoolConfigValue(CNFOpenAccess, true)
|
||||
config.AccountStorage = getNumConfigValue(CNFStorage, 0)
|
||||
config.EnableImage = getBoolConfigValue(CNFEnableImage, true)
|
||||
config.EnableAudio = getBoolConfigValue(CNFEnableAudio, true)
|
||||
config.EnableVideo = getBoolConfigValue(CNFEnableVideo, true)
|
||||
config.KeyType = getStrConfigValue(CNFKeyType, APPRSA4096)
|
||||
|
||||
WriteResponse(w, config)
|
||||
}
|
||||
|
@ -90,5 +90,9 @@ func SetChannelCard(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(account, &card)
|
||||
}
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true))
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true, image, audio, video))
|
||||
}
|
||||
|
@ -83,5 +83,9 @@ func SetChannelGroup(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(account, &card)
|
||||
}
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true))
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
WriteResponse(w, getChannelModel(&channelSlot, true, true, image, audio, video))
|
||||
}
|
||||
|
@ -82,5 +82,9 @@ func SetChannelSubject(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(account, &card)
|
||||
}
|
||||
WriteResponse(w, getChannelModel(&slot, true, true))
|
||||
|
||||
video := getBoolConfigValue(CNFEnableVideo, true);
|
||||
audio := getBoolConfigValue(CNFEnableAudio, true);
|
||||
image := getBoolConfigValue(CNFEnableImage, true);
|
||||
WriteResponse(w, getChannelModel(&slot, true, true, image, audio, video))
|
||||
}
|
||||
|
@ -34,22 +34,6 @@ func SetNodeConfig(w http.ResponseWriter, r *http.Request) {
|
||||
return res
|
||||
}
|
||||
|
||||
// upsert account limit config
|
||||
if res := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "config_id"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
|
||||
}).Create(&store.Config{ConfigID: CNFAccountLimit, NumValue: config.AccountLimit}).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
// upsert account open access
|
||||
if res := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "config_id"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"bool_value"}),
|
||||
}).Create(&store.Config{ConfigID: CNFAccountLimit, BoolValue: config.OpenAccess}).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
// upsert account storage config
|
||||
if res := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "config_id"}},
|
||||
@ -58,6 +42,38 @@ func SetNodeConfig(w http.ResponseWriter, r *http.Request) {
|
||||
return res
|
||||
}
|
||||
|
||||
// upsert enable image processing
|
||||
if res := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "config_id"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"bool_value"}),
|
||||
}).Create(&store.Config{ConfigID: CNFEnableImage, BoolValue: config.EnableImage}).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
// upsert enable audio processing
|
||||
if res := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "config_id"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"bool_value"}),
|
||||
}).Create(&store.Config{ConfigID: CNFEnableAudio, BoolValue: config.EnableAudio}).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
// upsert enable video processing
|
||||
if res := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "config_id"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"bool_value"}),
|
||||
}).Create(&store.Config{ConfigID: CNFEnableVideo, BoolValue: config.EnableVideo}).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
// upsert key type
|
||||
if res := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "config_id"}},
|
||||
DoUpdates: clause.AssignmentColumns([]string{"str_value"}),
|
||||
}).Create(&store.Config{ConfigID: CNFKeyType, StrValue: config.KeyType}).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -30,6 +30,18 @@ const CNFAssetPath = "asset_path"
|
||||
//CNFScriptPath specifies the path where transform scripts are found
|
||||
const CNFScriptPath = "script_path"
|
||||
|
||||
//CNFEnableImage specifies whether node can process image assets
|
||||
const CNFEnableImage = "enable_image"
|
||||
|
||||
//CNFEnableAudio specifies whether node can process audio assets
|
||||
const CNFEnableAudio = "enable_audio"
|
||||
|
||||
//CNFEnableVideo specifies whether node can process video assets
|
||||
const CNFEnableVideo = "enable_video"
|
||||
|
||||
//CNFKeyType specifies the type of key to use for identity
|
||||
const CNFKeyType = "key_type"
|
||||
|
||||
func getStrConfigValue(configID string, empty string) string {
|
||||
var config store.Config
|
||||
err := store.DB.Where("config_id = ?", configID).First(&config).Error
|
||||
|
@ -8,20 +8,14 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var keySize int = APPKeySize
|
||||
|
||||
//SetKeySize sets the key size to use for new accounts
|
||||
func SetKeySize(size int) {
|
||||
keySize = size
|
||||
}
|
||||
|
||||
//GenerateRsaKeyPair creates a public/private key for a new account
|
||||
func GenerateRsaKeyPair() (*rsa.PrivateKey, *rsa.PublicKey, string, error) {
|
||||
if keySize == 2048 {
|
||||
privkey, _ := rsa.GenerateKey(rand.Reader, keySize)
|
||||
keyType := getStrConfigValue(CNFKeyType, "RSA4096");
|
||||
if keyType == "RSA2048" {
|
||||
privkey, _ := rsa.GenerateKey(rand.Reader, 2048)
|
||||
return privkey, &privkey.PublicKey, "RSA2048", nil
|
||||
} else if keySize == 4096 {
|
||||
privkey, _ := rsa.GenerateKey(rand.Reader, keySize)
|
||||
} else if keyType == "RSA4096" {
|
||||
privkey, _ := rsa.GenerateKey(rand.Reader, 4096)
|
||||
return privkey, &privkey.PublicKey, "RSA2048", nil
|
||||
} else {
|
||||
return nil, nil, "", errors.New("invalid key setting")
|
||||
|
@ -166,7 +166,7 @@ func getChannelRevisionModel(slot *store.ChannelSlot, showData bool) *Channel {
|
||||
}
|
||||
}
|
||||
|
||||
func getChannelDetailModel(slot *store.ChannelSlot, showList bool) *ChannelDetail {
|
||||
func getChannelDetailModel(slot *store.ChannelSlot, showList bool, image bool, audio bool, video bool) *ChannelDetail {
|
||||
|
||||
if slot.Channel == nil {
|
||||
return nil
|
||||
@ -195,6 +195,9 @@ func getChannelDetailModel(slot *store.ChannelSlot, showList bool) *ChannelDetai
|
||||
Data: slot.Channel.Data,
|
||||
Created: slot.Channel.Created,
|
||||
Updated: slot.Channel.Updated,
|
||||
EnableImage: image,
|
||||
EnableAudio: audio,
|
||||
EnableVideo: video,
|
||||
Contacts: contacts,
|
||||
Members: members,
|
||||
}
|
||||
@ -221,7 +224,7 @@ func getChannelSummaryModel(slot *store.ChannelSlot) *ChannelSummary {
|
||||
}
|
||||
}
|
||||
|
||||
func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool) *Channel {
|
||||
func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool, image bool, audio bool, video bool) *Channel {
|
||||
|
||||
if !showData || slot.Channel == nil {
|
||||
return &Channel{
|
||||
@ -236,7 +239,7 @@ func getChannelModel(slot *store.ChannelSlot, showData bool, showList bool) *Cha
|
||||
Data: &ChannelData{
|
||||
DetailRevision: slot.Channel.DetailRevision,
|
||||
TopicRevision: slot.Channel.TopicRevision,
|
||||
ChannelDetail: getChannelDetailModel(slot, showList),
|
||||
ChannelDetail: getChannelDetailModel(slot, showList, image, audio, video),
|
||||
ChannelSummary: getChannelSummaryModel(slot),
|
||||
},
|
||||
}
|
||||
|
@ -178,6 +178,12 @@ type ChannelDetail struct {
|
||||
|
||||
Updated int64 `json:"updated"`
|
||||
|
||||
EnableImage bool `json:"enableImage"`
|
||||
|
||||
EnableAudio bool `json:"enableAudio"`
|
||||
|
||||
EnableVideo bool `json:"enableVideo"`
|
||||
|
||||
Contacts *ChannelContacts `json:"contacts,omitempty"`
|
||||
|
||||
Members []string `json:"members"`
|
||||
@ -321,9 +327,13 @@ type LoginAccess struct {
|
||||
type NodeConfig struct {
|
||||
Domain string `json:"domain"`
|
||||
|
||||
OpenAccess bool `json:"openAccess"`
|
||||
EnableImage bool `json:"enableImage"`
|
||||
|
||||
AccountLimit int64 `json:"accountLimit"`
|
||||
EnableAudio bool `json:"enableAudio"`
|
||||
|
||||
EnableVideo bool `json:"enableVideo"`
|
||||
|
||||
KeyType string `json:"keyType"`
|
||||
|
||||
AccountStorage int64 `json:"accountStorage"`
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { DashboardWrapper, SettingsButton, AddButton, SettingsLayout, CreateLayout } from './Dashboard.styled';
|
||||
import { Tooltip, Button, Modal, Input, InputNumber, Space, List } from 'antd';
|
||||
import { Tooltip, Checkbox, Select, Button, Modal, Input, InputNumber, Space, List } from 'antd';
|
||||
import { SettingOutlined, CopyOutlined, UserAddOutlined, LogoutOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||
import { useDashboard } from './useDashboard.hook';
|
||||
import { AccountItem } from './accountItem/AccountItem';
|
||||
@ -63,15 +63,35 @@ export function Dashboard({ token, config, logout }) {
|
||||
<Modal title="Settings" visible={state.showSettings} centered
|
||||
okText="Save" onOk={() => actions.setSettings()} onCancel={() => actions.setShowSettings(false)}>
|
||||
<SettingsLayout direction="vertical">
|
||||
<div class="host">
|
||||
<div class="field">
|
||||
<div>Federated Host: </div>
|
||||
<Input placeholder="domain:port/app" onChange={(e) => actions.setHost(e.target.value)}
|
||||
value={state.host} />
|
||||
value={state.domain} />
|
||||
</div>
|
||||
<div class="storage">
|
||||
<div class="field">
|
||||
<div>Storage Limit (GB) / Account: </div>
|
||||
<InputNumber defaultValue={8} onChange={(e) => actions.setStorage(e)}
|
||||
placeholder="0 for unrestricted" value={state.storage} />
|
||||
<InputNumber defaultValue={0} onChange={(e) => actions.setStorage(e)}
|
||||
placeholder="0 for unrestricted" value={state.accountStorage} />
|
||||
</div>
|
||||
<div class="field">
|
||||
<div>Account Key Type: </div>
|
||||
<Select labelInValue defaultValue={{ value: 'RSA4096', label: 'RSA 4096' }}
|
||||
value={state.keyType} onChange={(o) => actions.setKeyType(o.value)}>
|
||||
<Select.Option value="RSA2048">RSA 2048</Select.Option>
|
||||
<Select.Option value="RSA4096">RSA 4096</Select.Option>
|
||||
</Select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Checkbox onChange={(e) => actions.setEnableImage(e.target.checked)}
|
||||
defaultChecked={true} checked={state.enableImage}>Enable Image Queue</Checkbox>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Checkbox onChange={(e) => actions.setEnableAudio(e.target.checked)}
|
||||
defaultChecked={true} checked={state.enableAudio}>Enable Audio Queue</Checkbox>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Checkbox onChange={(e) => actions.setEnableVideo(e.target.checked)}
|
||||
defaultChecked={true} checked={state.enableVideo}>Enable Video Queue</Checkbox>
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
</Modal>
|
||||
|
@ -71,14 +71,7 @@ export const SettingsButton = styled(Button)`
|
||||
export const SettingsLayout = styled(Space)`
|
||||
width: 100%;
|
||||
|
||||
.host {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.storage {
|
||||
.field {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -7,8 +7,12 @@ import { addAccountCreate } from 'api/addAccountCreate';
|
||||
export function useDashboard(token, config) {
|
||||
|
||||
const [state, setState] = useState({
|
||||
host: "",
|
||||
storage: null,
|
||||
domain: "",
|
||||
accountStorage: null,
|
||||
keyType: null,
|
||||
enableImage: null,
|
||||
enableAudio: null,
|
||||
enableVideo: null,
|
||||
showSettings: false,
|
||||
busy: false,
|
||||
loading: false,
|
||||
@ -42,11 +46,23 @@ export function useDashboard(token, config) {
|
||||
await removeAccount(token, accountId);
|
||||
actions.getAccounts();
|
||||
},
|
||||
setHost: (value) => {
|
||||
updateState({ host: value });
|
||||
setHost: (domain) => {
|
||||
updateState({ domain });
|
||||
},
|
||||
setStorage: (value) => {
|
||||
updateState({ storage: value });
|
||||
setStorage: (accountStorage) => {
|
||||
updateState({ accountStorage });
|
||||
},
|
||||
setKeyType: (keyType) => {
|
||||
updateState({ keyType });
|
||||
},
|
||||
setEnableImage: (enableImage) => {
|
||||
updateState({ enableImage });
|
||||
},
|
||||
setEnableAudio: (enableAudio) => {
|
||||
updateState({ enableAudio });
|
||||
},
|
||||
setEnableVideo: (enableVideo) => {
|
||||
updateState({ enableVideo });
|
||||
},
|
||||
setShowSettings: (value) => {
|
||||
updateState({ showSettings: value });
|
||||
@ -55,8 +71,10 @@ export function useDashboard(token, config) {
|
||||
if (!state.busy) {
|
||||
updateState({ busy: true });
|
||||
try {
|
||||
const { domain, keyType, accountStorage, enableImage, enableAudio, enableVideo } = state;
|
||||
await setNodeConfig(token,
|
||||
{ ...state.config, domain: state.host, accountStorage: state.storage * 1073741824 });
|
||||
{ domain, accountStorage: accountStorage * 1073741824,
|
||||
keyType, enableImage, enableAudio, enableVideo });
|
||||
updateState({ showSettings: false });
|
||||
}
|
||||
catch(err) {
|
||||
@ -92,13 +110,11 @@ export function useDashboard(token, config) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let storage = config.accountStorage / 1073741824;
|
||||
if (storage > 1) {
|
||||
storage = Math.ceil(storage);
|
||||
}
|
||||
updateState({ host: config.domain, storage: storage });
|
||||
const { accountStorage, domain, keyType, enableImage, enableAudio, enableVideo } = config;
|
||||
updateState({ domain, accountStorage: Math.ceil(accountStorage / 1073741824), keyType,
|
||||
enableImage, enableAudio, enableVideo });
|
||||
actions.getAccounts();
|
||||
}, []);
|
||||
}, [config]);
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ export function useConversationContext() {
|
||||
members: new Set(),
|
||||
topics: new Map(),
|
||||
revision: null,
|
||||
enableImage: null,
|
||||
enabelAudio: null,
|
||||
enableVideo: null,
|
||||
});
|
||||
|
||||
const EVENT_OPEN = 1;
|
||||
@ -198,12 +201,16 @@ export function useConversationContext() {
|
||||
let subject = getSubject(chan);
|
||||
let contacts = getContacts(chan);
|
||||
let members = getMembers(chan);
|
||||
const { enableImage, enableAudio, enableVideo } = chan.data.channelDetail;
|
||||
updateState({
|
||||
init: true,
|
||||
error: false,
|
||||
subject,
|
||||
contacts,
|
||||
members,
|
||||
enableImage,
|
||||
enableAudio,
|
||||
enableVideo,
|
||||
topics: topics.current,
|
||||
revision: channelView.current.revision,
|
||||
});
|
||||
|
@ -104,15 +104,21 @@ export function AddTopic({ cardId, channelId }) {
|
||||
value={state.messageText} autocapitalize="none" />
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="button space" onClick={() => attachImage.current.click()}>
|
||||
<PictureOutlined />
|
||||
</div>
|
||||
<div class="button space" onClick={() => attachVideo.current.click()}>
|
||||
<VideoCameraOutlined />
|
||||
</div>
|
||||
<div class="button space" onClick={() => attachAudio.current.click()}>
|
||||
<SoundOutlined />
|
||||
</div>
|
||||
{ state.enableImage && (
|
||||
<div class="button space" onClick={() => attachImage.current.click()}>
|
||||
<PictureOutlined />
|
||||
</div>
|
||||
)}
|
||||
{ state.enableVideo && (
|
||||
<div class="button space" onClick={() => attachVideo.current.click()}>
|
||||
<VideoCameraOutlined />
|
||||
</div>
|
||||
)}
|
||||
{ state.enableAudio && (
|
||||
<div class="button space" onClick={() => attachAudio.current.click()}>
|
||||
<SoundOutlined />
|
||||
</div>
|
||||
)}
|
||||
<div class="bar space" />
|
||||
<div class="button space">
|
||||
<Dropdown overlay={picker} overlayStyle={{ minWidth: 0 }} trigger={['click']} placement="top">
|
||||
|
@ -1,10 +1,14 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { CardContext } from 'context/CardContext';
|
||||
import { ChannelContext } from 'context/ChannelContext';
|
||||
import { ConversationContext } from 'context/ConversationContext';
|
||||
|
||||
export function useAddTopic(cardId, channelId) {
|
||||
|
||||
const [state, setState] = useState({
|
||||
enableImage: null,
|
||||
enableAudio: null,
|
||||
enableVideo: null,
|
||||
assets: [],
|
||||
messageText: null,
|
||||
textColor: '#444444',
|
||||
@ -16,6 +20,7 @@ export function useAddTopic(cardId, channelId) {
|
||||
|
||||
const card = useContext(CardContext);
|
||||
const channel = useContext(ChannelContext);
|
||||
const conversation = useContext(ConversationContext);
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
@ -43,6 +48,11 @@ export function useAddTopic(cardId, channelId) {
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const { enableImage, enableAudio, enableVideo } = conversation.state;
|
||||
updateState({ enableImage, enableAudio, enableVideo });
|
||||
}, [conversation]);
|
||||
|
||||
const actions = {
|
||||
addImage: (image) => {
|
||||
let url = URL.createObjectURL(image);
|
||||
|
Loading…
Reference in New Issue
Block a user