added background for post pinning and logic to edit others posts

This commit is contained in:
csoler 2018-08-12 15:30:07 +02:00
parent ded9c21617
commit 5b1c150acb
No known key found for this signature in database
GPG Key ID: 7BCA522266C0804C
8 changed files with 129 additions and 49 deletions

View File

@ -43,7 +43,11 @@ class RsGxsForumGroup
public: public:
RsGroupMetaData mMeta; RsGroupMetaData mMeta;
std::string mDescription; std::string mDescription;
RsTlvGxsIdSet mAdminList; // this is optional, and handled by the serialiser
// What's below is optional, and handled by the serialiser
RsTlvGxsIdSet mAdminList;
RsTlvGxsMsgIdSet mPinnedPosts;
}; };
class RsGxsForumMsg class RsGxsForumMsg

View File

@ -53,12 +53,13 @@ void RsGxsForumGroupItem::serial_process(RsGenericSerializer::SerializeJob j,RsG
{ {
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,mGroup.mDescription,"mGroup.Description"); RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR,mGroup.mDescription,"mGroup.Description");
// image is optional // This is for backward compatibility: normally all members are serialized, but in the previous version, these members are missing.
if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize) if(j == RsGenericSerializer::DESERIALIZE && ctx.mOffset == ctx.mSize)
return ; return ;
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,mGroup.mAdminList,"admin_list") ; RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,mGroup.mAdminList ,"admin_list" ) ;
RsTypeSerializer::serial_process<RsTlvItem>(j,ctx,mGroup.mPinnedPosts,"pinned_posts") ;
} }
void RsGxsForumMsgItem::clear() void RsGxsForumMsgItem::clear()

View File

@ -205,6 +205,7 @@ const uint16_t TLV_TYPE_RECOGNSET = 0x1024;
const uint16_t TLV_TYPE_GXSIDSET = 0x1025; const uint16_t TLV_TYPE_GXSIDSET = 0x1025;
const uint16_t TLV_TYPE_GXSCIRCLEIDSET= 0x1026; const uint16_t TLV_TYPE_GXSCIRCLEIDSET= 0x1026;
const uint16_t TLV_TYPE_NODEGROUPIDSET= 0x1027; const uint16_t TLV_TYPE_NODEGROUPIDSET= 0x1027;
const uint16_t TLV_TYPE_GXSMSGIDSET = 0x1028;
const uint16_t TLV_TYPE_SERVICESET = 0x1030; const uint16_t TLV_TYPE_SERVICESET = 0x1030;

View File

