mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
rendering topic images
This commit is contained in:
parent
ed89df3235
commit
80c0b0c97d
@ -238,6 +238,7 @@ type Topic struct {
|
||||
Created int64 `gorm:"autoCreateTime"`
|
||||
Updated int64 `gorm:"autoUpdateTime"`
|
||||
TagRevision int64 `gorm:"not null"`
|
||||
Account Account
|
||||
Channel *Channel
|
||||
Assets []Asset
|
||||
Tags []Tag
|
||||
|
@ -1,7 +1,6 @@
|
||||
package databag
|
||||
|
||||
import (
|
||||
"time"
|
||||
"os"
|
||||
"io"
|
||||
"hash/crc32"
|
||||
@ -106,7 +105,6 @@ func transcodeAsset(asset *store.Asset) {
|
||||
cmd.Stdout = &stdout
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
time.Sleep(time.Second);
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
LogMsg(stdout.String())
|
||||
@ -138,7 +136,7 @@ time.Sleep(time.Second);
|
||||
|
||||
func UpdateAsset(asset *store.Asset, status string, crc uint32, size int64) (err error) {
|
||||
|
||||
act := asset.Account
|
||||
topic := store.Topic{};
|
||||
err = store.DB.Transaction(func(tx *gorm.DB) error {
|
||||
asset.Crc = crc
|
||||
asset.Size = size
|
||||
@ -146,19 +144,22 @@ func UpdateAsset(asset *store.Asset, status string, crc uint32, size int64) (err
|
||||
if res := tx.Model(store.Asset{}).Where("id = ?", asset.ID).Updates(asset).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&asset.Topic).Update("detail_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
if res := tx.Preload("Account").Preload("TopicSlot").Preload("Channel.ChannelSlot").First(&topic, asset.Topic.ID).Error; res != nil {
|
||||
return res;
|
||||
}
|
||||
if res := tx.Model(&topic).Update("detail_revision", topic.Account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&asset.Topic.TopicSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
if res := tx.Model(&topic.TopicSlot).Update("revision", topic.Account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&asset.Channel).Update("topic_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
if res := tx.Model(&topic.Channel).Update("topic_revision", topic.Account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&asset.Channel.ChannelSlot).Update("revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
if res := tx.Model(&topic.Channel.ChannelSlot).Update("revision", topic.Account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
if res := tx.Model(&act).Update("channel_revision", act.ChannelRevision + 1).Error; res != nil {
|
||||
if res := tx.Model(&topic.Account).Update("channel_revision", topic.Account.ChannelRevision + 1).Error; res != nil {
|
||||
return res
|
||||
}
|
||||
return nil
|
||||
@ -169,19 +170,19 @@ func UpdateAsset(asset *store.Asset, status string, crc uint32, size int64) (err
|
||||
|
||||
// determine affected contact list
|
||||
cards := make(map[string]store.Card)
|
||||
for _, card := range asset.Channel.Cards {
|
||||
for _, card := range topic.Channel.Cards {
|
||||
cards[card.Guid] = card
|
||||
}
|
||||
for _, group := range asset.Channel.Groups {
|
||||
for _, group := range topic.Channel.Groups {
|
||||
for _, card := range group.Cards {
|
||||
cards[card.Guid] = card
|
||||
}
|
||||
}
|
||||
|
||||
// notify
|
||||
SetStatus(&act)
|
||||
SetStatus(&topic.Account)
|
||||
for _, card := range cards {
|
||||
SetContactChannelNotification(&act, &card)
|
||||
SetContactChannelNotification(&topic.Account, &card)
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -4,6 +4,7 @@ import ReactResizeDetector from 'react-resize-detector';
|
||||
import { useTopicItem } from './useTopicItem.hook';
|
||||
import { Avatar } from 'avatar/Avatar';
|
||||
import { CommentOutlined } from '@ant-design/icons';
|
||||
import { Carousel } from 'Carousel/Carousel';
|
||||
|
||||
export function TopicItem({ topic }) {
|
||||
|
||||
@ -14,6 +15,13 @@ export function TopicItem({ topic }) {
|
||||
let d = new Date();
|
||||
let offset = d.getTime() / 1000 - state.created;
|
||||
|
||||
const renderAsset = (asset) => {
|
||||
if (asset.image) {
|
||||
return <img style={{ height: '100%', objectFit: 'container' }} src={actions.getAssetUrl(asset.image.full)} alt="" />
|
||||
}
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<TopicItemWrapper>
|
||||
<div class="avatar">
|
||||
@ -27,7 +35,8 @@ export function TopicItem({ topic }) {
|
||||
<CommentOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div class="message">{ state.message }</div>
|
||||
<Carousel items={state.assets} itemRenderer={renderAsset} />
|
||||
<div class="message">{ state.message?.text }</div>
|
||||
</div>
|
||||
</TopicItemWrapper>
|
||||
)
|
||||
|
@ -13,6 +13,9 @@ export function useTopicItem(topic) {
|
||||
imageUrl: null,
|
||||
message: null,
|
||||
created: null,
|
||||
status: null,
|
||||
transform: null,
|
||||
assets: [],
|
||||
});
|
||||
|
||||
const profile = useContext(ProfileContext);
|
||||
@ -24,10 +27,19 @@ export function useTopicItem(topic) {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const { status, transform, data } = topic.data.topicDetail;
|
||||
let message;
|
||||
if( topic.data.topicDetail.status === 'confirmed') {
|
||||
let assets = [];
|
||||
if (status === 'confirmed') {
|
||||
try {
|
||||
message = JSON.parse(topic.data.topicDetail.data).text;
|
||||
message = JSON.parse(data);
|
||||
if (transform === 'complete') {
|
||||
if (message.assets) {
|
||||
assets = message.assets;
|
||||
delete message.assets;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
@ -38,16 +50,19 @@ export function useTopicItem(topic) {
|
||||
const { guid, created } = topic.data.topicDetail;
|
||||
if (profile.state.profile.guid == guid) {
|
||||
const { name, handle, imageUrl } = profile.actions.getProfile();
|
||||
updateState({ name, handle, imageUrl, message, created });
|
||||
updateState({ name, handle, imageUrl, status, message, transform, assets, created });
|
||||
}
|
||||
else {
|
||||
const { name, handle, imageUrl } = card.actions.getCardProfileByGuid(guid);
|
||||
updateState({ name, handle, imageUrl, message, created });
|
||||
updateState({ name, handle, imageUrl, status, message, transform, assets, created });
|
||||
}
|
||||
}
|
||||
}, [profile, card, conversation, topic]);
|
||||
|
||||
const actions = {
|
||||
getAssetUrl: (assetId) => {
|
||||
return conversation.actions.getAssetUrl(topic.id, assetId);
|
||||
}
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
@ -2,30 +2,71 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil';
|
||||
|
||||
export async function addChannelTopic(token, channelId, message, assets ) {
|
||||
|
||||
if (assets == null || assets.length == 0) {
|
||||
let subject = { data: JSON.stringify(message, (key, value) => {
|
||||
if (value !== null) return value
|
||||
}), datatype: 'superbasictopic' };
|
||||
|
||||
if (assets == null || assets.length == 0) {
|
||||
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}&confirm=true`,
|
||||
{ method: 'POST', body: JSON.stringify(subject) });
|
||||
checkResponse(topic);
|
||||
}
|
||||
else {
|
||||
|
||||
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics?agent=${token}`,
|
||||
{ method: 'POST', body: JSON.stringify({}) });
|
||||
checkResponse(topic);
|
||||
let slot = await topic.json();
|
||||
|
||||
// add each asset
|
||||
message.assets = [];
|
||||
for (let asset of assets) {
|
||||
if (asset.image) {
|
||||
const formData = new FormData();
|
||||
formData.append('asset', asset.image);
|
||||
let transform = encodeURIComponent(JSON.stringify(["ithumb;photo"]));
|
||||
let transform = encodeURIComponent(JSON.stringify(["ithumb;photo", "icopy;photo"]));
|
||||
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
|
||||
checkResponse(topicAsset);
|
||||
console.log(await topicAsset.json());
|
||||
let assetEntry = await topicAsset.json();
|
||||
message.assets.push({
|
||||
image: {
|
||||
thumb: assetEntry.find(item => item.transform === 'ithumb;photo').assetId,
|
||||
full: assetEntry.find(item => item.transform === 'icopy;photo').assetId,
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (asset.video) {
|
||||
const formData = new FormData();
|
||||
formData.append('asset', asset.video);
|
||||
let transform = encodeURIComponent(JSON.stringify(["vthumb;video", "vcopy;video"]));
|
||||
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
|
||||
checkResponse(topicAsset);
|
||||
let assetEntry = await topicAsset.json();
|
||||
message.assets.push({
|
||||
image: {
|
||||
thumb: assetEntry.find(item => item.transform === 'vthumb;video').assetId,
|
||||
full: assetEntry.find(item => item.transform === 'vcopy;video').assetId,
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (asset.audio) {
|
||||
const formData = new FormData();
|
||||
formData.append('asset', asset.audio);
|
||||
let transform = encodeURIComponent(JSON.stringify(["acopy;audio"]));
|
||||
let topicAsset = await fetch(`/content/channels/${channelId}/topics/${slot.id}/assets?transforms=${transform}&agent=${token}`, { method: 'POST', body: formData });
|
||||
checkResponse(topicAsset);
|
||||
let assetEntry = await topicAsset.json();
|
||||
message.assets.push({
|
||||
image: {
|
||||
full: assetEntry.find(item => item.transform === 'acopy;audio').assetId,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let subject = { data: JSON.stringify(message, (key, value) => {
|
||||
if (value !== null) return value
|
||||
}), datatype: 'superbasictopic' };
|
||||
|
||||
let unconfirmed = await fetchWithTimeout(`/content/channels/${channelId}/topics/${slot.id}/subject?agent=${token}`,
|
||||
{ method: 'PUT', body: JSON.stringify(subject) });
|
||||
|
4
net/web/src/api/getChannelTopicAssetUrl.js
Normal file
4
net/web/src/api/getChannelTopicAssetUrl.js
Normal file
@ -0,0 +1,4 @@
|
||||
export function getChannelTopicAssetUrl(token, channelId, topicId, assetId) {
|
||||
return `/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?agent=${token}`
|
||||
}
|
||||
|
4
net/web/src/api/getContactChannelTopicAssetUrl.js
Normal file
4
net/web/src/api/getContactChannelTopicAssetUrl.js
Normal file
@ -0,0 +1,4 @@
|
||||
export function getContactChannelTopicAssetUrl(server, token, channelId, topicId, assetId) {
|
||||
return `https://${server}/content/channels/${channelId}/topics/${topicId}/assets/${assetId}?contact=${token}`
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import { getCardCloseMessage } from 'api/getCardCloseMessage';
|
||||
import { setCardCloseMessage } from 'api/setCardCloseMessage';
|
||||
import { getContactChannelTopics } from 'api/getContactChannelTopics';
|
||||
import { getContactChannelTopic } from 'api/getContactChannelTopic';
|
||||
import { getContactChannelTopicAssetUrl } from 'api/getContactChannelTopicAssetUrl';
|
||||
import { addCard } from 'api/addCard';
|
||||
import { removeCard } from 'api/removeCard';
|
||||
|
||||
@ -249,6 +250,12 @@ export function useCardContext() {
|
||||
setCardCloseMessage: async (server, message) => {
|
||||
return await setCardCloseMessage(server, message);
|
||||
},
|
||||
getContactChannelTopicAssetUrl: (cardId, channelId, topicId, assetId) => {
|
||||
let card = cards.current.get(cardId);
|
||||
let node = card.data.cardProfile.node;
|
||||
let token = card.data.cardProfile.guid + "." + card.data.cardDetail.token;
|
||||
return getContactChannelTopicAssetUrl(node, token, channelId, topicId, assetId);
|
||||
}
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
|
@ -5,6 +5,7 @@ import { addChannel } from 'api/addChannel';
|
||||
import { addChannelTopic } from 'api/addChannelTopic';
|
||||
import { getChannelTopics } from 'api/getChannelTopics';
|
||||
import { getChannelTopic } from 'api/getChannelTopic';
|
||||
import { getChannelTopicAssetUrl } from 'api/getChannelTopicAssetUrl';
|
||||
|
||||
export function useChannelContext() {
|
||||
const [state, setState] = useState({
|
||||
@ -91,6 +92,9 @@ export function useChannelContext() {
|
||||
getChannelTopic: async (channelId, topicId) => {
|
||||
return await getChannelTopic(access.current, channelId, topicId);
|
||||
},
|
||||
getChannelTopicAssetUrl: (channelId, topicId, assetId) => {
|
||||
return getChannelTopicAssetUrl(access.current, channelId, topicId, assetId);
|
||||
}
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
|
@ -13,6 +13,7 @@ export function useConversationContext() {
|
||||
const channel = useContext(ChannelContext);
|
||||
const topics = useRef(new Map());
|
||||
const revision = useRef(null);
|
||||
const count = useRef(0);
|
||||
const conversationId = useRef(null);
|
||||
|
||||
const updateState = (value) => {
|
||||
@ -26,7 +27,6 @@ export function useConversationContext() {
|
||||
let rev = card.actions.getChannelRevision(cardId, channelId);
|
||||
if (revision.current != rev) {
|
||||
let delta = await card.actions.getChannelTopics(cardId, channelId, revision.current);
|
||||
console.log(delta);
|
||||
for (let topic of delta) {
|
||||
if (topic.data == null) {
|
||||
topics.current.delete(topic.id);
|
||||
@ -37,7 +37,7 @@ export function useConversationContext() {
|
||||
cur = { id: topic.id, data: {} };
|
||||
}
|
||||
if (topic.data.detailRevision != cur.data.detailRevision) {
|
||||
if(topic.data.topicDetail != null) {
|
||||
if(topic.data.topicDetail) {
|
||||
cur.data.topicDetail = topic.data.topicDetail;
|
||||
cur.data.detailRevision = topic.data.detailRevision;
|
||||
}
|
||||
@ -108,12 +108,21 @@ export function useConversationContext() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count.current == 0) {
|
||||
count.current += 1;
|
||||
while(count.current > 0) {
|
||||
try {
|
||||
setTopics();
|
||||
await setTopics();
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
count.current -= 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
count.current += 1;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -129,6 +138,15 @@ export function useConversationContext() {
|
||||
topics.current = new Map();
|
||||
updateState({ init: false, topics: topics.current });
|
||||
updateConversation();
|
||||
},
|
||||
getAssetUrl: (topicId, assetId) => {
|
||||
const { cardId, channelId } = conversationId.current;
|
||||
if (conversationId.current.cardId) {
|
||||
return card.actions.getContactChannelTopicAssetUrl(cardId, channelId, topicId, assetId);
|
||||
}
|
||||
else {
|
||||
return channel.actions.getChannelTopicAssetUrl(channelId, topicId, assetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user