@ -118,12 +118,13 @@ template<class ID_CLASS,uint32_t TLV_TYPE> class t_RsTlvIdSet: public RsTlvItem
std::set<ID_CLASS> ids ; std::set<ID_CLASS> ids ;
}; };
typedef t_RsTlvIdSet<RsPeerId, TLV_TYPE_PEERSET> RsTlvPeerIdSet ; typedef t_RsTlvIdSet<RsPeerId, TLV_TYPE_PEERSET> RsTlvPeerIdSet ;
typedef t_RsTlvIdSet<RsPgpId, TLV_TYPE_PGPIDSET> RsTlvPgpIdSet ; typedef t_RsTlvIdSet<RsPgpId, TLV_TYPE_PGPIDSET> RsTlvPgpIdSet ;
typedef t_RsTlvIdSet<Sha1CheckSum, TLV_TYPE_HASHSET> RsTlvHashSet ; typedef t_RsTlvIdSet<Sha1CheckSum, TLV_TYPE_HASHSET> RsTlvHashSet ;
typedef t_RsTlvIdSet<RsGxsId, TLV_TYPE_GXSIDSET> RsTlvGxsIdSet ; typedef t_RsTlvIdSet<RsGxsId, TLV_TYPE_GXSIDSET> RsTlvGxsIdSet ;
typedef t_RsTlvIdSet<RsGxsCircleId,TLV_TYPE_GXSCIRCLEIDSET> RsTlvGxsCircleIdSet ; typedef t_RsTlvIdSet<RsGxsMessageId,TLV_TYPE_GXSMSGIDSET> RsTlvGxsMsgIdSet ;
typedef t_RsTlvIdSet<RsNodeGroupId,TLV_TYPE_NODEGROUPIDSET> RsTlvNodeGroupIdSet ; typedef t_RsTlvIdSet<RsGxsCircleId, TLV_TYPE_GXSCIRCLEIDSET> RsTlvGxsCircleIdSet ;
typedef t_RsTlvIdSet<RsNodeGroupId, TLV_TYPE_NODEGROUPIDSET> RsTlvNodeGroupIdSet ;
class RsTlvServiceIdSet: public RsTlvItem class RsTlvServiceIdSet: public RsTlvItem
{ {

View File

@ -1539,7 +1539,7 @@ void SharedFilesDialog::FilterItems()
if(text.length() < 3) if(text.length() < 3)
return ; return ;
FileSearchFlags flags = isRemote()?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL; //FileSearchFlags flags = isRemote()?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL;
QStringList lst = text.split(" ",QString::SkipEmptyParts) ; QStringList lst = text.split(" ",QString::SkipEmptyParts) ;
std::list<std::string> keywords ; std::list<std::string> keywords ;

View File

@ -116,6 +116,7 @@ bool GxsForumGroupDialog::service_EditGroup(uint32_t &token, RsGroupMetaData &ed
RsGxsForumGroup grp; RsGxsForumGroup grp;
grp.mMeta = editedMeta; grp.mMeta = editedMeta;
grp.mDescription = getDescription().toUtf8().constData(); grp.mDescription = getDescription().toUtf8().constData();
getSelectedModerators(grp.mAdminList.ids);
std::cerr << "GxsForumGroupDialog::service_EditGroup() submitting changes"; std::cerr << "GxsForumGroupDialog::service_EditGroup() submitting changes";
std::cerr << std::endl; std::cerr << std::endl;

View File

@ -592,6 +592,21 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
RsGxsId author_id; RsGxsId author_id;
if(gxsIdItem && gxsIdItem->getId(author_id) && rsIdentity->isOwnId(author_id)) if(gxsIdItem && gxsIdItem->getId(author_id) && rsIdentity->isOwnId(author_id))
contextMnu.addAction(editAct); contextMnu.addAction(editAct);
else
{
// Go through the list of own ids and see if one of them is a moderator
// TODO: offer to select which moderator ID to use if multiple IDs fit the conditions of the forum
std::list<RsGxsId> own_ids ;
rsIdentity->getOwnIds(own_ids) ;
for(auto it(own_ids.begin());it!=own_ids.end();++it)
if(mForumGroup.mAdminList.ids.find(author_id) != mForumGroup.mAdminList.ids.end())
{
contextMnu.addAction(editAct);
break ;
}
}
} }
contextMnu.addAction(replyAct); contextMnu.addAction(replyAct);
@ -946,6 +961,10 @@ static QString getDurationString(uint32_t days)
else if(IS_GROUP_PGP_AUTHED(tw->mSignFlags)) anti_spam_features1 = tr("Anonymous posts forwarded if reputation is positive"); else if(IS_GROUP_PGP_AUTHED(tw->mSignFlags)) anti_spam_features1 = tr("Anonymous posts forwarded if reputation is positive");
tw->mForumDescription = QString("<b>%1: \t</b>%2<br/>").arg(tr("Forum name"), QString::fromUtf8( group.mMeta.mGroupName.c_str())); tw->mForumDescription = QString("<b>%1: \t</b>%2<br/>").arg(tr("Forum name"), QString::fromUtf8( group.mMeta.mGroupName.c_str()));
tw->mForumDescription += QString("<b>%1: </b>%2<br/>").arg(tr("Description"),
group.mDescription.empty()?
tr("[None]<br/>")
:(QString::fromUtf8(group.mDescription.c_str())+"<br/>"));
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Subscribers")).arg(group.mMeta.mPop); tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Subscribers")).arg(group.mMeta.mPop);
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Posts (at neighbor nodes)")).arg(group.mMeta.mVisibleMsgCount); tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Posts (at neighbor nodes)")).arg(group.mMeta.mVisibleMsgCount);
if(group.mMeta.mLastPost==0) if(group.mMeta.mLastPost==0)
@ -997,16 +1016,26 @@ static QString getDurationString(uint32_t days)
if(!anti_spam_features1.isNull()) if(!anti_spam_features1.isNull())
tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Anti-spam")).arg(anti_spam_features1); tw->mForumDescription += QString("<b>%1: \t</b>%2<br/>").arg(tr("Anti-spam")).arg(anti_spam_features1);
tw->mForumDescription += QString("<b>%1: </b><br/><br/>%2").arg(tr("Description"), QString::fromUtf8(group.mDescription.c_str()));
tw->ui->subscribeToolButton->setSubscribed(IS_GROUP_SUBSCRIBED(tw->mSubscribeFlags)); tw->ui->subscribeToolButton->setSubscribed(IS_GROUP_SUBSCRIBED(tw->mSubscribeFlags));
tw->mStateHelper->setWidgetEnabled(tw->ui->newthreadButton, (IS_GROUP_SUBSCRIBED(tw->mSubscribeFlags))); tw->mStateHelper->setWidgetEnabled(tw->ui->newthreadButton, (IS_GROUP_SUBSCRIBED(tw->mSubscribeFlags)));
if (tw->mThreadId.isNull() && !tw->mStateHelper->isLoading(tw->mTokenTypeMessageData)) if(!group.mAdminList.ids.empty())
{ {
//ui->threadTitle->setText(tr("Forum Description")); QString admin_list_str ;
tw->ui->postText->setText(tw->mForumDescription);
for(auto it(group.mAdminList.ids.begin());it!=group.mAdminList.ids.end();++it)
{
RsIdentityDetails det ;
rsIdentity->getIdDetails(*it,det);
admin_list_str += (admin_list_str.isNull()?"":", ") + QString::fromUtf8(det.mNickname.c_str()) ;
}
tw->mForumDescription += QString("<b>%1: </b>%2").arg(tr("Moderators"), admin_list_str);
} }
if (tw->mThreadId.isNull() && !tw->mStateHelper->isLoading(tw->mTokenTypeMessageData))
tw->ui->postText->setText(tw->mForumDescription);
} }
void GxsForumThreadWidget::fillThreadFinished() void GxsForumThreadWidget::fillThreadFinished()

View File

@ -94,57 +94,101 @@ static bool decreasing_time_comp(const QPair<time_t,RsGxsMessageId>& e1,const QP
void GxsForumsFillThread::run() void GxsForumsFillThread::run()
{ {
RsTokenService *service = rsGxsForums->getTokenService(); RsTokenService *service = rsGxsForums->getTokenService();
uint32_t msg_token;
uint32_t grp_token;
emit status(tr("Waiting")); emit status(tr("Waiting"));
/* get all messages of the forum */ {
RsTokReqOptions opts; /* get all messages of the forum */
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA; RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
std::list<RsGxsGroupId> grpIds; std::list<RsGxsGroupId> grpIds;
grpIds.push_back(mForumId); grpIds.push_back(mForumId);
#ifdef DEBUG_FORUMS #ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() forum id " << mForumId << std::endl; std::cerr << "GxsForumsFillThread::run() forum id " << mForumId << std::endl;
#endif #endif
uint32_t token; service->requestMsgInfo(msg_token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds);
service->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds);
/* wait for the answer */ /* wait for the answer */
uint32_t requestStatus = RsTokenService::GXS_REQUEST_V2_STATUS_PENDING; uint32_t requestStatus = RsTokenService::GXS_REQUEST_V2_STATUS_PENDING;
while (!wasStopped()) { while (!wasStopped()) {
requestStatus = service->requestStatus(token); requestStatus = service->requestStatus(msg_token);
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED || if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED ||
requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) { requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) {
break; break;
}
msleep(200);
} }
msleep(100);
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
return;
} }
if (wasStopped()) { // also get the forum meta data.
{
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
std::list<RsGxsGroupId> grpIds;
grpIds.push_back(mForumId);
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() forum id " << mForumId << std::endl;
#endif
service->requestGroupInfo(grp_token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds);
/* wait for the answer */
uint32_t requestStatus = RsTokenService::GXS_REQUEST_V2_STATUS_PENDING;
while (!wasStopped()) {
requestStatus = service->requestStatus(grp_token);
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED ||
requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) {
break;
}
msleep(200);
}
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED)
return;
}
if (wasStopped())
{
#ifdef DEBUG_FORUMS #ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() thread stopped, cancel request" << std::endl; std::cerr << "GxsForumsFillThread::run() thread stopped, cancel request" << std::endl;
#endif #endif
/* cancel request */ /* cancel request */
service->cancelRequest(token); service->cancelRequest(msg_token);
service->cancelRequest(grp_token);
return; return;
} }
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) {
//#TODO
return;
}
//#TODO
// if (failed) {
// mService->cancelRequest(token);
// return;
// }
emit status(tr("Retrieving")); emit status(tr("Retrieving"));
std::vector<RsGxsForumGroup> forum_groups;
if (!rsGxsForums->getGroupData(grp_token, forum_groups) || forum_groups.size() != 1)
return;
RsGxsForumGroup forum_group = *forum_groups.begin();
//#ifdef DEBUG_FORUMS
std::cerr << "Retrieved group data: " << std::endl;
std::cerr << " Group ID: " << forum_group.mMeta.mGroupId << std::endl;
std::cerr << " Admin lst: " << forum_group.mAdminList.ids.size() << " elements." << std::endl;
for(auto it(forum_group.mAdminList.ids.begin());it!=forum_group.mAdminList.ids.end();++it)
std::cerr << " " << *it << std::endl;
std::cerr << " Pinned Post: " << forum_group.mPinnedPosts.ids.size() << " messages." << std::endl;
for(auto it(forum_group.mPinnedPosts.ids.begin());it!=forum_group.mPinnedPosts.ids.end();++it)
std::cerr << " " << *it << std::endl;
//#endif
/* get messages */ /* get messages */
std::map<RsGxsMessageId,RsGxsForumMsg> msgs; std::map<RsGxsMessageId,RsGxsForumMsg> msgs;
@ -152,9 +196,8 @@ void GxsForumsFillThread::run()
std::vector<RsGxsForumMsg> msgs_array; std::vector<RsGxsForumMsg> msgs_array;
if (!rsGxsForums->getMsgData(token, msgs_array)) { if (!rsGxsForums->getMsgData(msg_token, msgs_array))
return; return;
}
// now put everything into a map in order to make search log(n) // now put everything into a map in order to make search log(n)
@ -209,10 +252,10 @@ void GxsForumsFillThread::run()
if(msgIt2 == msgs.end()) if(msgIt2 == msgs.end())
continue ; continue ;
// Make sure that the author is the same than the original message. This should always happen, but nothing can prevent someone to // Make sure that the author is the same than the original message, or is a moderator. This should always happen when messages are constructed using
// craft a new version of a message with his own signature. // the UI but nothing can prevent a nasty user to craft a new version of a message with his own signature.
if(msgIt2->second.mMeta.mAuthorId != msgIt->second.mMeta.mAuthorId) if(msgIt2->second.mMeta.mAuthorId != msgIt->second.mMeta.mAuthorId && forum_group.mAdminList.ids.find(msgIt->second.mMeta.mAuthorId)==forum_group.mAdminList.ids.end())
continue ; continue ;
// always add the post a self version // always add the post a self version