mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
Merge remote-tracking branch g1o/qml_app_identity_avatar into qml_app_chat_aesthetic
This commit is contained in:
commit
ca3a0bd2d1
@ -16,6 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QStringList>
|
||||
#include "ApiServerLocal.h"
|
||||
#include "JsonStream.h"
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <retroshare/rsidentity.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <util/radix64.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "Operators.h"
|
||||
@ -500,6 +501,11 @@ void IdentityHandler::handleGetIdentityDetails(Request& req, Response& resp)
|
||||
|
||||
RsIdentityDetails details;
|
||||
mRsIdentity->getIdDetails(RsGxsId(data.mMeta.mGroupId), details);
|
||||
|
||||
std::string base64Avatar;
|
||||
Radix64::encode(details.mAvatar.mData, details.mAvatar.mSize, base64Avatar);
|
||||
resp.mDataStream << makeKeyValue("avatar", base64Avatar);
|
||||
|
||||
StreamBase& usagesStream = resp.mDataStream.getStreamToMember("usages");
|
||||
usagesStream.getStreamToMember();
|
||||
|
||||
|
@ -169,6 +169,12 @@ class p3ChatService::AvatarInfo
|
||||
|
||||
void toUnsignedChar(unsigned char *& data,uint32_t& size) const
|
||||
{
|
||||
if(_image_size == 0)
|
||||
{
|
||||
size = 0 ;
|
||||
data = NULL ;
|
||||
return ;
|
||||
}
|
||||
data = (unsigned char *)rs_malloc(_image_size) ;
|
||||
size = _image_size ;
|
||||
memcpy(data,_image_data,size*sizeof(unsigned char)) ;
|
||||
|
@ -190,52 +190,54 @@ void RsGenExchange::tick()
|
||||
now = time(NULL);
|
||||
if(mChecking || (mLastCheck + INTEGRITY_CHECK_PERIOD < now))
|
||||
{
|
||||
if(mIntegrityCheck)
|
||||
mLastCheck = time(NULL);
|
||||
|
||||
{
|
||||
if(mIntegrityCheck->isDone())
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
|
||||
if(!mIntegrityCheck)
|
||||
{
|
||||
std::list<RsGxsGroupId> grpIds;
|
||||
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgIds;
|
||||
mIntegrityCheck->getDeletedIds(grpIds, msgIds);
|
||||
|
||||
if (!grpIds.empty())
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
|
||||
RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, false);
|
||||
gc->mGrpIdList = grpIds;
|
||||
#ifdef GEN_EXCH_DEBUG
|
||||
std::cerr << " adding the following grp ids to notification: " << std::endl;
|
||||
for(std::list<RsGxsGroupId>::const_iterator it(grpIds.begin());it!=grpIds.end();++it)
|
||||
std::cerr << " " << *it << std::endl;
|
||||
#endif
|
||||
mNotifications.push_back(gc);
|
||||
|
||||
// also notify the network exchange service that these groups no longer exist.
|
||||
|
||||
if(mNetService)
|
||||
mNetService->removeGroups(grpIds) ;
|
||||
}
|
||||
|
||||
if (!msgIds.empty()) {
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
|
||||
RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, false);
|
||||
c->msgChangeMap = msgIds;
|
||||
mNotifications.push_back(c);
|
||||
}
|
||||
|
||||
delete mIntegrityCheck;
|
||||
mIntegrityCheck = NULL;
|
||||
mLastCheck = time(NULL);
|
||||
mChecking = false;
|
||||
mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore,this,mGixs);
|
||||
mIntegrityCheck->start("gxs integrity");
|
||||
mChecking = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if(mIntegrityCheck->isDone())
|
||||
{
|
||||
mIntegrityCheck = new RsGxsIntegrityCheck(mDataStore,this,mGixs);
|
||||
mIntegrityCheck->start("gxs integrity");
|
||||
mChecking = true;
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
|
||||
std::list<RsGxsGroupId> grpIds;
|
||||
std::map<RsGxsGroupId, std::vector<RsGxsMessageId> > msgIds;
|
||||
mIntegrityCheck->getDeletedIds(grpIds, msgIds);
|
||||
|
||||
if (!grpIds.empty())
|
||||
{
|
||||
RsGxsGroupChange* gc = new RsGxsGroupChange(RsGxsNotify::TYPE_PROCESSED, false);
|
||||
gc->mGrpIdList = grpIds;
|
||||
#ifdef GEN_EXCH_DEBUG
|
||||
std::cerr << " adding the following grp ids to notification: " << std::endl;
|
||||
for(std::list<RsGxsGroupId>::const_iterator it(grpIds.begin());it!=grpIds.end();++it)
|
||||
std::cerr << " " << *it << std::endl;
|
||||
#endif
|
||||
mNotifications.push_back(gc);
|
||||
|
||||
// also notify the network exchange service that these groups no longer exist.
|
||||
|
||||
if(mNetService)
|
||||
mNetService->removeGroups(grpIds) ;
|
||||
}
|
||||
|
||||
if (!msgIds.empty())
|
||||
{
|
||||
RsGxsMsgChange* c = new RsGxsMsgChange(RsGxsNotify::TYPE_PROCESSED, false);
|
||||
c->msgChangeMap = msgIds;
|
||||
mNotifications.push_back(c);
|
||||
}
|
||||
|
||||
delete mIntegrityCheck;
|
||||
mIntegrityCheck = NULL;
|
||||
mChecking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1752,8 +1754,18 @@ void RsGenExchange::deleteGroup(uint32_t& token, const RsGxsGroupId& grpId)
|
||||
}
|
||||
void RsGenExchange::deleteMsgs(uint32_t& token, const GxsMsgReq& msgs)
|
||||
{
|
||||
RS_STACK_MUTEX(mGenMtx) ;
|
||||
|
||||
token = mDataAccess->generatePublicToken();
|
||||
mMsgDeletePublish.push_back(MsgDeletePublish(msgs, token));
|
||||
|
||||
// This code below will suspend any requests of the deleted messages for 24 hrs. This of course only works
|
||||
// if all friend nodes consistently delete the messages in the mean time.
|
||||
|
||||
if(mNetService != NULL)
|
||||
for(GxsMsgReq::const_iterator it(msgs.begin());it!=msgs.end();++it)
|
||||
for(uint32_t i=0;i<it->second.size();++i)
|
||||
mNetService->rejectMessage(it->second[i]) ;
|
||||
}
|
||||
|
||||
void RsGenExchange::publishMsg(uint32_t& token, RsGxsMsgItem *msgItem)
|
||||
@ -2900,8 +2912,12 @@ void RsGenExchange::processRecvdMessages()
|
||||
std::cerr << " deserialised info: grp id=" << meta->mGroupId << ", msg id=" << meta->mMsgId ;
|
||||
#endif
|
||||
uint8_t validateReturn = VALIDATE_FAIL;
|
||||
bool accept_new_msg = acceptNewMessage(meta,msg->msg.bin_len);
|
||||
|
||||
if(ok)
|
||||
if(!accept_new_msg && mNetService != NULL)
|
||||
mNetService->rejectMessage(meta->mMsgId) ; // This prevents reloading the message again at next sync.
|
||||
|
||||
if(ok && accept_new_msg)
|
||||
{
|
||||
std::map<RsGxsGroupId, RsGxsGrpMetaData*>::iterator mit = grpMetas.find(msg->grpId);
|
||||
|
||||
@ -3042,8 +3058,8 @@ void RsGenExchange::processRecvdMessages()
|
||||
mNetService->rejectMessage(*it) ;
|
||||
}
|
||||
|
||||
bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ )
|
||||
{ return true; }
|
||||
bool RsGenExchange::acceptNewGroup(const RsGxsGrpMetaData* /*grpMeta*/ ) { return true; }
|
||||
bool RsGenExchange::acceptNewMessage(const RsGxsMsgMetaData* /*grpMeta*/,uint32_t size ) { return true; }
|
||||
|
||||
void RsGenExchange::processRecvdGroups()
|
||||
{
|
||||
|
@ -260,6 +260,17 @@ public:
|
||||
*/
|
||||
virtual bool acceptNewGroup(const RsGxsGrpMetaData *grpMeta) ;
|
||||
|
||||
/*!
|
||||
* \brief acceptNewMessage
|
||||
* Early checks if the message can be accepted. This is mainly used to check wether the group is for instance overloaded and the service wants
|
||||
* to put limitations to it.
|
||||
* Returns true unless derived in GXS services.
|
||||
*
|
||||
* \param grpMeta Group metadata to check
|
||||
* \return
|
||||
*/
|
||||
virtual bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ;
|
||||
|
||||
bool subscribeToGroup(uint32_t& token, const RsGxsGroupId& grpId, bool subscribe);
|
||||
|
||||
/*!
|
||||
|
@ -268,7 +268,7 @@ static const uint32_t RS_NXS_ITEM_ENCRYPTION_STATUS_GXS_KEY_MISSING = 0x05 ;
|
||||
|
||||
static const RsPeerId peer_to_print = RsPeerId(std::string("")) ;
|
||||
static const RsGxsGroupId group_id_to_print = RsGxsGroupId(std::string("")) ; // use this to allow to this group id only, or "" for all IDs
|
||||
static const uint32_t service_to_print = 0x215 ; // use this to allow to this service id only, or 0 for all services
|
||||
static const uint32_t service_to_print = RS_SERVICE_TYPE_GXS_TRANS ; // use this to allow to this service id only, or 0 for all services
|
||||
// warning. Numbers should be SERVICE IDS (see serialiser/rsserviceids.h. E.g. 0x0215 for forums)
|
||||
|
||||
class nullstream: public std::ostream {};
|
||||
@ -447,6 +447,9 @@ void RsGxsNetService::rejectMessage(const RsGxsMessageId& msg_id)
|
||||
{
|
||||
RS_STACK_MUTEX(mNxsMutex) ;
|
||||
|
||||
#ifdef NXS_NET_DEBUG_0
|
||||
GXSNETDEBUG___ << "adding message " << msg_id << " to rejection list for 24hrs." << std::endl;
|
||||
#endif
|
||||
mRejectedMessages[msg_id] = time(NULL) ;
|
||||
}
|
||||
void RsGxsNetService::cleanRejectedMessages()
|
||||
@ -595,9 +598,9 @@ void RsGxsNetService::syncWithPeers()
|
||||
#ifdef NXS_NET_DEBUG_0
|
||||
GXSNETDEBUG_PG(peerId,grpId) << " peer can send messages for group " << grpId ;
|
||||
if(!encrypt_to_this_circle_id.isNull())
|
||||
std::cerr << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl;
|
||||
GXSNETDEBUG_PG(peerId,grpId) << " request should be encrypted for circle ID " << encrypt_to_this_circle_id << std::endl;
|
||||
else
|
||||
std::cerr << " request should be sent in clear." << std::endl;
|
||||
GXSNETDEBUG_PG(peerId,grpId) << " request should be sent in clear." << std::endl;
|
||||
|
||||
#endif
|
||||
// On default, the info has never been received so the TS is 0, meaning the peer has sent that it had no information.
|
||||
@ -1839,7 +1842,7 @@ void RsGxsNetService::debugDump()
|
||||
GXSNETDEBUG_PG(it->first,it2->first) << " group " << it2->first << " - last updated at peer (secs ago): " << nice_time_stamp(time(NULL),it2->second.time_stamp) << ". Message count=" << it2->second.message_count << std::endl;
|
||||
}
|
||||
|
||||
GXSNETDEBUG___<< " List of rejected message ids: " << mRejectedMessages.size() << std::endl;
|
||||
GXSNETDEBUG___<< " List of rejected message ids: " << std::dec << mRejectedMessages.size() << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -136,6 +136,9 @@ RsGxsIntegrityCheck::RsGxsIntegrityCheck(RsGeneralDataService* const dataService
|
||||
void RsGxsIntegrityCheck::run()
|
||||
{
|
||||
check();
|
||||
|
||||
RsStackMutex stack(mIntegrityMutex);
|
||||
mDone = true;
|
||||
}
|
||||
|
||||
bool RsGxsIntegrityCheck::check()
|
||||
@ -286,71 +289,72 @@ bool RsGxsIntegrityCheck::check()
|
||||
|
||||
mDs->removeMsgs(msgsToDel);
|
||||
|
||||
RsStackMutex stack(mIntegrityMutex);
|
||||
mDone = true;
|
||||
{
|
||||
RsStackMutex stack(mIntegrityMutex);
|
||||
|
||||
std::vector<RsGxsGroupId>::iterator grpIt;
|
||||
for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt)
|
||||
{
|
||||
mDeletedGrps.push_back(*grpIt);
|
||||
}
|
||||
mDeletedMsgs = msgsToDel;
|
||||
std::vector<RsGxsGroupId>::iterator grpIt;
|
||||
for(grpIt = grpsToDel.begin(); grpIt != grpsToDel.end(); ++grpIt)
|
||||
{
|
||||
mDeletedGrps.push_back(*grpIt);
|
||||
}
|
||||
mDeletedMsgs = msgsToDel;
|
||||
|
||||
#ifdef DEBUG_GXSUTIL
|
||||
GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl;
|
||||
GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl;
|
||||
GXSUTIL_DEBUG() << "At end of pass, this is the list used GXS ids: " << std::endl;
|
||||
GXSUTIL_DEBUG() << " requesting them to GXS identity service to enforce loading." << std::endl;
|
||||
#endif
|
||||
|
||||
std::list<RsPeerId> connected_friends ;
|
||||
rsPeers->getOnlineList(connected_friends) ;
|
||||
std::list<RsPeerId> connected_friends ;
|
||||
rsPeers->getOnlineList(connected_friends) ;
|
||||
|
||||
std::vector<std::pair<RsGxsId,RsIdentityUsage> > gxs_ids ;
|
||||
std::vector<std::pair<RsGxsId,RsIdentityUsage> > gxs_ids ;
|
||||
|
||||
for(std::map<RsGxsId,RsIdentityUsage>::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it)
|
||||
{
|
||||
gxs_ids.push_back(*it) ;
|
||||
for(std::map<RsGxsId,RsIdentityUsage>::const_iterator it(used_gxs_ids.begin());it!=used_gxs_ids.end();++it)
|
||||
{
|
||||
gxs_ids.push_back(*it) ;
|
||||
#ifdef DEBUG_GXSUTIL
|
||||
GXSUTIL_DEBUG() << " " << *it << std::endl;
|
||||
GXSUTIL_DEBUG() << " " << *it << std::endl;
|
||||
#endif
|
||||
}
|
||||
uint32_t nb_requested_not_in_cache = 0;
|
||||
}
|
||||
uint32_t nb_requested_not_in_cache = 0;
|
||||
|
||||
#ifdef DEBUG_GXSUTIL
|
||||
GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl;
|
||||
GXSUTIL_DEBUG() << " issuing random get on friends for non existing IDs" << std::endl;
|
||||
#endif
|
||||
|
||||
// now request a cache update for them, which triggers downloading from friends, if missing.
|
||||
// now request a cache update for them, which triggers downloading from friends, if missing.
|
||||
|
||||
for(;nb_requested_not_in_cache<MAX_GXS_IDS_REQUESTS_NET && !gxs_ids.empty();)
|
||||
{
|
||||
uint32_t n = RSRandom::random_u32() % gxs_ids.size() ;
|
||||
for(;nb_requested_not_in_cache<MAX_GXS_IDS_REQUESTS_NET && !gxs_ids.empty();)
|
||||
{
|
||||
uint32_t n = RSRandom::random_u32() % gxs_ids.size() ;
|
||||
#ifdef DEBUG_GXSUTIL
|
||||
GXSUTIL_DEBUG() << " requesting ID " << gxs_ids[n] ;
|
||||
GXSUTIL_DEBUG() << " requesting ID " << gxs_ids[n] ;
|
||||
#endif
|
||||
|
||||
if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
|
||||
{
|
||||
mGixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second);
|
||||
if(!mGixs->haveKey(gxs_ids[n].first)) // checks if we have it already in the cache (conservative way to ensure that we atually have it)
|
||||
{
|
||||
mGixs->requestKey(gxs_ids[n].first,connected_friends,gxs_ids[n].second);
|
||||
|
||||
++nb_requested_not_in_cache ;
|
||||
++nb_requested_not_in_cache ;
|
||||
#ifdef DEBUG_GXSUTIL
|
||||
GXSUTIL_DEBUG() << " ... from cache/net" << std::endl;
|
||||
GXSUTIL_DEBUG() << " ... from cache/net" << std::endl;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_GXSUTIL
|
||||
GXSUTIL_DEBUG() << " ... already in cache" << std::endl;
|
||||
GXSUTIL_DEBUG() << " ... already in cache" << std::endl;
|
||||
#endif
|
||||
}
|
||||
mGixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second);
|
||||
}
|
||||
mGixs->timeStampKey(gxs_ids[n].first,gxs_ids[n].second);
|
||||
|
||||
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
|
||||
gxs_ids.pop_back() ;
|
||||
}
|
||||
gxs_ids[n] = gxs_ids[gxs_ids.size()-1] ;
|
||||
gxs_ids.pop_back() ;
|
||||
}
|
||||
#ifdef DEBUG_GXSUTIL
|
||||
GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl;
|
||||
GXSUTIL_DEBUG() << " total actual cache requests: "<< nb_requested_not_in_cache << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -20,17 +20,20 @@
|
||||
#include "gxstrans/p3gxstrans.h"
|
||||
#include "util/stacktrace.h"
|
||||
|
||||
#define DEBUG_GXSTRANS 1
|
||||
typedef unsigned int uint;
|
||||
|
||||
RsGxsTrans *rsGxsTrans = NULL ;
|
||||
|
||||
const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 900; // every 15 mins. Could be less.
|
||||
|
||||
p3GxsTrans::~p3GxsTrans()
|
||||
{
|
||||
p3Config::saveConfiguration();
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mIngoingMutex);
|
||||
for ( auto& kv : mIngoingQueue ) delete kv.second;
|
||||
for ( auto& kv : mIncomingQueue) delete kv.second;
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,8 +51,8 @@ bool p3GxsTrans::getStatistics(GxsTransStatistics& stats)
|
||||
|
||||
RsGxsTransOutgoingRecord rec ;
|
||||
rec.status = pr.status ;
|
||||
rec.send_TS = pr.mailItem.meta.mPublishTs ;
|
||||
rec.group_id = pr.mailItem.meta.mGroupId ;
|
||||
rec.send_TS = pr.sent_ts ;
|
||||
rec.group_id = pr.group_id ;
|
||||
rec.trans_id = pr.mailItem.mailId ;
|
||||
rec.recipient = pr.recipient ;
|
||||
rec.data_size = pr.mailData.size();
|
||||
@ -69,7 +72,9 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId,
|
||||
const uint8_t* data, uint32_t size,
|
||||
RsGxsTransEncryptionMode cm )
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::sendEmail(...)" << std::endl;
|
||||
#endif
|
||||
|
||||
if(!mIdService.isOwnId(own_gxsid))
|
||||
{
|
||||
@ -89,8 +94,7 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId,
|
||||
OutgoingRecord pr( recipient, service, data, size );
|
||||
|
||||
pr.mailItem.clear();
|
||||
pr.mailItem.meta.mAuthorId = own_gxsid;
|
||||
pr.mailItem.meta.mMsgId.clear();
|
||||
pr.author = own_gxsid; //pr.mailItem.meta.mAuthorId = own_gxsid;
|
||||
pr.mailItem.cryptoType = cm;
|
||||
pr.mailItem.mailId = RSRandom::random_u64();
|
||||
|
||||
@ -100,6 +104,8 @@ bool p3GxsTrans::sendData( RsGxsTransId& mailId,
|
||||
}
|
||||
|
||||
mailId = pr.mailItem.mailId;
|
||||
|
||||
IndicateConfigChanged(); // This causes the saving of the message after all data has been filled in.
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -124,8 +130,11 @@ void p3GxsTrans::registerGxsTransClient(
|
||||
|
||||
void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
|
||||
{
|
||||
std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type
|
||||
<< ")" << std::endl;
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::handleResponse(" << token << ", " << req_type << ")" << std::endl;
|
||||
#endif
|
||||
bool changed = false ;
|
||||
|
||||
switch (req_type)
|
||||
{
|
||||
case GROUPS_LIST:
|
||||
@ -186,8 +195,10 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
|
||||
* avoid to create yet another never used mail distribution group.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "p3GxsTrans::handleResponse(...) preferredGroupId.isNu"
|
||||
<< "ll() let's create a new group." << std::endl;
|
||||
#endif
|
||||
uint32_t token;
|
||||
publishGroup(token, new RsGxsTransGroupItem());
|
||||
queueRequest(token, GROUP_CREATE);
|
||||
@ -197,7 +208,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
|
||||
}
|
||||
case GROUP_CREATE:
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "p3GxsTrans::handleResponse(...) GROUP_CREATE" << std::endl;
|
||||
#endif
|
||||
RsGxsGroupId grpId;
|
||||
acknowledgeTokenGrp(token, grpId);
|
||||
supersedePreferredGroup(grpId);
|
||||
@ -205,7 +218,9 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
|
||||
}
|
||||
case MAILS_UPDATE:
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::handleResponse(...) MAILS_UPDATE" << std::endl;
|
||||
#endif
|
||||
typedef std::map<RsGxsGroupId, std::vector<RsGxsMsgItem*> > GxsMsgDataMap;
|
||||
GxsMsgDataMap gpMsgMap;
|
||||
getMsgData(token, gpMsgMap);
|
||||
@ -222,12 +237,14 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT:
|
||||
{
|
||||
RsGxsTransBaseItem* mb =
|
||||
dynamic_cast<RsGxsTransBaseItem*>(*mIt);
|
||||
RsGxsTransBaseMsgItem* mb = dynamic_cast<RsGxsTransBaseMsgItem*>(*mIt);
|
||||
|
||||
if(mb)
|
||||
{
|
||||
RS_STACK_MUTEX(mIngoingMutex);
|
||||
mIngoingQueue.insert(inMap::value_type(mb->mailId, mb));
|
||||
mIncomingQueue.insert(inMap::value_type(mb->mailId,mb));
|
||||
|
||||
changed = true ;
|
||||
}
|
||||
else
|
||||
std::cerr << "p3GxsTrans::handleResponse(...) "
|
||||
@ -253,6 +270,15 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
|
||||
<< req_type << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if(changed)
|
||||
IndicateConfigChanged();
|
||||
}
|
||||
void p3GxsTrans::GxsTransIntegrityCleanupThread::getPerUserStatistics(std::map<RsGxsId,MsgSizeCount>& m)
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx) ;
|
||||
|
||||
m = total_message_size_and_count ;
|
||||
}
|
||||
|
||||
void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq& m)
|
||||
@ -263,13 +289,33 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::getMessagesToDelete(GxsMsgReq&
|
||||
mMsgToDel.clear();
|
||||
}
|
||||
|
||||
// This method does two things:
|
||||
// 1 - cleaning up old messages and messages for which an ACK has been received.
|
||||
// 2 - building per user statistics across groups. This is important because it allows to mitigate the excess of
|
||||
// messages, which might be due to spam.
|
||||
//
|
||||
// Note: the anti-spam system is disabled the level of GXS, because we want to allow to send anonymous messages
|
||||
// between identities that might not have a reputation yet. Still, messages from identities with a bad reputation
|
||||
// are still deleted by GXS.
|
||||
//
|
||||
// The group limits are enforced according to the following rules:
|
||||
// * a temporal sliding window is computed for each identity and the number of messages signed by this identity is counted
|
||||
// *
|
||||
//
|
||||
//
|
||||
// Deleted messages are notified to the RsGxsNetService part which keeps a list of delete messages so as not to request them again
|
||||
// during the same session. This allows to safely delete messages while avoiding re-synchronisation from friend nodes.
|
||||
|
||||
void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
|
||||
{
|
||||
// first take out all the groups
|
||||
|
||||
std::map<RsGxsGroupId, RsNxsGrp*> grp;
|
||||
mDs->retrieveNxsGrps(grp, true, true);
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "GxsTransIntegrityCleanupThread::run()" << std::endl;
|
||||
#endif
|
||||
|
||||
// compute hash and compare to stored value, if it fails then simply add it
|
||||
// to list
|
||||
@ -287,6 +333,8 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
|
||||
|
||||
// now messages
|
||||
|
||||
std::map<RsGxsId,MsgSizeCount> totalMessageSizeAndCount;
|
||||
|
||||
std::map<RsGxsTransId,std::pair<RsGxsGroupId,RsGxsMessageId> > stored_msgs ;
|
||||
std::list<RsGxsTransId> received_msgs ;
|
||||
|
||||
@ -312,27 +360,41 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
|
||||
std::cerr << " Unrecocognised item type!" << std::endl;
|
||||
else if(NULL != (mitem = dynamic_cast<RsGxsTransMailItem*>(item)))
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << " " << msg->metaData->mMsgId << ": Mail data with ID " << std::hex << std::setfill('0') << std::setw(16) << mitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl;
|
||||
#endif
|
||||
|
||||
stored_msgs[mitem->mailId] = std::make_pair(msg->metaData->mGroupId,msg->metaData->mMsgId) ;
|
||||
}
|
||||
else if(NULL != (pitem = dynamic_cast<RsGxsTransPresignedReceipt*>(item)))
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << " " << msg->metaData->mMsgId << ": Signed rcpt of ID " << std::hex << pitem->mailId << std::dec << " from " << msg->metaData->mAuthorId << " size: " << msg->msg.bin_len << std::endl;
|
||||
#endif
|
||||
|
||||
received_msgs.push_back(pitem->mailId) ;
|
||||
}
|
||||
else
|
||||
std::cerr << " Unknown item type!" << std::endl;
|
||||
|
||||
totalMessageSizeAndCount[msg->metaData->mAuthorId].size += msg->msg.bin_len ;
|
||||
totalMessageSizeAndCount[msg->metaData->mAuthorId].count++;
|
||||
delete msg;
|
||||
}
|
||||
}
|
||||
|
||||
// From the collected information, build a list of group messages to delete.
|
||||
|
||||
GxsMsgReq msgsToDel ;
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "Msg removal report:" << std::endl;
|
||||
|
||||
std::cerr << " Per user size and count: " << std::endl;
|
||||
for(std::map<RsGxsId,MsgSizeCount>::const_iterator it(totalMessageSizeAndCount.begin());it!=totalMessageSizeAndCount.end();++it)
|
||||
std::cerr << " " << it->first << ": " << it->second.count << " messages, for a total size of " << it->second.size << " bytes." << std::endl;
|
||||
#endif
|
||||
|
||||
for(std::list<RsGxsTransId>::const_iterator it(received_msgs.begin());it!=received_msgs.end();++it)
|
||||
{
|
||||
std::map<RsGxsTransId,std::pair<RsGxsGroupId,RsGxsMessageId> >::const_iterator it2 = stored_msgs.find(*it) ;
|
||||
@ -341,22 +403,33 @@ void p3GxsTrans::GxsTransIntegrityCleanupThread::run()
|
||||
{
|
||||
msgsToDel[it2->second.first].push_back(it2->second.second);
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << " scheduling msg " << std::hex << it2->second.first << "," << it2->second.second << " for deletion." << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
RS_STACK_MUTEX(mMtx) ;
|
||||
mMsgToDel = msgsToDel ;
|
||||
total_message_size_and_count = totalMessageSizeAndCount;
|
||||
mDone = true;
|
||||
}
|
||||
|
||||
bool p3GxsTrans::GxsTransIntegrityCleanupThread::isDone()
|
||||
{
|
||||
RS_STACK_MUTEX(mMtx) ;
|
||||
return mDone ;
|
||||
}
|
||||
void p3GxsTrans::service_tick()
|
||||
{
|
||||
GxsTokenQueue::checkRequests();
|
||||
|
||||
time_t now = time(NULL);
|
||||
bool changed = false ;
|
||||
|
||||
if(mLastMsgCleanup + MAX_DELAY_BETWEEN_CLEANUPS < now)
|
||||
{
|
||||
RS_STACK_MUTEX(mPerUserStatsMutex);
|
||||
if(!mCleanupThread)
|
||||
mCleanupThread = new GxsTransIntegrityCleanupThread(getDataStore());
|
||||
|
||||
@ -364,7 +437,9 @@ void p3GxsTrans::service_tick()
|
||||
std::cerr << "Cleanup thread is already running. Not running it again!" << std::endl;
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "Starting GxsIntegrity cleanup thread." << std::endl;
|
||||
#endif
|
||||
|
||||
mCleanupThread->start() ;
|
||||
mLastMsgCleanup = now ;
|
||||
@ -373,17 +448,32 @@ void p3GxsTrans::service_tick()
|
||||
|
||||
// now grab collected messages to delete
|
||||
|
||||
if(mCleanupThread != NULL && !mCleanupThread->isRunning())
|
||||
if(mCleanupThread != NULL && mCleanupThread->isDone())
|
||||
{
|
||||
RS_STACK_MUTEX(mPerUserStatsMutex);
|
||||
GxsMsgReq msgToDel ;
|
||||
|
||||
mCleanupThread->getMessagesToDelete(msgToDel) ;
|
||||
|
||||
if(!msgToDel.empty())
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "p3GxsTrans::service_tick(): deleting messages." << std::endl;
|
||||
getDataStore()->removeMsgs(msgToDel);
|
||||
#endif
|
||||
uint32_t token ;
|
||||
deleteMsgs(token,msgToDel);
|
||||
}
|
||||
|
||||
mCleanupThread->getPerUserStatistics(per_user_statistics) ;
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "p3GxsTrans: Got new set of per user statistics:"<< std::endl;
|
||||
for(std::map<RsGxsId,MsgSizeCount>::const_iterator it(per_user_statistics.begin());it!=per_user_statistics.end();++it)
|
||||
std::cerr << " " << it->first << ": " << it->second.count << " " << it->second.size << std::endl;
|
||||
#endif
|
||||
|
||||
delete mCleanupThread;
|
||||
mCleanupThread=NULL ;
|
||||
}
|
||||
|
||||
{
|
||||
@ -392,10 +482,15 @@ void p3GxsTrans::service_tick()
|
||||
{
|
||||
OutgoingRecord& pr(it->second);
|
||||
GxsTransSendStatus oldStatus = pr.status;
|
||||
processOutgoingRecord(pr);
|
||||
|
||||
locked_processOutgoingRecord(pr);
|
||||
|
||||
if (oldStatus != pr.status) notifyClientService(pr);
|
||||
if( pr.status >= GxsTransSendStatus::RECEIPT_RECEIVED )
|
||||
{
|
||||
it = mOutgoingQueue.erase(it);
|
||||
changed = true ;
|
||||
}
|
||||
else ++it;
|
||||
}
|
||||
}
|
||||
@ -403,15 +498,14 @@ void p3GxsTrans::service_tick()
|
||||
|
||||
{
|
||||
RS_STACK_MUTEX(mIngoingMutex);
|
||||
for( auto it = mIngoingQueue.begin(); it != mIngoingQueue.end(); )
|
||||
for( auto it = mIncomingQueue.begin(); it != mIncomingQueue.end(); )
|
||||
{
|
||||
switch(static_cast<GxsTransItemsSubtypes>(
|
||||
it->second->PacketSubType()))
|
||||
switch(static_cast<GxsTransItemsSubtypes>( it->second->PacketSubType()))
|
||||
{
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
|
||||
{
|
||||
RsGxsTransMailItem* msg =
|
||||
dynamic_cast<RsGxsTransMailItem*>(it->second);
|
||||
RsGxsTransMailItem* msg = dynamic_cast<RsGxsTransMailItem*>(it->second);
|
||||
|
||||
if(!msg)
|
||||
{
|
||||
std::cerr << "p3GxsTrans::service_tick() (EE) "
|
||||
@ -421,6 +515,7 @@ void p3GxsTrans::service_tick()
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::service_tick() "
|
||||
<< "GXS_MAIL_SUBTYPE_MAIL handling: "
|
||||
<< msg->meta.mMsgId
|
||||
@ -430,14 +525,15 @@ void p3GxsTrans::service_tick()
|
||||
<< " mailId: "<< msg->mailId
|
||||
<< " payload.size(): " << msg->payload.size()
|
||||
<< std::endl;
|
||||
#endif
|
||||
handleEncryptedMail(msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT:
|
||||
{
|
||||
RsGxsTransPresignedReceipt* rcpt =
|
||||
dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
|
||||
RsGxsTransPresignedReceipt* rcpt = dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
|
||||
|
||||
if(!rcpt)
|
||||
{
|
||||
std::cerr << "p3GxsTrans::service_tick() (EE) "
|
||||
@ -467,22 +563,31 @@ void p3GxsTrans::service_tick()
|
||||
break;
|
||||
}
|
||||
|
||||
delete it->second; it = mIngoingQueue.erase(it);
|
||||
delete it->second ;
|
||||
it = mIncomingQueue.erase(it);
|
||||
changed = true ;
|
||||
}
|
||||
}
|
||||
|
||||
if(changed)
|
||||
IndicateConfigChanged();
|
||||
}
|
||||
|
||||
RsGenExchange::ServiceCreate_Return p3GxsTrans::service_CreateGroup(
|
||||
RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& /*keySet*/ )
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::service_CreateGroup(...) "
|
||||
<< grpItem->meta.mGroupId << std::endl;
|
||||
#endif
|
||||
return SERVICE_CREATE_SUCCESS;
|
||||
}
|
||||
|
||||
void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::notifyChanges(...)" << std::endl;
|
||||
#endif
|
||||
for( std::vector<RsGxsNotify*>::const_iterator it = changes.begin();
|
||||
it != changes.end(); ++it )
|
||||
{
|
||||
@ -491,12 +596,16 @@ void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
|
||||
|
||||
if (grpChange)
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::notifyChanges(...) grpChange" << std::endl;
|
||||
#endif
|
||||
requestGroupsData(&(grpChange->mGrpIdList));
|
||||
}
|
||||
else if(msgChange)
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::notifyChanges(...) msgChange" << std::endl;
|
||||
#endif
|
||||
uint32_t token;
|
||||
RsTokReqOptions opts; opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||
RsGenExchange::getTokenService()->requestMsgInfo( token, 0xcaca,
|
||||
@ -512,13 +621,16 @@ void p3GxsTrans::notifyChanges(std::vector<RsGxsNotify*>& changes)
|
||||
for(itT vit = msgsIds.begin(); vit != msgsIds.end(); ++vit)
|
||||
{
|
||||
const RsGxsMessageId& msgId = *vit;
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::notifyChanges(...) got "
|
||||
<< "notification for message " << msgId
|
||||
<< " in group " << grpId << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
RsGxsIfaceHelper::receiveChanges(changes);
|
||||
}
|
||||
|
||||
uint32_t p3GxsTrans::AuthenPolicy()
|
||||
@ -563,7 +675,9 @@ bool p3GxsTrans::requestGroupsData(const std::list<RsGxsGroupId>* groupIds)
|
||||
|
||||
bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail)
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::handleEcryptedMail(...)" << std::endl;
|
||||
#endif
|
||||
|
||||
std::set<RsGxsId> decryptIds;
|
||||
std::list<RsGxsId> ownIds;
|
||||
@ -586,8 +700,11 @@ bool p3GxsTrans::handleEncryptedMail(const RsGxsTransMailItem* mail)
|
||||
uint16_t csri = 0;
|
||||
uint32_t off = 0;
|
||||
getRawUInt16(&mail->payload[0], mail->payload.size(), &off, &csri);
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "service: " << csri << " got CLEAR_TEXT mail!"
|
||||
<< std::endl;
|
||||
#endif
|
||||
/* As we cannot verify recipient without encryption, just pass the hint
|
||||
* as recipient */
|
||||
return dispatchDecryptedMail( mail->meta.mAuthorId, mail->recipientHint,
|
||||
@ -626,8 +743,10 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
|
||||
const uint8_t* decrypted_data,
|
||||
uint32_t decrypted_data_size )
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::dispatchDecryptedMail(, , " << decrypted_data_size
|
||||
<< ")" << std::endl;
|
||||
#endif
|
||||
|
||||
uint16_t csri = 0;
|
||||
uint32_t offset = 0;
|
||||
@ -653,8 +772,10 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
|
||||
<< " wrong is happening!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::dispatchDecryptedMail(...) dispatching receipt "
|
||||
<< "with: msgId: " << receipt->msgId << std::endl;
|
||||
#endif
|
||||
|
||||
std::vector<RsNxsMsg*> rcct; rcct.push_back(receipt);
|
||||
RsGenExchange::notifyNewMessages(rcct);
|
||||
@ -678,7 +799,7 @@ bool p3GxsTrans::dispatchDecryptedMail( const RsGxsId& authorId,
|
||||
}
|
||||
}
|
||||
|
||||
void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
|
||||
void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
|
||||
{
|
||||
//std::cout << "p3GxsTrans::processRecord(...)" << std::endl;
|
||||
|
||||
@ -688,7 +809,7 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
|
||||
{
|
||||
pr.mailItem.saltRecipientHint(pr.recipient);
|
||||
pr.mailItem.saltRecipientHint(RsGxsId::random());
|
||||
pr.mailItem.meta.mPublishTs = time(NULL);
|
||||
pr.sent_ts = time(NULL) ; //pr.mailItem.meta.mPublishTs = time(NULL);
|
||||
}
|
||||
case GxsTransSendStatus::PENDING_PREFERRED_GROUP:
|
||||
{
|
||||
@ -699,12 +820,16 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
|
||||
break;
|
||||
}
|
||||
|
||||
pr.mailItem.meta.mGroupId = mPreferredGroupId;
|
||||
pr.group_id = mPreferredGroupId ; //pr.mailItem.meta.mGroupId = mPreferredGroupId;
|
||||
}
|
||||
case GxsTransSendStatus::PENDING_RECEIPT_CREATE:
|
||||
{
|
||||
RsGxsTransPresignedReceipt grcpt;
|
||||
grcpt.meta = pr.mailItem.meta;
|
||||
grcpt.meta.mAuthorId = pr.author ; //grcpt.meta = pr.mailItem.meta;
|
||||
grcpt.meta.mGroupId = pr.group_id ; //grcpt.meta = pr.mailItem.meta;
|
||||
grcpt.meta.mMsgId.clear() ;
|
||||
grcpt.meta.mParentId.clear() ;
|
||||
grcpt.meta.mOrigMsgId.clear() ;
|
||||
grcpt.meta.mPublishTs = time(NULL);
|
||||
grcpt.mailId = pr.mailItem.mailId;
|
||||
uint32_t grsz = RsGxsTransSerializer().size(&grcpt);
|
||||
@ -717,7 +842,7 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
|
||||
*pr.presignedReceipt.metaData = grcpt.meta;
|
||||
pr.presignedReceipt.msg.setBinData(&grsrz[0], grsz);
|
||||
}
|
||||
case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE:
|
||||
case GxsTransSendStatus::PENDING_RECEIPT_SIGNATURE: // (cyril) This step is never actually used.
|
||||
{
|
||||
switch (RsGenExchange::createMessage(&pr.presignedReceipt))
|
||||
{
|
||||
@ -795,6 +920,7 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
|
||||
}
|
||||
case GxsTransSendStatus::PENDING_PUBLISH:
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::sendEmail(...) sending mail to: "
|
||||
<< pr.recipient
|
||||
<< " with cryptoType: "
|
||||
@ -803,28 +929,50 @@ void p3GxsTrans::processOutgoingRecord(OutgoingRecord& pr)
|
||||
<< " receiptId: " << pr.mailItem.mailId
|
||||
<< " payload size: " << pr.mailItem.payload.size()
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
RsGxsTransMailItem *mail_item = new RsGxsTransMailItem(pr.mailItem);
|
||||
|
||||
// pr.mailItem.meta is *not* serialised. So it is important to not rely on what's in it!
|
||||
|
||||
mail_item->meta.mGroupId = pr.group_id ;
|
||||
mail_item->meta.mAuthorId = pr.author ;
|
||||
|
||||
mail_item->meta.mMsgId.clear();
|
||||
mail_item->meta.mParentId.clear();
|
||||
mail_item->meta.mOrigMsgId.clear();
|
||||
|
||||
uint32_t token;
|
||||
publishMsg(token, new RsGxsTransMailItem(pr.mailItem));
|
||||
publishMsg(token, mail_item) ;
|
||||
|
||||
pr.status = GxsTransSendStatus::PENDING_RECEIPT_RECEIVE;
|
||||
|
||||
IndicateConfigChanged(); // This causes the saving of the message after pr.status has changed.
|
||||
break;
|
||||
}
|
||||
//case GxsTransSendStatus::PENDING_TRANSFER:
|
||||
case GxsTransSendStatus::PENDING_RECEIPT_RECEIVE:
|
||||
{
|
||||
RS_STACK_MUTEX(mIngoingMutex);
|
||||
auto range = mIngoingQueue.equal_range(pr.mailItem.mailId);
|
||||
auto range = mIncomingQueue.equal_range(pr.mailItem.mailId);
|
||||
bool changed = false ;
|
||||
|
||||
for( auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
RsGxsTransPresignedReceipt* rt =
|
||||
dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
|
||||
RsGxsTransPresignedReceipt* rt = dynamic_cast<RsGxsTransPresignedReceipt*>(it->second);
|
||||
|
||||
if(rt && mIdService.isOwnId(rt->meta.mAuthorId))
|
||||
{
|
||||
mIngoingQueue.erase(it); delete rt;
|
||||
mIncomingQueue.erase(it); delete rt;
|
||||
pr.status = GxsTransSendStatus::RECEIPT_RECEIVED;
|
||||
|
||||
changed = true ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(changed)
|
||||
IndicateConfigChanged();
|
||||
|
||||
// TODO: Resend message if older then treshold
|
||||
break;
|
||||
}
|
||||
@ -875,19 +1023,31 @@ RsSerialiser* p3GxsTrans::setupSerialiser()
|
||||
|
||||
bool p3GxsTrans::saveList(bool &cleanup, std::list<RsItem *>& saveList)
|
||||
{
|
||||
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " "
|
||||
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
|
||||
<< std::endl;
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl;
|
||||
#endif
|
||||
|
||||
mOutgoingMutex.lock();
|
||||
mIngoingMutex.lock();
|
||||
|
||||
for ( auto& kv : mOutgoingQueue ) saveList.push_back(&kv.second);
|
||||
for ( auto& kv : mIngoingQueue ) saveList.push_back(kv.second);
|
||||
for ( auto& kv : mOutgoingQueue )
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "Saving outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::dec << "Group id: " << kv.second.group_id << ", TS=" << kv.second.sent_ts << std::endl;
|
||||
#endif
|
||||
saveList.push_back(&kv.second);
|
||||
}
|
||||
for ( auto& kv : mIncomingQueue )
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "Saving incoming item, ID " << std::hex << std::setfill('0') << std::setw(16) << kv.first << std::endl;
|
||||
#endif
|
||||
saveList.push_back(kv.second);
|
||||
}
|
||||
|
||||
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " "
|
||||
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
|
||||
<< std::endl;
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::saveList(...)" << saveList.size() << " " << mIncomingQueue.size() << " " << mOutgoingQueue.size() << std::endl;
|
||||
#endif
|
||||
|
||||
cleanup = false;
|
||||
return true;
|
||||
@ -901,9 +1061,11 @@ void p3GxsTrans::saveDone()
|
||||
|
||||
bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " "
|
||||
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
|
||||
<< mIncomingQueue.size() << " " << mOutgoingQueue.size()
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
for(auto& v : loadList)
|
||||
switch(static_cast<GxsTransItemsSubtypes>(v->PacketSubType()))
|
||||
@ -911,14 +1073,44 @@ bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL:
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT:
|
||||
{
|
||||
RsGxsTransBaseItem* mi = dynamic_cast<RsGxsTransBaseItem*>(v);
|
||||
RsGxsTransBaseMsgItem* mi = dynamic_cast<RsGxsTransBaseMsgItem*>(v);
|
||||
if(mi)
|
||||
{
|
||||
RS_STACK_MUTEX(mIngoingMutex);
|
||||
mIngoingQueue.insert(inMap::value_type(mi->mailId, mi));
|
||||
mIncomingQueue.insert(inMap::value_type(mi->mailId, mi));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated:
|
||||
{
|
||||
OutgoingRecord_deprecated* dot = dynamic_cast<OutgoingRecord_deprecated*>(v);
|
||||
|
||||
if(dot)
|
||||
{
|
||||
std::cerr << "(EE) Read a deprecated GxsTrans outgoing item. Converting to new format..." << std::endl;
|
||||
|
||||
OutgoingRecord ot(dot->recipient,dot->clientService,&dot->mailData[0],dot->mailData.size()) ;
|
||||
|
||||
ot.status = dot->status ;
|
||||
|
||||
ot.author.clear(); // These 3 fields cannot be stored in mailItem.meta, which is not serialised, so they are lost.
|
||||
ot.group_id.clear() ;
|
||||
ot.sent_ts = 0;
|
||||
|
||||
ot.mailItem = dot->mailItem ;
|
||||
ot.presignedReceipt = dot->presignedReceipt;
|
||||
|
||||
RS_STACK_MUTEX(mOutgoingMutex);
|
||||
mOutgoingQueue.insert(prMap::value_type(ot.mailItem.mailId, ot));
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "Loaded outgoing item (converted), ID " << std::hex << std::setfill('0') << std::setw(16) << ot.mailItem.mailId<< std::dec << ", Group id: " << ot.group_id << ", TS=" << ot.sent_ts << std::endl;
|
||||
#endif
|
||||
}
|
||||
delete v;
|
||||
break;
|
||||
}
|
||||
|
||||
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM:
|
||||
{
|
||||
OutgoingRecord* ot = dynamic_cast<OutgoingRecord*>(v);
|
||||
@ -927,6 +1119,10 @@ bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
|
||||
RS_STACK_MUTEX(mOutgoingMutex);
|
||||
mOutgoingQueue.insert(
|
||||
prMap::value_type(ot->mailItem.mailId, *ot));
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "Loading outgoing item, ID " << std::hex << std::setfill('0') << std::setw(16) << ot->mailItem.mailId<< std::dec << "Group id: " << ot->group_id << ", TS=" << ot->sent_ts << std::endl;
|
||||
#endif
|
||||
}
|
||||
delete v;
|
||||
break;
|
||||
@ -941,9 +1137,106 @@ bool p3GxsTrans::loadList(std::list<RsItem *>&loadList)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cout << "p3GxsTrans::loadList(...) " << loadList.size() << " "
|
||||
<< mIngoingQueue.size() << " " << mOutgoingQueue.size()
|
||||
<< mIncomingQueue.size() << " " << mOutgoingQueue.size()
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsTrans::acceptNewMessage(const RsGxsMsgMetaData *msgMeta,uint32_t msg_size)
|
||||
{
|
||||
// 1 - check the total size of the msgs for the author of this particular msg.
|
||||
|
||||
// 2 - Reject depending on embedded limits.
|
||||
|
||||
// Depending on reputation, the messages will be rejected:
|
||||
//
|
||||
// Reputation | Maximum msg count | Maximum msg size
|
||||
// ------------+----------------------+------------------
|
||||
// Negative | 0 | 0 // This is already handled by the anti-spam
|
||||
// R-Negative | 10 | 10k
|
||||
// Neutral | 100 | 20k
|
||||
// R-Positive | 400 | 1M
|
||||
// Positive | 1000 | 2M
|
||||
|
||||
// Ideally these values should be left as user-defined parameters, with the
|
||||
// default values below used as backup.
|
||||
|
||||
static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT = 10 ;
|
||||
static const uint32_t GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT = 40 ;
|
||||
static const uint32_t GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT = 400 ;
|
||||
static const uint32_t GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT = 1000 ;
|
||||
|
||||
static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT = 10 * 1024 ;
|
||||
static const uint32_t GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT = 200 * 1024 ;
|
||||
static const uint32_t GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT = 1024 * 1024 ;
|
||||
static const uint32_t GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT = 2 * 1024 * 1024 ;
|
||||
|
||||
uint32_t max_count = 0 ;
|
||||
uint32_t max_size = 0 ;
|
||||
uint32_t identity_flags = 0 ;
|
||||
|
||||
RsReputations::ReputationLevel rep_lev = rsReputations->overallReputationLevel(msgMeta->mAuthorId,&identity_flags);
|
||||
|
||||
switch(rep_lev)
|
||||
{
|
||||
case RsReputations::REPUTATION_REMOTELY_NEGATIVE: max_count = GXSTRANS_MAX_COUNT_REMOTELY_NEGATIVE_DEFAULT;
|
||||
max_size = GXSTRANS_MAX_SIZE_REMOTELY_NEGATIVE_DEFAULT;
|
||||
break ;
|
||||
case RsReputations::REPUTATION_NEUTRAL: max_count = GXSTRANS_MAX_COUNT_NEUTRAL_DEFAULT;
|
||||
max_size = GXSTRANS_MAX_SIZE_NEUTRAL_DEFAULT;
|
||||
break ;
|
||||
case RsReputations::REPUTATION_REMOTELY_POSITIVE: max_count = GXSTRANS_MAX_COUNT_REMOTELY_POSITIVE_DEFAULT;
|
||||
max_size = GXSTRANS_MAX_SIZE_REMOTELY_POSITIVE_DEFAULT;
|
||||
break ;
|
||||
case RsReputations::REPUTATION_LOCALLY_POSITIVE: max_count = GXSTRANS_MAX_COUNT_LOCALLY_POSITIVE_DEFAULT;
|
||||
max_size = GXSTRANS_MAX_SIZE_LOCALLY_POSITIVE_DEFAULT;
|
||||
break ;
|
||||
default:
|
||||
case RsReputations::REPUTATION_LOCALLY_NEGATIVE: max_count = 0 ;
|
||||
max_size = 0 ;
|
||||
break ;
|
||||
}
|
||||
|
||||
bool pgp_linked = identity_flags & RS_IDENTITY_FLAGS_PGP_LINKED ;
|
||||
|
||||
if(rep_lev <= RsReputations::REPUTATION_NEUTRAL && !pgp_linked)
|
||||
{
|
||||
max_count /= 10 ;
|
||||
max_size /= 10 ;
|
||||
}
|
||||
|
||||
RS_STACK_MUTEX(mPerUserStatsMutex);
|
||||
|
||||
MsgSizeCount& s(per_user_statistics[msgMeta->mAuthorId]) ;
|
||||
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "GxsTrans::acceptMessage(): size=" << msg_size << ", grp=" << msgMeta->mGroupId << ", gxs_id=" << msgMeta->mAuthorId << ", pgp_linked=" << pgp_linked << ", current (size,cnt)=("
|
||||
<< s.size << "," << s.count << ") reputation=" << rep_lev << ", limits=(" << max_size << "," << max_count << ") " ;
|
||||
#endif
|
||||
|
||||
if(s.size + msg_size > max_size || 1+s.count > max_count)
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "=> rejected." << std::endl;
|
||||
#endif
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_GXSTRANS
|
||||
std::cerr << "=> accepted." << std::endl;
|
||||
#endif
|
||||
|
||||
s.count++ ;
|
||||
s.size += msg_size ; // update the statistics, so that it's not possible to pass a bunch of msgs at once below the limits.
|
||||
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -57,6 +57,14 @@ struct GxsTransClient
|
||||
GxsTransSendStatus status ) = 0;
|
||||
};
|
||||
|
||||
struct MsgSizeCount
|
||||
{
|
||||
MsgSizeCount() : size(0),count(0) {}
|
||||
|
||||
uint32_t size ;
|
||||
uint32_t count ;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief p3GxsTrans is a mail delivery service based on GXS.
|
||||
* p3GxsTrans is capable of asynchronous mail delivery and acknowledgement.
|
||||
@ -90,9 +98,10 @@ public:
|
||||
mIdService(identities),
|
||||
mServClientsMutex("p3GxsTrans client services map mutex"),
|
||||
mOutgoingMutex("p3GxsTrans outgoing queue map mutex"),
|
||||
mIngoingMutex("p3GxsTrans ingoing queue map mutex")
|
||||
mIngoingMutex("p3GxsTrans ingoing queue map mutex"),
|
||||
mPerUserStatsMutex("p3GxsTrans user stats mutex")
|
||||
{
|
||||
mLastMsgCleanup = time(NULL) - 60; // to be changed into 0
|
||||
mLastMsgCleanup = time(NULL) - MAX_DELAY_BETWEEN_CLEANUPS + 30; // always check 30 secs after start
|
||||
mCleanupThread = NULL ;
|
||||
}
|
||||
|
||||
@ -159,7 +168,7 @@ private:
|
||||
* Two weeks seems fair ATM.
|
||||
*/
|
||||
static const uint32_t GXS_STORAGE_PERIOD = 0x127500;
|
||||
static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS = 1203; // every 20 mins. Could be less.
|
||||
static const uint32_t MAX_DELAY_BETWEEN_CLEANUPS ; // every 20 mins. Could be less.
|
||||
|
||||
time_t mLastMsgCleanup ;
|
||||
|
||||
@ -193,7 +202,7 @@ private:
|
||||
typedef std::map<RsGxsTransId, OutgoingRecord> prMap;
|
||||
prMap mOutgoingQueue;
|
||||
RsMutex mOutgoingMutex;
|
||||
void processOutgoingRecord(OutgoingRecord& r);
|
||||
void locked_processOutgoingRecord(OutgoingRecord& r);
|
||||
|
||||
/**
|
||||
* @brief Ingoing mail and receipt processing queue.
|
||||
@ -204,8 +213,8 @@ private:
|
||||
* item to not being processed and memleaked multimap is used instead of map
|
||||
* for incoming queue.
|
||||
*/
|
||||
typedef std::unordered_multimap<RsGxsTransId, RsGxsTransBaseItem*> inMap;
|
||||
inMap mIngoingQueue;
|
||||
typedef std::unordered_multimap<RsGxsTransId, RsGxsTransBaseMsgItem*> inMap;
|
||||
inMap mIncomingQueue;
|
||||
RsMutex mIngoingMutex;
|
||||
|
||||
/// @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type)
|
||||
@ -282,7 +291,7 @@ private:
|
||||
enum CheckState { CheckStart, CheckChecking };
|
||||
|
||||
public:
|
||||
GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService),mMtx("GxsTransIntegrityCheck") {}
|
||||
GxsTransIntegrityCleanupThread(RsGeneralDataService *const dataService): mDs(dataService),mMtx("GxsTransIntegrityCheck") { mDone=false;}
|
||||
|
||||
bool isDone();
|
||||
void run();
|
||||
@ -290,14 +299,26 @@ private:
|
||||
void getDeletedIds(std::list<RsGxsGroupId>& grpIds, std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >& msgIds);
|
||||
|
||||
void getMessagesToDelete(GxsMsgReq& req) ;
|
||||
void getPerUserStatistics(std::map<RsGxsId,MsgSizeCount>& m) ;
|
||||
|
||||
private:
|
||||
RsGeneralDataService* const mDs;
|
||||
RsMutex mMtx ;
|
||||
|
||||
GxsMsgReq mMsgToDel ;
|
||||
std::map<RsGxsId,MsgSizeCount> total_message_size_and_count;
|
||||
bool mDone ;
|
||||
};
|
||||
|
||||
// Overloaded from RsGenExchange.
|
||||
|
||||
bool acceptNewMessage(const RsGxsMsgMetaData *msgMeta, uint32_t size) ;
|
||||
|
||||
GxsTransIntegrityCleanupThread *mCleanupThread ;
|
||||
|
||||
// statistics of the load across all groups, per user.
|
||||
|
||||
RsMutex mPerUserStatsMutex;
|
||||
std::map<RsGxsId,MsgSizeCount> per_user_statistics ;
|
||||
};
|
||||
|
||||
|
@ -21,10 +21,11 @@
|
||||
|
||||
const RsGxsId RsGxsTransMailItem::allRecipientsHint("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
||||
|
||||
OutgoingRecord::OutgoingRecord() :
|
||||
RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS,
|
||||
static_cast<uint8_t>(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) )
|
||||
{ clear();}
|
||||
OutgoingRecord_deprecated::OutgoingRecord_deprecated()
|
||||
: RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast<uint8_t>(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated) ) { clear();}
|
||||
|
||||
OutgoingRecord::OutgoingRecord()
|
||||
: RsItem( RS_PKT_VERSION_SERVICE, RS_SERVICE_TYPE_GXS_TRANS, static_cast<uint8_t>(GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM) ) { clear();}
|
||||
|
||||
OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
|
||||
const uint8_t* data, uint32_t size ) :
|
||||
@ -41,8 +42,7 @@ OutgoingRecord::OutgoingRecord( RsGxsId rec, GxsTransSubServices cs,
|
||||
RS_REGISTER_ITEM_TYPE(RsGxsTransMailItem) // for mailItem
|
||||
RS_REGISTER_ITEM_TYPE(RsNxsTransPresignedReceipt) // for presignedReceipt
|
||||
|
||||
void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx)
|
||||
void OutgoingRecord_deprecated::serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t);
|
||||
RS_REGISTER_SERIAL_MEMBER(recipient);
|
||||
@ -51,3 +51,17 @@ void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j,
|
||||
RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t);
|
||||
RS_REGISTER_SERIAL_MEMBER(presignedReceipt);
|
||||
}
|
||||
|
||||
void OutgoingRecord::serial_process(RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RS_REGISTER_SERIAL_MEMBER_TYPED(status, uint8_t);
|
||||
RS_REGISTER_SERIAL_MEMBER(recipient);
|
||||
RS_REGISTER_SERIAL_MEMBER(author);
|
||||
RS_REGISTER_SERIAL_MEMBER(group_id);
|
||||
RS_REGISTER_SERIAL_MEMBER(sent_ts);
|
||||
RS_REGISTER_SERIAL_MEMBER(mailItem);
|
||||
RS_REGISTER_SERIAL_MEMBER(mailData);
|
||||
RS_REGISTER_SERIAL_MEMBER_TYPED(clientService, uint16_t);
|
||||
RS_REGISTER_SERIAL_MEMBER(presignedReceipt);
|
||||
}
|
||||
|
@ -36,14 +36,14 @@ public:
|
||||
virtual ~RsNxsTransPresignedReceipt() {}
|
||||
};
|
||||
|
||||
class RsGxsTransBaseItem : public RsGxsMsgItem
|
||||
class RsGxsTransBaseMsgItem : public RsGxsMsgItem
|
||||
{
|
||||
public:
|
||||
RsGxsTransBaseItem(GxsTransItemsSubtypes subtype) :
|
||||
RsGxsTransBaseMsgItem(GxsTransItemsSubtypes subtype) :
|
||||
RsGxsMsgItem( RS_SERVICE_TYPE_GXS_TRANS,
|
||||
static_cast<uint8_t>(subtype) ), mailId(0) {}
|
||||
|
||||
virtual ~RsGxsTransBaseItem() {}
|
||||
virtual ~RsGxsTransBaseMsgItem() {}
|
||||
|
||||
RsGxsTransId mailId;
|
||||
|
||||
@ -58,10 +58,10 @@ public:
|
||||
{ RS_REGISTER_SERIAL_MEMBER_TYPED(mailId, uint64_t); }
|
||||
};
|
||||
|
||||
class RsGxsTransPresignedReceipt : public RsGxsTransBaseItem
|
||||
class RsGxsTransPresignedReceipt : public RsGxsTransBaseMsgItem
|
||||
{
|
||||
public:
|
||||
RsGxsTransPresignedReceipt() : RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {}
|
||||
RsGxsTransPresignedReceipt() : RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT) {}
|
||||
virtual ~RsGxsTransPresignedReceipt() {}
|
||||
};
|
||||
|
||||
@ -72,11 +72,11 @@ enum class RsGxsTransEncryptionMode : uint8_t
|
||||
UNDEFINED_ENCRYPTION = 250
|
||||
};
|
||||
|
||||
class RsGxsTransMailItem : public RsGxsTransBaseItem
|
||||
class RsGxsTransMailItem : public RsGxsTransBaseMsgItem
|
||||
{
|
||||
public:
|
||||
RsGxsTransMailItem() :
|
||||
RsGxsTransBaseItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL),
|
||||
RsGxsTransBaseMsgItem(GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL),
|
||||
cryptoType(RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION) {}
|
||||
|
||||
virtual ~RsGxsTransMailItem() {}
|
||||
@ -139,7 +139,7 @@ public:
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx )
|
||||
{
|
||||
RsGxsTransBaseItem::serial_process(j, ctx);
|
||||
RsGxsTransBaseMsgItem::serial_process(j, ctx);
|
||||
RS_REGISTER_SERIAL_MEMBER_TYPED(cryptoType, uint8_t);
|
||||
RS_REGISTER_SERIAL_MEMBER(recipientHint);
|
||||
RS_REGISTER_SERIAL_MEMBER(payload);
|
||||
@ -147,7 +147,7 @@ public:
|
||||
|
||||
void clear()
|
||||
{
|
||||
RsGxsTransBaseItem::clear();
|
||||
RsGxsTransBaseMsgItem::clear();
|
||||
cryptoType = RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION;
|
||||
recipientHint.clear();
|
||||
payload.clear();
|
||||
@ -183,6 +183,33 @@ public:
|
||||
|
||||
class RsGxsTransSerializer;
|
||||
|
||||
class OutgoingRecord_deprecated : public RsItem
|
||||
{
|
||||
public:
|
||||
OutgoingRecord_deprecated( RsGxsId rec, GxsTransSubServices cs, const uint8_t* data, uint32_t size );
|
||||
|
||||
virtual ~OutgoingRecord_deprecated() {}
|
||||
|
||||
GxsTransSendStatus status;
|
||||
RsGxsId recipient;
|
||||
/// Don't use a pointer would be invalid after publish
|
||||
RsGxsTransMailItem mailItem;
|
||||
|
||||
std::vector<uint8_t> mailData;
|
||||
GxsTransSubServices clientService;
|
||||
|
||||
RsNxsTransPresignedReceipt presignedReceipt;
|
||||
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
RsGenericSerializer::SerializeContext& ctx );
|
||||
|
||||
void clear() {}
|
||||
|
||||
private:
|
||||
friend class RsGxsTransSerializer;
|
||||
OutgoingRecord_deprecated();
|
||||
};
|
||||
|
||||
class OutgoingRecord : public RsItem
|
||||
{
|
||||
public:
|
||||
@ -191,12 +218,19 @@ public:
|
||||
|
||||
virtual ~OutgoingRecord() {}
|
||||
|
||||
GxsTransSendStatus status;
|
||||
RsGxsId recipient;
|
||||
GxsTransSendStatus status;
|
||||
RsGxsId recipient;
|
||||
|
||||
RsGxsId author; // These 3 fields cannot be stored in mailItem.meta, which is not serialised.
|
||||
RsGxsGroupId group_id ;
|
||||
uint32_t sent_ts ;
|
||||
|
||||
/// Don't use a pointer would be invalid after publish
|
||||
RsGxsTransMailItem mailItem;
|
||||
|
||||
std::vector<uint8_t> mailData;
|
||||
GxsTransSubServices clientService;
|
||||
|
||||
RsNxsTransPresignedReceipt presignedReceipt;
|
||||
|
||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||
@ -225,6 +259,7 @@ public:
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_MAIL: return new RsGxsTransMailItem();
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_RECEIPT: return new RsGxsTransPresignedReceipt();
|
||||
case GxsTransItemsSubtypes::GXS_TRANS_SUBTYPE_GROUP: return new RsGxsTransGroupItem();
|
||||
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM_deprecated: return new OutgoingRecord_deprecated();
|
||||
case GxsTransItemsSubtypes::OUTGOING_RECORD_ITEM: return new OutgoingRecord();
|
||||
default: return NULL;
|
||||
}
|
||||
|
@ -142,6 +142,7 @@ public:
|
||||
|
||||
/* standard load */
|
||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups) = 0;
|
||||
virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsCircleMsg> &msgs) = 0;
|
||||
|
||||
/* make new group */
|
||||
virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group) = 0;
|
||||
|
@ -16,10 +16,11 @@ enum class GxsTransSubServices : uint16_t
|
||||
/// Values must fit into uint8_t
|
||||
enum class GxsTransItemsSubtypes : uint8_t
|
||||
{
|
||||
GXS_TRANS_SUBTYPE_MAIL = 0x01,
|
||||
GXS_TRANS_SUBTYPE_RECEIPT = 0x02,
|
||||
GXS_TRANS_SUBTYPE_GROUP = 0x03,
|
||||
OUTGOING_RECORD_ITEM = 0x04
|
||||
GXS_TRANS_SUBTYPE_MAIL = 0x01,
|
||||
GXS_TRANS_SUBTYPE_RECEIPT = 0x02,
|
||||
GXS_TRANS_SUBTYPE_GROUP = 0x03,
|
||||
OUTGOING_RECORD_ITEM_deprecated = 0x04,
|
||||
OUTGOING_RECORD_ITEM = 0x05
|
||||
};
|
||||
|
||||
enum class GxsTransSendStatus : uint8_t
|
||||
|
@ -77,6 +77,7 @@ const uint32_t RS_FEED_TYPE_FILES = 0x0400;
|
||||
const uint32_t RS_FEED_TYPE_SECURITY = 0x0800;
|
||||
const uint32_t RS_FEED_TYPE_POSTED = 0x1000;
|
||||
const uint32_t RS_FEED_TYPE_SECURITY_IP = 0x2000;
|
||||
const uint32_t RS_FEED_TYPE_CIRCLE = 0x4000;
|
||||
|
||||
const uint32_t RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002;
|
||||
@ -114,9 +115,12 @@ const uint32_t RS_FEED_ITEM_POSTED_NEW = RS_FEED_TYPE_POSTED | 0x0001;
|
||||
//const uint32_t RS_FEED_ITEM_POSTED_UPDATE = RS_FEED_TYPE_POSTED | 0x0002;
|
||||
const uint32_t RS_FEED_ITEM_POSTED_MSG = RS_FEED_TYPE_POSTED | 0x0003;
|
||||
|
||||
const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_CHAT_NEW = RS_FEED_TYPE_CHAT | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_MESSAGE = RS_FEED_TYPE_MSG | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_FILES_NEW = RS_FEED_TYPE_FILES | 0x0001;
|
||||
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_MEMB_REQ = RS_FEED_TYPE_CIRCLE | 0x0001;
|
||||
const uint32_t RS_FEED_ITEM_CIRCLE_INVIT_REC = RS_FEED_TYPE_CIRCLE | 0x0002;
|
||||
|
||||
const uint32_t RS_MESSAGE_CONNECT_ATTEMPT = 0x0001;
|
||||
|
||||
|
@ -55,7 +55,8 @@ void RsGxsCircleSubscriptionRequestItem::clear()
|
||||
|
||||
void RsGxsCircleMsgItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
{
|
||||
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,msg.stuff,"msg.stuff") ;
|
||||
//RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"mMsg.stuff") ;//Should be this but not retrocompatible...
|
||||
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_MSG,mMsg.stuff,"msg.stuff") ;
|
||||
}
|
||||
|
||||
void RsGxsCircleSubscriptionRequestItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||
@ -74,7 +75,7 @@ void RsGxsCircleGroupItem::serial_process(RsGenericSerializer::SerializeJob j,Rs
|
||||
|
||||
void RsGxsCircleMsgItem::clear()
|
||||
{
|
||||
msg.stuff.clear();
|
||||
mMsg.stuff.clear();
|
||||
}
|
||||
|
||||
void RsGxsCircleGroupItem::clear()
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
|
||||
virtual void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||
|
||||
RsGxsCircleMsg msg;
|
||||
RsGxsCircleMsg mMsg;
|
||||
};
|
||||
|
||||
class RsGxsCircleSubscriptionRequestItem: public RsGxsMsgItem
|
||||
|
@ -34,7 +34,7 @@ static const int sleepFactorDefault = 10; // 0.5s
|
||||
static const int sleepFactorFast = 1; // 0.05s
|
||||
static const int sleepFactorSlow = 20; // 1s
|
||||
|
||||
static struct RsLog::logInfo i2pBobLogInfo = {RsLog::Debug_All, "p3I2pBob"};
|
||||
static struct RsLog::logInfo i2pBobLogInfo = {RsLog::Default, "p3I2pBob"};
|
||||
|
||||
static const time_t selfCheckPeroid = 30;
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "pgp/pgpauxutils.h"
|
||||
#include "retroshare/rsgxscircles.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
#include "rsserver/p3face.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
@ -194,30 +195,38 @@ void p3GxsCircles::service_tick()
|
||||
void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
std::cerr << "p3GxsCircles::notifyChanges()";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "p3GxsCircles::notifyChanges()";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
std::vector<RsGxsNotify *>::iterator it;
|
||||
for(it = changes.begin(); it != changes.end(); ++it)
|
||||
{
|
||||
RsGxsGroupChange *groupChange = dynamic_cast<RsGxsGroupChange *>(*it);
|
||||
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
|
||||
p3Notify *notify = RsServer::notify();
|
||||
std::vector<RsGxsNotify *>::iterator it;
|
||||
for(it = changes.begin(); it != changes.end(); ++it)
|
||||
{
|
||||
RsGxsGroupChange *groupChange = dynamic_cast<RsGxsGroupChange *>(*it);
|
||||
RsGxsMsgChange *msgChange = dynamic_cast<RsGxsMsgChange *>(*it);
|
||||
RsGxsNotify *c = *it;
|
||||
|
||||
if (msgChange && !msgChange->metaChange())
|
||||
{
|
||||
if (msgChange && !msgChange->metaChange())
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
std::cerr << " Found circle Message Change Notification" << std::endl;
|
||||
std::cerr << " Found circle Message Change Notification" << std::endl;
|
||||
#endif
|
||||
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator mit = msgChange->msgChangeMap.begin(); mit != msgChange->msgChangeMap.end(); ++mit)
|
||||
{
|
||||
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::iterator mit = msgChange->msgChangeMap.begin(); mit != msgChange->msgChangeMap.end(); ++mit)
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
std::cerr << " Msgs for Group: " << mit->first << std::endl;
|
||||
std::cerr << " Msgs for Group: " << mit->first << std::endl;
|
||||
#endif
|
||||
for(std::map<RsGxsGroupId, std::vector<RsGxsMessageId> >::const_iterator it2(msgChange->msgChangeMap.begin());it2!=msgChange->msgChangeMap.end();++it2)
|
||||
force_cache_reload(RsGxsCircleId(it2->first)) ;
|
||||
}
|
||||
}
|
||||
force_cache_reload(RsGxsCircleId(mit->first));
|
||||
if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVE) )
|
||||
for (std::vector<RsGxsMessageId>::const_iterator msgIdIt(mit->second.begin()), end(mit->second.end()); msgIdIt != end; ++msgIdIt)
|
||||
{
|
||||
const RsGxsMessageId& msgId = *msgIdIt;
|
||||
notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_MEMB_REQ,RsGxsCircleId(mit->first).toStdString(),msgId.toStdString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* add groups to ExternalIdList (Might get Personal Circles here until NetChecks in place) */
|
||||
if (groupChange && !groupChange->metaChange())
|
||||
@ -245,16 +254,19 @@ void p3GxsCircles::notifyChanges(std::vector<RsGxsNotify *> &changes)
|
||||
}
|
||||
}
|
||||
|
||||
if(groupChange)
|
||||
for(std::list<RsGxsGroupId>::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git)
|
||||
{
|
||||
if(groupChange)
|
||||
for(std::list<RsGxsGroupId>::const_iterator git(groupChange->mGrpIdList.begin());git!=groupChange->mGrpIdList.end();++git)
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl;
|
||||
std::cerr << " forcing cache loading for circle " << *git << " in order to trigger subscribe update." << std::endl;
|
||||
#endif
|
||||
force_cache_reload(RsGxsCircleId(*git)) ;
|
||||
}
|
||||
}
|
||||
RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements
|
||||
force_cache_reload(RsGxsCircleId(*git)) ;
|
||||
if (notify && (c->getType() == RsGxsNotify::TYPE_RECEIVE) )
|
||||
notify->AddFeedItem(RS_FEED_ITEM_CIRCLE_INVIT_REC,RsGxsCircleId(*git).toStdString(),"");
|
||||
}
|
||||
|
||||
}
|
||||
RsGxsIfaceHelper::receiveChanges(changes); // this clear up the vector and delete its elements
|
||||
}
|
||||
|
||||
/********************************************************************************/
|
||||
@ -496,6 +508,62 @@ bool p3GxsCircles::getGroupData(const uint32_t &token, std::vector<RsGxsCircleGr
|
||||
/********************************************************************************/
|
||||
/********************************************************************************/
|
||||
|
||||
bool p3GxsCircles::getMsgData(const uint32_t &token, std::vector<RsGxsCircleMsg> &msgs)
|
||||
{
|
||||
GxsMsgDataMap msgData;
|
||||
bool ok = RsGenExchange::getMsgData(token, msgData);
|
||||
|
||||
if(ok)
|
||||
{
|
||||
GxsMsgDataMap::iterator mit = msgData.begin();
|
||||
|
||||
for(; mit != msgData.end(); ++mit)
|
||||
{
|
||||
std::vector<RsGxsMsgItem*>& msgItems = mit->second;
|
||||
std::vector<RsGxsMsgItem*>::iterator vit = msgItems.begin();
|
||||
|
||||
for(; vit != msgItems.end(); ++vit)
|
||||
{
|
||||
RsGxsCircleMsgItem* item = dynamic_cast<RsGxsCircleMsgItem*>(*vit);
|
||||
RsGxsCircleSubscriptionRequestItem* rsItem = dynamic_cast<RsGxsCircleSubscriptionRequestItem*>(*vit);
|
||||
if(item)
|
||||
{
|
||||
RsGxsCircleMsg msg = item->mMsg;
|
||||
msg.mMeta = item->meta;
|
||||
msgs.push_back(msg);
|
||||
delete item;
|
||||
}
|
||||
else if (rsItem)
|
||||
{
|
||||
RsGxsCircleMsg msg ;//= rsItem->mMsg;
|
||||
msg.mMeta = rsItem->meta;
|
||||
switch (rsItem->subscription_type)
|
||||
{
|
||||
case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNKNOWN:
|
||||
msg.stuff.clear();
|
||||
break;
|
||||
case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_SUBSCRIBE:
|
||||
msg.stuff="SUBSCRIPTION_REQUEST_SUBSCRIBE";
|
||||
break;
|
||||
case RsGxsCircleSubscriptionRequestItem::SUBSCRIPTION_REQUEST_UNSUBSCRIBE:
|
||||
msg.stuff="SUBSCRIPTION_REQUEST_UNSUBSCRIBE";
|
||||
break;
|
||||
}
|
||||
msgs.push_back(msg);
|
||||
delete rsItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Not a GxsCircleMsgItem, deleting!" << std::endl;
|
||||
delete *vit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void p3GxsCircles::createGroup(uint32_t& token, RsGxsCircleGroup &group)
|
||||
{
|
||||
#ifdef DEBUG_CIRCLES
|
||||
@ -2065,21 +2133,3 @@ bool p3GxsCircles::processMembershipRequests(uint32_t token)
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -199,6 +199,7 @@ virtual RsServiceInfo getServiceInfo();
|
||||
|
||||
|
||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsCircleGroup> &groups);
|
||||
virtual bool getMsgData(const uint32_t &token, std::vector<RsGxsCircleMsg> &msgs);
|
||||
virtual void createGroup(uint32_t& token, RsGxsCircleGroup &group);
|
||||
virtual void updateGroup(uint32_t &token, RsGxsCircleGroup &group);
|
||||
|
||||
|
@ -179,6 +179,7 @@ void RsThread::start(const std::string &threadName)
|
||||
THREAD_DEBUG << "pqithreadstreamer::start() initing should_stop=0" << std::endl;
|
||||
#endif
|
||||
mShouldStopSemaphore.set(0) ;
|
||||
mHasStoppedSemaphore.set(0) ;
|
||||
|
||||
int err ;
|
||||
|
||||
|
@ -25,45 +25,43 @@
|
||||
#include "NewsFeed.h"
|
||||
#include "ui_NewsFeed.h"
|
||||
|
||||
#include <retroshare/rsnotify.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <retroshare/rsbanlist.h>
|
||||
#include <retroshare/rsgxschannels.h>
|
||||
#include <retroshare/rsgxsforums.h>
|
||||
#include <retroshare/rsposted.h>
|
||||
#include <retroshare/rsmsgs.h>
|
||||
#include <retroshare/rsnotify.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <retroshare/rsplugin.h>
|
||||
#include <retroshare/rsbanlist.h>
|
||||
|
||||
#include "feeds/GxsChannelGroupItem.h"
|
||||
#include "feeds/GxsChannelPostItem.h"
|
||||
#include "feeds/GxsForumGroupItem.h"
|
||||
#include "feeds/GxsForumMsgItem.h"
|
||||
#include "feeds/PostedGroupItem.h"
|
||||
#include "Posted/PostedItem.h"
|
||||
#include "feeds/GxsForumMsgItem.h"
|
||||
|
||||
#include "settings/rsettingswin.h"
|
||||
#include <retroshare/rsposted.h>
|
||||
|
||||
#include "feeds/ChatMsgItem.h"
|
||||
#ifdef BLOGS
|
||||
#include "feeds/BlogNewItem.h"
|
||||
#include "feeds/BlogMsgItem.h"
|
||||
#endif
|
||||
|
||||
#include "feeds/GxsCircleItem.h"
|
||||
#include "feeds/GxsChannelGroupItem.h"
|
||||
#include "feeds/GxsChannelPostItem.h"
|
||||
#include "feeds/GxsForumGroupItem.h"
|
||||
#include "feeds/GxsForumMsgItem.h"
|
||||
#include "feeds/MsgItem.h"
|
||||
#include "feeds/NewsFeedUserNotify.h"
|
||||
#include "feeds/PeerItem.h"
|
||||
#include "feeds/ChatMsgItem.h"
|
||||
#include "feeds/PostedGroupItem.h"
|
||||
#include "feeds/SecurityItem.h"
|
||||
#include "feeds/SecurityIpItem.h"
|
||||
#include "feeds/NewsFeedUserNotify.h"
|
||||
|
||||
#include "settings/rsettingswin.h"
|
||||
#include "settings/rsharesettings.h"
|
||||
|
||||
#include "chat/ChatDialog.h"
|
||||
#include "Posted/PostedItem.h"
|
||||
#include "msgs/MessageComposer.h"
|
||||
#include "msgs/MessageInterface.h"
|
||||
|
||||
#include "common/FeedNotify.h"
|
||||
#include "notifyqt.h"
|
||||
|
||||
#include "gui/msgs/MessageInterface.h"
|
||||
|
||||
const uint32_t NEWSFEED_PEERLIST = 0x0001;
|
||||
|
||||
const uint32_t NEWSFEED_FORUMNEWLIST = 0x0002;
|
||||
@ -80,6 +78,7 @@ const uint32_t NEWSFEED_CHATMSGLIST = 0x0009;
|
||||
const uint32_t NEWSFEED_SECLIST = 0x000a;
|
||||
const uint32_t NEWSFEED_POSTEDNEWLIST = 0x000b;
|
||||
const uint32_t NEWSFEED_POSTEDMSGLIST = 0x000c;
|
||||
const uint32_t NEWSFEED_CIRCLELIST = 0x000d;
|
||||
|
||||
#define ROLE_RECEIVED FEED_TREEWIDGET_SORTROLE
|
||||
|
||||
@ -102,6 +101,7 @@ NewsFeed::NewsFeed(QWidget *parent) :
|
||||
ui->setupUi(this);
|
||||
|
||||
mTokenQueueChannel = NULL;
|
||||
mTokenQueueCircle = NULL;
|
||||
mTokenQueueForum = NULL;
|
||||
mTokenQueuePosted = NULL;
|
||||
|
||||
@ -156,6 +156,9 @@ NewsFeed::~NewsFeed()
|
||||
if (mTokenQueueChannel) {
|
||||
delete(mTokenQueueChannel);
|
||||
}
|
||||
if (mTokenQueueCircle) {
|
||||
delete(mTokenQueueCircle);
|
||||
}
|
||||
if (mTokenQueueForum) {
|
||||
delete(mTokenQueueForum);
|
||||
}
|
||||
@ -370,6 +373,52 @@ void NewsFeed::updateDisplay()
|
||||
if (flags & RS_FEED_TYPE_FILES)
|
||||
addFeedItemFilesNew(fi);
|
||||
break;
|
||||
|
||||
case RS_FEED_ITEM_CIRCLE_MEMB_REQ:
|
||||
if (flags & RS_FEED_TYPE_CIRCLE)
|
||||
{
|
||||
if (!mTokenQueueCircle) {
|
||||
mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance);
|
||||
}
|
||||
|
||||
RsGxsGroupId grpId(fi.mId1);
|
||||
RsGxsMessageId msgId(fi.mId2);
|
||||
if (!grpId.isNull() && !msgId.isNull()) {
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
|
||||
|
||||
GxsMsgReq msgIds;
|
||||
std::vector<RsGxsMessageId> &vect_msgIds = msgIds[grpId];
|
||||
vect_msgIds.push_back(msgId);
|
||||
|
||||
uint32_t token;
|
||||
mTokenQueueCircle->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, msgIds, TOKEN_TYPE_MESSAGE);
|
||||
}
|
||||
}
|
||||
// addFeedItemCircleMembReq(fi);
|
||||
break;
|
||||
case RS_FEED_ITEM_CIRCLE_INVIT_REC:
|
||||
if (flags & RS_FEED_TYPE_CIRCLE)
|
||||
{
|
||||
if (!mTokenQueueCircle) {
|
||||
mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance);
|
||||
}
|
||||
|
||||
RsGxsGroupId grpId(fi.mId1);
|
||||
if (!grpId.isNull()) {
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
|
||||
std::list<RsGxsGroupId> grpIds;
|
||||
grpIds.push_back(grpId);
|
||||
|
||||
uint32_t token;
|
||||
mTokenQueueCircle->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, grpIds, TOKEN_TYPE_GROUP);
|
||||
}
|
||||
}
|
||||
// addFeedItemCircleInvitRec(fi);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "(EE) Unknown type " << std::hex << fi.mType << std::dec << " in news feed." << std::endl;
|
||||
break;
|
||||
@ -534,6 +583,24 @@ void NewsFeed::testFeeds(uint notifyFlags)
|
||||
// not used
|
||||
// instance->addFeedItemFilesNew(fi);
|
||||
break;
|
||||
|
||||
case RS_FEED_TYPE_CIRCLE:
|
||||
{
|
||||
if (!instance->mTokenQueueCircle) {
|
||||
instance->mTokenQueueCircle = new TokenQueue(rsGxsCircles->getTokenService(), instance);
|
||||
}
|
||||
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
uint32_t token;
|
||||
instance->mTokenQueueCircle->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_SUMMARY, opts, TOKEN_TYPE_GROUP);
|
||||
|
||||
break;
|
||||
}
|
||||
// instance->addFeedItemCircleMembReq(fi);
|
||||
// instance->addFeedItemCircleInvitRec(fi);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -542,6 +609,78 @@ void NewsFeed::testFeeds(uint notifyFlags)
|
||||
instance->sendNewsFeedChanged();
|
||||
}
|
||||
|
||||
void NewsFeed::loadCircleGroup(const uint32_t &token)
|
||||
{
|
||||
std::vector<RsGxsCircleGroup> groups;
|
||||
if (!rsGxsCircles->getGroupData(token, groups)) {
|
||||
std::cerr << "NewsFeed::loadCircleGroup() ERROR getting data";
|
||||
std::cerr << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<RsGxsId> own_identities;
|
||||
rsIdentity->getOwnIds(own_identities);
|
||||
|
||||
std::vector<RsGxsCircleGroup>::const_iterator circleIt;
|
||||
for (circleIt = groups.begin(); circleIt != groups.end(); ++circleIt) {
|
||||
RsGxsCircleGroup group = *(circleIt);
|
||||
RsGxsCircleDetails details;
|
||||
if(rsGxsCircles->getCircleDetails(group.mMeta.mCircleId,details))
|
||||
{
|
||||
for(std::list<RsGxsId>::const_iterator it(own_identities.begin());it!=own_identities.end();++it) {
|
||||
std::map<RsGxsId,uint32_t>::const_iterator vit = details.mSubscriptionFlags.find(*it);
|
||||
uint32_t subscribe_flags = (vit == details.mSubscriptionFlags.end())?0:(vit->second);
|
||||
|
||||
if( !(subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED)
|
||||
&& (subscribe_flags & GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST) ) {
|
||||
|
||||
RsFeedItem fi;
|
||||
fi.mId1 = group.mMeta.mGroupId.toStdString();
|
||||
fi.mId2 = it->toStdString();
|
||||
|
||||
instance->addFeedItemCircleInvitRec(fi);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewsFeed::loadCircleMessage(const uint32_t &token)
|
||||
{
|
||||
std::vector<RsGxsCircleMsg> msgs;
|
||||
if (!rsGxsCircles->getMsgData(token, msgs)) {
|
||||
std::cerr << "NewsFeed::loadCircleMessage() ERROR getting data";
|
||||
std::cerr << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<RsGxsId> own_identities;
|
||||
rsIdentity->getOwnIds(own_identities);
|
||||
|
||||
std::vector<RsGxsCircleMsg>::iterator msgIt;
|
||||
for (msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) {
|
||||
RsGxsCircleMsg msg = *(msgIt);
|
||||
RsGxsCircleDetails details;
|
||||
if(rsGxsCircles->getCircleDetails(RsGxsCircleId(msg.mMeta.mGroupId),details)) {
|
||||
//for(std::list<RsGxsId>::const_iterator it(own_identities.begin());it!=own_identities.end();++it) {
|
||||
// std::map<RsGxsId,uint32_t>::const_iterator vit = details.mSubscriptionFlags.find(*it);
|
||||
// if (vit != details.mSubscriptionFlags.end()) {
|
||||
RsFeedItem fi;
|
||||
fi.mId1 = msgIt->mMeta.mGroupId.toStdString();
|
||||
fi.mId2 = msgIt->mMeta.mAuthorId.toStdString();
|
||||
|
||||
if (msgIt->stuff == "SUBSCRIPTION_REQUEST_UNSUBSCRIBE")
|
||||
instance->remFeedItemCircleMembReq(fi);
|
||||
else
|
||||
instance->addFeedItemCircleMembReq(fi);
|
||||
|
||||
//}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NewsFeed::loadChannelGroup(const uint32_t &token)
|
||||
{
|
||||
std::vector<RsGxsChannelGroup> groups;
|
||||
@ -821,7 +960,24 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req)
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE";
|
||||
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID CHANNEL TYPE";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (queue == mTokenQueueCircle) {
|
||||
switch (req.mUserType) {
|
||||
case TOKEN_TYPE_GROUP:
|
||||
loadCircleGroup(req.mToken);
|
||||
break;
|
||||
|
||||
case TOKEN_TYPE_MESSAGE:
|
||||
loadCircleMessage(req.mToken);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID CIRCLE TYPE";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
@ -842,7 +998,7 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req)
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE";
|
||||
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID FORUM TYPE";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
@ -859,7 +1015,7 @@ void NewsFeed::loadRequest(const TokenQueue *queue, const TokenRequest &req)
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID TYPE";
|
||||
std::cerr << "NewsFeed::loadRequest() ERROR: INVALID POSTED TYPE";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
@ -908,18 +1064,24 @@ void NewsFeed::addFeedItem(FeedItem *item)
|
||||
|
||||
struct AddFeedItemIfUniqueData
|
||||
{
|
||||
AddFeedItemIfUniqueData(FeedItem *feedItem, int type, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported)
|
||||
: mType(type), mSslId(sslId), mIpAddr(ipAddr), mIpAddrReported(ipAddrReported)
|
||||
AddFeedItemIfUniqueData(FeedItem *feedItem, int type
|
||||
, const std::string& id1, const std::string& id2
|
||||
, const std::string& id3, const std::string& id4)
|
||||
: mType(type), mId1(id1), mId2(id2), mId3(id3), mId4(id4)
|
||||
{
|
||||
mGxsCircleItem = dynamic_cast<GxsCircleItem*>(feedItem);
|
||||
mPeerItem = dynamic_cast<PeerItem*>(feedItem);
|
||||
mSecItem = dynamic_cast<SecurityItem*>(feedItem);
|
||||
mSecurityIpItem = dynamic_cast<SecurityIpItem*>(feedItem);
|
||||
}
|
||||
|
||||
int mType;
|
||||
const RsPeerId &mSslId;
|
||||
const std::string& mIpAddr;
|
||||
const std::string& mIpAddrReported;
|
||||
const std::string& mId1;
|
||||
const std::string& mId2;
|
||||
const std::string& mId3;
|
||||
const std::string& mId4;
|
||||
|
||||
GxsCircleItem *mGxsCircleItem;
|
||||
PeerItem *mPeerItem;
|
||||
SecurityItem *mSecItem;
|
||||
SecurityIpItem *mSecurityIpItem;
|
||||
@ -928,13 +1090,21 @@ struct AddFeedItemIfUniqueData
|
||||
static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
|
||||
{
|
||||
AddFeedItemIfUniqueData *findData = (AddFeedItemIfUniqueData*) data;
|
||||
if (!findData || findData->mSslId.isNull()) {
|
||||
if (!findData || findData->mId1.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (findData->mGxsCircleItem) {
|
||||
GxsCircleItem *gxsCircleItem = dynamic_cast<GxsCircleItem*>(feedItem);
|
||||
if (gxsCircleItem && gxsCircleItem->isSame(RsGxsCircleId(findData->mId1), RsGxsId(findData->mId2), findData->mType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (findData->mPeerItem) {
|
||||
PeerItem *peerItem = dynamic_cast<PeerItem*>(feedItem);
|
||||
if (peerItem && peerItem->isSame(findData->mSslId, findData->mType)) {
|
||||
if (peerItem && peerItem->isSame(RsPeerId(findData->mId1), findData->mType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -942,7 +1112,7 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
|
||||
|
||||
if (findData->mSecItem) {
|
||||
SecurityItem *secitem = dynamic_cast<SecurityItem*>(feedItem);
|
||||
if (secitem && secitem->isSame(findData->mSslId, findData->mType)) {
|
||||
if (secitem && secitem->isSame(RsPeerId(findData->mId1), findData->mType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -950,7 +1120,7 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
|
||||
|
||||
if (findData->mSecurityIpItem) {
|
||||
SecurityIpItem *securityIpItem = dynamic_cast<SecurityIpItem*>(feedItem);
|
||||
if (securityIpItem && securityIpItem->isSame(findData->mIpAddr, findData->mIpAddrReported, findData->mType)) {
|
||||
if (securityIpItem && securityIpItem->isSame(findData->mId1, findData->mId2, findData->mType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -959,9 +1129,9 @@ static bool addFeedItemIfUniqueCallback(FeedItem *feedItem, void *data)
|
||||
return false;
|
||||
}
|
||||
|
||||
void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, bool replace)
|
||||
void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, bool replace)
|
||||
{
|
||||
AddFeedItemIfUniqueData data(item, itemType, sslId, ipAddr, ipAddrReported);
|
||||
AddFeedItemIfUniqueData data(item, itemType, id1, id2, id3, id4);
|
||||
FeedItem *feedItem = ui->feedWidget->findFeedItem(addFeedItemIfUniqueCallback, &data);
|
||||
|
||||
if (feedItem) {
|
||||
@ -976,6 +1146,18 @@ void NewsFeed::addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId
|
||||
addFeedItem(item);
|
||||
}
|
||||
|
||||
void NewsFeed::remUniqueFeedItem(FeedItem *item, int itemType, const std::string &id1, const std::string &id2, const std::string &id3, const std::string &id4)
|
||||
{
|
||||
AddFeedItemIfUniqueData data(item, itemType, id1, id2, id3, id4);
|
||||
FeedItem *feedItem = ui->feedWidget->findFeedItem(addFeedItemIfUniqueCallback, &data);
|
||||
|
||||
if (feedItem) {
|
||||
delete item;
|
||||
|
||||
ui->feedWidget->removeFeedItem(feedItem);
|
||||
}
|
||||
}
|
||||
|
||||
void NewsFeed::addFeedItemPeerConnect(const RsFeedItem &fi)
|
||||
{
|
||||
/* make new widget */
|
||||
@ -1038,7 +1220,7 @@ void NewsFeed::addFeedItemPeerOffset(const RsFeedItem &fi)
|
||||
PeerItem *pi = new PeerItem(this, NEWSFEED_PEERLIST, RsPeerId(fi.mId1), PEER_TYPE_OFFSET, false);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(pi, PEER_TYPE_OFFSET, RsPeerId(fi.mId1), "", "", false);
|
||||
addFeedItemIfUnique(pi, PEER_TYPE_OFFSET, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemPeerOffset()";
|
||||
@ -1052,7 +1234,7 @@ void NewsFeed::addFeedItemSecurityConnectAttempt(const RsFeedItem &fi)
|
||||
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, fi.mType, false);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(pi, fi.mType, RsPeerId(fi.mId2), "", "", false);
|
||||
addFeedItemIfUnique(pi, fi.mType, fi.mId2, "", "", "", false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemSecurityConnectAttempt()";
|
||||
@ -1066,7 +1248,7 @@ void NewsFeed::addFeedItemSecurityAuthDenied(const RsFeedItem &fi)
|
||||
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, fi.mType, false);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_AUTH_DENIED, RsPeerId(fi.mId2), "", "", false);
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_AUTH_DENIED, fi.mId2, "", "", "", false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemSecurityAuthDenied()";
|
||||
@ -1080,7 +1262,7 @@ void NewsFeed::addFeedItemSecurityUnknownIn(const RsFeedItem &fi)
|
||||
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, RS_FEED_ITEM_SEC_UNKNOWN_IN, false);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_IN, RsPeerId(fi.mId2), "", "", false);
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_IN, fi.mId2, "", "", "", false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemSecurityUnknownIn()";
|
||||
@ -1094,7 +1276,7 @@ void NewsFeed::addFeedItemSecurityUnknownOut(const RsFeedItem &fi)
|
||||
SecurityItem *pi = new SecurityItem(this, NEWSFEED_SECLIST, RsPgpId(fi.mId1), RsPeerId(fi.mId2), fi.mId3, fi.mId4, RS_FEED_ITEM_SEC_UNKNOWN_OUT, false);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_OUT, RsPeerId(fi.mId2), "", "", false);
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_UNKNOWN_OUT, fi.mId2, "", "", "", false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemSecurityUnknownOut()";
|
||||
@ -1108,7 +1290,7 @@ void NewsFeed::addFeedItemSecurityIpBlacklisted(const RsFeedItem &fi, bool isTes
|
||||
SecurityIpItem *pi = new SecurityIpItem(this, RsPeerId(fi.mId1), fi.mId2, fi.mResult1, RS_FEED_ITEM_SEC_IP_BLACKLISTED, isTest);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_BLACKLISTED, RsPeerId(fi.mId1), fi.mId2, "", false);
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_BLACKLISTED, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemSecurityIpBlacklisted()";
|
||||
@ -1122,7 +1304,7 @@ void NewsFeed::addFeedItemSecurityWrongExternalIpReported(const RsFeedItem &fi,
|
||||
SecurityIpItem *pi = new SecurityIpItem(this, RsPeerId(fi.mId1), fi.mId2, fi.mId3, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, isTest);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, RsPeerId(fi.mId1), fi.mId2, fi.mId3, false);
|
||||
addFeedItemIfUnique(pi, RS_FEED_ITEM_SEC_IP_WRONG_EXTERNAL_IP_REPORTED, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemSecurityWrongExternalIpReported()";
|
||||
@ -1375,6 +1557,66 @@ void NewsFeed::addFeedItemFilesNew(const RsFeedItem &/*fi*/)
|
||||
#endif
|
||||
}
|
||||
|
||||
void NewsFeed::addFeedItemCircleMembReq(const RsFeedItem &fi)
|
||||
{
|
||||
RsGxsCircleId circleId(fi.mId1);
|
||||
RsGxsId gxsId(fi.mId2);
|
||||
|
||||
if (circleId.isNull() || gxsId.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* make new widget */
|
||||
GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_MEMB_REQ);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItemIfUnique(item, RS_FEED_ITEM_CIRCLE_MEMB_REQ, fi.mId1, fi.mId2, fi.mId3, fi.mId4, false);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemCircleMembReq()" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NewsFeed::remFeedItemCircleMembReq(const RsFeedItem &fi)
|
||||
{
|
||||
RsGxsCircleId circleId(fi.mId1);
|
||||
RsGxsId gxsId(fi.mId2);
|
||||
|
||||
if (circleId.isNull() || gxsId.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* make new widget */
|
||||
GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_MEMB_REQ);
|
||||
|
||||
/* add to layout */
|
||||
remUniqueFeedItem(item, RS_FEED_ITEM_CIRCLE_MEMB_REQ, fi.mId1, fi.mId2, fi.mId3, fi.mId4);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::remFeedItemCircleMembReq()" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NewsFeed::addFeedItemCircleInvitRec(const RsFeedItem &fi)
|
||||
{
|
||||
RsGxsCircleId circleId(fi.mId1);
|
||||
RsGxsId gxsId(fi.mId2);
|
||||
|
||||
if (circleId.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* make new widget */
|
||||
GxsCircleItem *item = new GxsCircleItem(this, NEWSFEED_CIRCLELIST, circleId, gxsId, RS_FEED_ITEM_CIRCLE_INVIT_REC);
|
||||
|
||||
/* add to layout */
|
||||
addFeedItem(item);
|
||||
|
||||
#ifdef NEWS_DEBUG
|
||||
std::cerr << "NewsFeed::addFeedItemCircleInvitRec()" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* FeedHolder Functions (for FeedItem functionality) */
|
||||
QScrollArea *NewsFeed::getScrollArea()
|
||||
{
|
||||
@ -1403,7 +1645,7 @@ void NewsFeed::openChat(const RsPeerId &peerId)
|
||||
ChatDialog::chatFriend(ChatId(peerId));
|
||||
}
|
||||
|
||||
void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector<RsGxsMessageId>& versions,const RsGxsMessageId &/*msgId*/, const QString &/*title*/)
|
||||
void NewsFeed::openComments(uint32_t /*type*/, const RsGxsGroupId &/*groupId*/, const QVector<RsGxsMessageId> &/*versions*/,const RsGxsMessageId &/*msgId*/, const QString &/*title*/)
|
||||
{
|
||||
std::cerr << "NewsFeed::openComments() Not Handled Yet";
|
||||
std::cerr << std::endl;
|
||||
|
@ -83,7 +83,8 @@ private slots:
|
||||
|
||||
private:
|
||||
void addFeedItem(FeedItem *item);
|
||||
void addFeedItemIfUnique(FeedItem *item, int itemType, const RsPeerId &sslId, const std::string& ipAddr, const std::string& ipAddrReported, bool replace);
|
||||
void addFeedItemIfUnique(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4, bool replace);
|
||||
void remUniqueFeedItem(FeedItem *item, int itemType, const std::string& id1, const std::string& id2, const std::string& id3, const std::string& id4);
|
||||
|
||||
void addFeedItemPeerConnect(const RsFeedItem &fi);
|
||||
void addFeedItemPeerDisconnect(const RsFeedItem &fi);
|
||||
@ -119,6 +120,10 @@ private:
|
||||
void addFeedItemMessage(const RsFeedItem &fi);
|
||||
void addFeedItemFilesNew(const RsFeedItem &fi);
|
||||
|
||||
void addFeedItemCircleMembReq(const RsFeedItem &fi);
|
||||
void remFeedItemCircleMembReq(const RsFeedItem &fi);
|
||||
void addFeedItemCircleInvitRec(const RsFeedItem &fi);
|
||||
|
||||
virtual void loadChannelGroup(const uint32_t &token);
|
||||
virtual void loadChannelPost(const uint32_t &token);
|
||||
virtual void loadChannelPublishKey(const uint32_t &token);
|
||||
@ -130,8 +135,12 @@ private:
|
||||
virtual void loadPostedGroup(const uint32_t &token);
|
||||
virtual void loadPostedMessage(const uint32_t &token);
|
||||
|
||||
virtual void loadCircleGroup(const uint32_t &token);
|
||||
virtual void loadCircleMessage(const uint32_t &token);
|
||||
|
||||
private:
|
||||
TokenQueue *mTokenQueueChannel;
|
||||
TokenQueue *mTokenQueueCircle;
|
||||
TokenQueue *mTokenQueueForum;
|
||||
TokenQueue *mTokenQueuePosted;
|
||||
|
||||
|
@ -185,8 +185,9 @@ bool GxsChannelPostItem::setGroup(const RsGxsChannelGroup &group, bool doFill)
|
||||
mGroup = group;
|
||||
|
||||
// if not publisher, hide the edit button. Without the publish key, there's no way to edit a message.
|
||||
|
||||
#ifdef DEBUG_ITEM
|
||||
std::cerr << "Group subscribe flags = " << std::hex << mGroup.mMeta.mSubscribeFlags << std::dec << std::endl;
|
||||
#endif
|
||||
if(!IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags))
|
||||
ui->editButton->hide();
|
||||
|
||||
|
284
retroshare-gui/src/gui/feeds/GxsCircleItem.cpp
Normal file
284
retroshare-gui/src/gui/feeds/GxsCircleItem.cpp
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Retroshare Gxs Feed Item
|
||||
*
|
||||
* Copyright 2014 RetroShare Team
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GxsCircleItem.h"
|
||||
#include "ui_GxsCircleItem.h"
|
||||
|
||||
#include "FeedHolder.h"
|
||||
#include "gui/notifyqt.h"
|
||||
#include "gui/Circles/CreateCircleDialog.h"
|
||||
#include "gui/gxs/GxsIdDetails.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/****
|
||||
* #define DEBUG_ITEM 1
|
||||
****/
|
||||
|
||||
#define COLOR_NORMAL QColor(248, 248, 248)
|
||||
#define COLOR_NEW QColor(220, 236, 253)
|
||||
|
||||
#define CIRCLESDIALOG_GROUPUPDATE 3
|
||||
|
||||
|
||||
GxsCircleItem::GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type)
|
||||
:FeedItem(NULL), mFeedHolder(feedHolder), mFeedId(feedId), mType(type), mCircleId(circleId), mGxsId(gxsId)
|
||||
{
|
||||
setup();
|
||||
}
|
||||
|
||||
|
||||
GxsCircleItem::~GxsCircleItem()
|
||||
{
|
||||
delete(ui);
|
||||
}
|
||||
|
||||
void GxsCircleItem::setup()
|
||||
{
|
||||
/* Invoke the Qt Designer generated object setup routine */
|
||||
ui = new Ui::GxsCircleItem;
|
||||
ui->setupUi(this);
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
/* general ones */
|
||||
connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(showCircleDetails()));
|
||||
connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem()));
|
||||
|
||||
/* update gxs information */
|
||||
|
||||
RsIdentityDetails idDetails ;
|
||||
QString idName ;
|
||||
if(rsIdentity->getIdDetails(mGxsId, idDetails))
|
||||
idName = tr("for identity ")+QString::fromUtf8(idDetails.mNickname.c_str()) + " (ID=" + QString::fromStdString(mGxsId.toStdString()) + ")" ;
|
||||
else
|
||||
idName = tr("for identity ")+QString::fromStdString(mGxsId.toStdString()) ;
|
||||
|
||||
|
||||
/* update circle information */
|
||||
|
||||
RsGxsCircleDetails circleDetails;
|
||||
if (rsGxsCircles->getCircleDetails(mCircleId, circleDetails))
|
||||
{
|
||||
|
||||
if (mType == RS_FEED_ITEM_CIRCLE_MEMB_REQ)
|
||||
{
|
||||
ui->titleLabel->setText(tr("You received a membership request for circle:"));
|
||||
ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str()));
|
||||
ui->gxsIdLabel->setText(idName);
|
||||
|
||||
ui->acceptButton->setToolTip(tr("Grant membership request"));
|
||||
ui->revokeButton->setToolTip(tr("Revoke membership request"));
|
||||
connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(grantCircleMembership()));
|
||||
connect(ui->revokeButton, SIGNAL(clicked()), this, SLOT(revokeCircleMembership()));
|
||||
}
|
||||
else if (mType == RS_FEED_ITEM_CIRCLE_INVIT_REC)
|
||||
{
|
||||
ui->titleLabel->setText(tr("You received an invitation for circle:"));
|
||||
ui->nameLabel->setText(QString::fromUtf8(circleDetails.mCircleName.c_str()));
|
||||
ui->gxsIdLabel->setText(idName);
|
||||
|
||||
ui->acceptButton->setToolTip(tr("Accept invitation"));
|
||||
connect(ui->acceptButton, SIGNAL(clicked()), this, SLOT(acceptCircleSubscription()));
|
||||
ui->revokeButton->setHidden(true);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->titleLabel->setText(tr("Received event from unknown Circle:"));
|
||||
ui->nameLabel->setText(QString::fromStdString(mCircleId.toStdString()));
|
||||
ui->gxsIdLabel->setText(idName);
|
||||
}
|
||||
|
||||
/* Setup TokenQueue */
|
||||
mCircleQueue = new TokenQueue(rsGxsCircles->getTokenService(), this);
|
||||
|
||||
}
|
||||
|
||||
bool GxsCircleItem::isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type)
|
||||
{
|
||||
if ((mCircleId == circleId) && (mGxsId == gxsId) && (mType == type))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void GxsCircleItem::removeItem()
|
||||
{
|
||||
#ifdef DEBUG_ITEM
|
||||
std::cerr << "GxsCircleItem::removeItem()" << std::endl;
|
||||
#endif
|
||||
|
||||
if (mFeedHolder)
|
||||
{
|
||||
mFeedHolder->lockLayout(this, true);
|
||||
hide();
|
||||
mFeedHolder->lockLayout(this, false);
|
||||
|
||||
mFeedHolder->deleteFeedItem(this, mFeedId);
|
||||
}
|
||||
}
|
||||
|
||||
void GxsCircleItem::loadRequest(const TokenQueue * queue, const TokenRequest &req)
|
||||
{
|
||||
#ifdef ID_DEBUG
|
||||
std::cerr << "GxsCircleItem::loadRequest() UserType: " << req.mUserType;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
if(queue == mCircleQueue)
|
||||
{
|
||||
#ifdef ID_DEBUG
|
||||
std::cerr << "CirclesDialog::loadRequest() UserType: " << req.mUserType;
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
/* now switch on req */
|
||||
switch(req.mUserType)
|
||||
{
|
||||
case CIRCLESDIALOG_GROUPUPDATE:
|
||||
updateCircleGroup(req.mToken);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cerr << "GxsCircleItem::loadRequest() ERROR: INVALID TYPE";
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********** SPECIFIC FUNCTIONS ***********************/
|
||||
|
||||
void GxsCircleItem::showCircleDetails()
|
||||
{
|
||||
CreateCircleDialog dlg;
|
||||
|
||||
dlg.editExistingId(RsGxsGroupId(mCircleId), true, mType != RS_FEED_ITEM_CIRCLE_MEMB_REQ) ;
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void GxsCircleItem::acceptCircleSubscription()
|
||||
{
|
||||
if (rsGxsCircles->requestCircleMembership(mGxsId, mCircleId))
|
||||
removeItem();
|
||||
}
|
||||
|
||||
void GxsCircleItem::grantCircleMembership()
|
||||
{
|
||||
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
|
||||
std::list<RsGxsGroupId> grps ;
|
||||
grps.push_back(RsGxsGroupId(mCircleId));
|
||||
|
||||
uint32_t token;
|
||||
mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grps, CIRCLESDIALOG_GROUPUPDATE);
|
||||
|
||||
CircleUpdateOrder c ;
|
||||
c.token = token ;
|
||||
c.gxs_id = mGxsId ;
|
||||
c.action = CircleUpdateOrder::GRANT_MEMBERSHIP ;
|
||||
|
||||
mCircleUpdates[token] = c ;
|
||||
}
|
||||
|
||||
void GxsCircleItem::revokeCircleMembership()
|
||||
{
|
||||
|
||||
RsTokReqOptions opts;
|
||||
opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA;
|
||||
|
||||
std::list<RsGxsGroupId> grps;
|
||||
grps.push_back(RsGxsGroupId(mCircleId));
|
||||
|
||||
uint32_t token;
|
||||
mCircleQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grps, CIRCLESDIALOG_GROUPUPDATE);
|
||||
|
||||
CircleUpdateOrder c;
|
||||
c.token = token;
|
||||
c.gxs_id = mGxsId;
|
||||
c.action = CircleUpdateOrder::REVOKE_MEMBERSHIP;
|
||||
|
||||
mCircleUpdates[token] = c;
|
||||
}
|
||||
|
||||
void GxsCircleItem::updateCircleGroup(const uint32_t& token)
|
||||
{
|
||||
#ifdef ID_DEBUG
|
||||
std::cerr << "Loading circle info" << std::endl;
|
||||
#endif
|
||||
|
||||
std::vector<RsGxsCircleGroup> circle_grp_v ;
|
||||
rsGxsCircles->getGroupData(token, circle_grp_v);
|
||||
|
||||
if (circle_grp_v.empty())
|
||||
{
|
||||
std::cerr << "(EE) unexpected empty result from getGroupData. Cannot process circle now!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
if (circle_grp_v.size() != 1)
|
||||
{
|
||||
std::cerr << "(EE) very weird result from getGroupData. Should get exactly one circle" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
RsGxsCircleGroup cg = circle_grp_v.front();
|
||||
|
||||
/* now mark all the members */
|
||||
|
||||
//std::set<RsGxsId> members = cg.mInvitedMembers;
|
||||
|
||||
std::map<uint32_t,CircleUpdateOrder>::iterator it = mCircleUpdates.find(token) ;
|
||||
|
||||
if(it == mCircleUpdates.end())
|
||||
{
|
||||
std::cerr << "(EE) Cannot find token " << token << " to perform group update!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
if(it->second.action == CircleUpdateOrder::GRANT_MEMBERSHIP)
|
||||
cg.mInvitedMembers.insert(it->second.gxs_id) ;
|
||||
else if(it->second.action == CircleUpdateOrder::REVOKE_MEMBERSHIP)
|
||||
cg.mInvitedMembers.erase(it->second.gxs_id) ;
|
||||
else
|
||||
{
|
||||
std::cerr << "(EE) unrecognised membership action to perform: " << it->second.action << "!" << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
uint32_t token2 ;
|
||||
rsGxsCircles->updateGroup(token2,cg) ;
|
||||
|
||||
mCircleUpdates.erase(it) ;
|
||||
}
|
||||
|
98
retroshare-gui/src/gui/feeds/GxsCircleItem.h
Normal file
98
retroshare-gui/src/gui/feeds/GxsCircleItem.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Retroshare Gxs Feed Item
|
||||
*
|
||||
* Copyright 2014 RetroShare Team
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License Version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA.
|
||||
*
|
||||
* Please report all bugs and problems to "retroshare@lunamutt.com".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _GXSCIRCLEITEM_H
|
||||
#define _GXSCIRCLEITEM_H
|
||||
|
||||
#include <retroshare/rsgxscircles.h>
|
||||
#include "FeedItem.h"
|
||||
|
||||
#include "util/TokenQueue.h"
|
||||
|
||||
namespace Ui {
|
||||
class GxsCircleItem;
|
||||
}
|
||||
|
||||
class FeedHolder;
|
||||
|
||||
struct CircleUpdateOrder
|
||||
{
|
||||
enum { UNKNOWN_ACTION=0x00, GRANT_MEMBERSHIP=0x01, REVOKE_MEMBERSHIP=0x02 };
|
||||
|
||||
uint32_t token ;
|
||||
RsGxsId gxs_id ;
|
||||
uint32_t action ;
|
||||
};
|
||||
|
||||
|
||||
class GxsCircleItem : public FeedItem, public TokenResponse
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/** Default Constructor */
|
||||
GxsCircleItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsCircleId &circleId, const RsGxsId &gxsId, const uint32_t type);
|
||||
virtual ~GxsCircleItem();
|
||||
|
||||
bool isSame(const RsGxsCircleId &circleId, const RsGxsId &gxsId, uint32_t type);
|
||||
|
||||
void loadRequest(const TokenQueue *queue, const TokenRequest &req);
|
||||
|
||||
|
||||
protected:
|
||||
/* FeedItem */
|
||||
virtual void doExpand(bool /*open*/) {}
|
||||
|
||||
void updateCircleGroup(const uint32_t& token);
|
||||
|
||||
|
||||
|
||||
private slots:
|
||||
/* default stuff */
|
||||
void removeItem();
|
||||
|
||||
void showCircleDetails();
|
||||
void acceptCircleSubscription();
|
||||
void grantCircleMembership() ;
|
||||
void revokeCircleMembership();
|
||||
|
||||
private:
|
||||
void setup();
|
||||
|
||||
FeedHolder *mFeedHolder;
|
||||
uint32_t mFeedId;
|
||||
uint32_t mType;
|
||||
|
||||
RsGxsCircleId mCircleId;
|
||||
RsGxsId mGxsId;
|
||||
|
||||
TokenQueue *mCircleQueue;
|
||||
std::map<uint32_t, CircleUpdateOrder> mCircleUpdates ;
|
||||
|
||||
|
||||
/** Qt Designer generated object */
|
||||
Ui::GxsCircleItem *ui;
|
||||
};
|
||||
|
||||
#endif
|
298
retroshare-gui/src/gui/feeds/GxsCircleItem.ui
Normal file
298
retroshare-gui/src/gui/feeds/GxsCircleItem.ui
Normal file
@ -0,0 +1,298 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GxsCircleItem</class>
|
||||
<widget class="QWidget" name="GxsCircleItem">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>618</width>
|
||||
<height>96</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="GxsCircleItemGLayout">
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>215</red>
|
||||
<green>215</green>
|
||||
<blue>215</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>215</red>
|
||||
<green>215</green>
|
||||
<blue>215</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>215</red>
|
||||
<green>215</green>
|
||||
<blue>215</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>215</red>
|
||||
<green>215</green>
|
||||
<blue>215</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>215</red>
|
||||
<green>215</green>
|
||||
<blue>215</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>215</red>
|
||||
<green>215</green>
|
||||
<blue>215</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="frameGLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="topGLayout">
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<widget class="QLabel" name="logoLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>70</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../icons.qrc">:/icons/svg/circles.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="nameHLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="titleLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<italic>true</italic>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Circle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="text">
|
||||
<string notr="true">name</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="nameHSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="toolbarHLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="gxsIdLabel">
|
||||
<property name="text">
|
||||
<string notr="true">name</string>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="tollbarHSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>254</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="acceptButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/accepted16.png</normaloff>:/images/accepted16.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="revokeButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/cancel.png</normaloff>:/images/cancel.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="expandButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Details</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/edit_add24.png</normaloff>:/images/edit_add24.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="clearButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::NoFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove Item</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images.qrc">
|
||||
<normaloff>:/images/close_normal.png</normaloff>:/images/close_normal.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -162,6 +162,7 @@ NotifyPage::NotifyPage(QWidget * parent, Qt::WindowFlags flags)
|
||||
connect(ui.message_ConnectAttempt, SIGNAL(toggled(bool)), this, SLOT(updateMessageFlags())) ;
|
||||
|
||||
connect(ui.notify_Peers, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
|
||||
connect(ui.notify_Circles, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
|
||||
connect(ui.notify_Channels, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
|
||||
connect(ui.notify_Forums, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
|
||||
connect(ui.notify_Posted, SIGNAL(toggled(bool)), this, SLOT(updateNewsFeedFlags()));
|
||||
@ -195,6 +196,8 @@ uint NotifyPage::getNewsFlags()
|
||||
|
||||
if (ui.notify_Peers->isChecked())
|
||||
newsFlags |= RS_FEED_TYPE_PEER;
|
||||
if (ui.notify_Circles->isChecked())
|
||||
newsFlags |= RS_FEED_TYPE_CIRCLE;
|
||||
if (ui.notify_Channels->isChecked())
|
||||
newsFlags |= RS_FEED_TYPE_CHANNEL;
|
||||
if (ui.notify_Forums->isChecked())
|
||||
@ -324,6 +327,7 @@ void NotifyPage::load()
|
||||
whileBlocking(ui.popup_ConnectAttempt)->setChecked(notifyflags & RS_POPUP_CONNECT_ATTEMPT);
|
||||
|
||||
whileBlocking(ui.notify_Peers)->setChecked(newsflags & RS_FEED_TYPE_PEER);
|
||||
whileBlocking(ui.notify_Circles)->setChecked(newsflags & RS_FEED_TYPE_CIRCLE);
|
||||
whileBlocking(ui.notify_Channels)->setChecked(newsflags & RS_FEED_TYPE_CHANNEL);
|
||||
whileBlocking(ui.notify_Forums)->setChecked(newsflags & RS_FEED_TYPE_FORUM);
|
||||
whileBlocking(ui.notify_Posted)->setChecked(newsflags & RS_FEED_TYPE_POSTED);
|
||||
|
@ -51,6 +51,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="notify_Circles">
|
||||
<property name="text">
|
||||
<string>Circles</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="notify_Channels">
|
||||
<property name="text">
|
||||
|
@ -1635,7 +1635,7 @@ void ServerPage::updateStatusBob()
|
||||
ui.pbBobStart->setToolTip("BOB is not accessible");
|
||||
ui.pbBobRestart->setEnabled(false);
|
||||
ui.pbBobRestart->setToolTip("BOB is not accessible");
|
||||
ui.pbBobStop->setEnabled(false);
|
||||
// don't disable the stop button! (in case bob is running you are otherwise unable to stop and disable it)
|
||||
ui.pbBobStop->setToolTip("BOB is not accessible");
|
||||
} else {
|
||||
ui.pbBobStart->setToolTip("");
|
||||
|
@ -73,7 +73,7 @@ static const int GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ = 30 ; // never req
|
||||
#define DEBUG_GXSTRANS_STATS 1
|
||||
|
||||
GxsTransportStatistics::GxsTransportStatistics(QWidget *parent)
|
||||
: RsAutoUpdatePage(2000,parent)
|
||||
: RsGxsUpdateBroadcastPage(rsGxsTrans,parent)
|
||||
{
|
||||
setupUi(this) ;
|
||||
|
||||
@ -93,6 +93,7 @@ GxsTransportStatistics::GxsTransportStatistics(QWidget *parent)
|
||||
|
||||
// load settings
|
||||
processSettings(true);
|
||||
updateDisplay(true);
|
||||
}
|
||||
|
||||
GxsTransportStatistics::~GxsTransportStatistics()
|
||||
@ -139,19 +140,14 @@ void GxsTransportStatistics::CustomPopupMenu( QPoint )
|
||||
contextMnu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void GxsTransportStatistics::updateDisplay()
|
||||
void GxsTransportStatistics::updateDisplay(bool)
|
||||
{
|
||||
time_t now = time(NULL) ;
|
||||
time_t now = time(NULL) ;
|
||||
|
||||
if(mLastGroupReqTS + GXSTRANS_STATISTICS_DELAY_BETWEEN_GROUP_REQ < now)
|
||||
{
|
||||
requestGroupMeta();
|
||||
mLastGroupReqTS = now ;
|
||||
}
|
||||
std::cerr << "GxsTransportStatistics::updateDisplay()" << std::endl;
|
||||
|
||||
//_tst_CW->updateContent() ;
|
||||
|
||||
updateContent();
|
||||
requestGroupMeta();
|
||||
mLastGroupReqTS = now ;
|
||||
}
|
||||
|
||||
QString GxsTransportStatistics::getPeerName(const RsPeerId &peer_id)
|
||||
@ -319,6 +315,8 @@ void GxsTransportStatistics::loadRequest(const TokenQueue *queue, const TokenReq
|
||||
std::cerr << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
updateContent();
|
||||
}
|
||||
|
||||
void GxsTransportStatistics::requestGroupMeta()
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "util/TokenQueue.h"
|
||||
#include "RsAutoUpdatePage.h"
|
||||
#include "ui_GxsTransportStatistics.h"
|
||||
#include "gui/gxs/RsGxsUpdateBroadcastPage.h"
|
||||
|
||||
class GxsTransportStatisticsWidget ;
|
||||
class UIStateHelper;
|
||||
@ -45,7 +46,7 @@ public:
|
||||
std::vector<RsMsgMetaData> messages_metas ;
|
||||
};
|
||||
|
||||
class GxsTransportStatistics: public RsAutoUpdatePage, public TokenResponse, public Ui::GxsTransportStatistics
|
||||
class GxsTransportStatistics: public RsGxsUpdateBroadcastPage, public TokenResponse, public Ui::GxsTransportStatistics
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -66,6 +67,7 @@ private slots:
|
||||
void personDetails();
|
||||
|
||||
private:
|
||||
void updateDisplay(bool complete) ;
|
||||
void loadGroupMeta(const uint32_t& token);
|
||||
void loadGroupStat(const uint32_t& token);
|
||||
void loadMsgMeta(const uint32_t& token);
|
||||
@ -77,8 +79,6 @@ private:
|
||||
void processSettings(bool bLoad);
|
||||
bool m_bProcessSettings;
|
||||
|
||||
virtual void updateDisplay() ;
|
||||
|
||||
GxsTransportStatisticsWidget *_tst_CW ;
|
||||
TokenQueue *mTransQueue ;
|
||||
UIStateHelper *mStateHelper;
|
||||
|
@ -13,51 +13,8 @@
|
||||
<property name="windowTitle">
|
||||
<string>Router Statistics</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Gxs Transport Groups:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="groupTreeWidget">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Group ID / Author</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Number of messages / Publish TS</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Total size of messages</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Subscribed</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Popularity</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>GroupBox</string>
|
||||
@ -65,6 +22,12 @@
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
@ -114,6 +77,49 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Gxs Transport Groups:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTreeWidget" name="groupTreeWidget">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Group ID / Author</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Number of messages / Publish TS</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Total size of messages</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Subscribed</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Popularity</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -142,7 +142,7 @@ void TurtleRouterDialog::updateTunnelRequests( const std::vector<std::vector<std
|
||||
num /= 1024.0f,++k;
|
||||
sprintf(tmp,"%3.2f %s",num,units[k].c_str()) ;
|
||||
|
||||
QString str = tr("Tunnel id") + ": " + QString::fromUtf8(tunnels_info[i][0].c_str()) + "\t [" + QString::fromUtf8(tunnels_info[i][2].c_str()) + "] --> [" + QString::fromUtf8(tunnels_info[i][1].c_str()) + "]\t\t " + tr("last transfer") + ": " + QString::fromStdString(tunnels_info[i][4]) + " " + "\t " + tr("Speed") + ": " + QString::fromStdString(tmp) ;
|
||||
QString str = tr("Tunnel id") + ": " + QString::fromUtf8(tunnels_info[i][0].c_str()) + "\t" + tr("Speed") + ": " + QString::fromStdString(tmp) + "\t " + tr("last transfer") + ": " + QString::fromStdString(tunnels_info[i][4])+ "\t" + QString::fromUtf8(tunnels_info[i][2].c_str()) + " -> " + QString::fromUtf8(tunnels_info[i][1].c_str());
|
||||
stl.clear() ;
|
||||
stl.push_back(str) ;
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(stl);
|
||||
|
@ -551,6 +551,7 @@ HEADERS += rshare.h \
|
||||
gui/NewsFeed.h \
|
||||
gui/feeds/FeedItem.h \
|
||||
gui/feeds/FeedHolder.h \
|
||||
gui/feeds/GxsCircleItem.h \
|
||||
gui/feeds/PeerItem.h \
|
||||
gui/feeds/MsgItem.h \
|
||||
gui/feeds/ChatMsgItem.h \
|
||||
@ -656,6 +657,7 @@ FORMS += gui/StartDialog.ui \
|
||||
gui/advsearch/AdvancedSearchDialog.ui \
|
||||
gui/advsearch/expressionwidget.ui \
|
||||
gui/NewsFeed.ui \
|
||||
gui/feeds/GxsCircleItem.ui \
|
||||
gui/feeds/PeerItem.ui \
|
||||
gui/feeds/MsgItem.ui \
|
||||
gui/feeds/ChatMsgItem.ui \
|
||||
@ -685,7 +687,7 @@ FORMS += gui/StartDialog.ui \
|
||||
gui/statistics/StatisticsWindow.ui \
|
||||
gui/statistics/BwCtrlWindow.ui \
|
||||
gui/statistics/RttStatistics.ui \
|
||||
gui/GetStartedDialog.ui \
|
||||
gui/GetStartedDialog.ui
|
||||
|
||||
|
||||
# gui/ForumsDialog.ui \
|
||||
@ -900,6 +902,7 @@ SOURCES += main.cpp \
|
||||
gui/NewsFeed.cpp \
|
||||
gui/feeds/FeedItem.cpp \
|
||||
gui/feeds/FeedHolder.cpp \
|
||||
gui/feeds/GxsCircleItem.cpp \
|
||||
gui/feeds/PeerItem.cpp \
|
||||
gui/feeds/MsgItem.cpp \
|
||||
gui/feeds/ChatMsgItem.cpp \
|
||||
|
76
retroshare-qml-app/src/AvatarOrColorHash.qml
Normal file
76
retroshare-qml-app/src/AvatarOrColorHash.qml
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* RetroShare Android QML App
|
||||
* Copyright (C) 2017 Gioacchino Mazzurco <gio@eigenlab.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.7
|
||||
|
||||
|
||||
Item
|
||||
{
|
||||
id: compRoot
|
||||
|
||||
property string gxs_id
|
||||
|
||||
height: 130
|
||||
width: height
|
||||
|
||||
|
||||
////////////// The following should be considered privates /////////////////////
|
||||
|
||||
property bool has_avatar: false
|
||||
property int avatarAttemptCnt: 0
|
||||
function getDetails()
|
||||
{
|
||||
++compRoot.avatarAttemptCnt
|
||||
rsApi.request(
|
||||
"/identity/get_identity_details",
|
||||
JSON.stringify({ gxs_id: compRoot.gxs_id }),
|
||||
function(par)
|
||||
{
|
||||
var jData = JSON.parse(par.response).data
|
||||
setDetails(jData)
|
||||
if(!compRoot.has_avatar &&
|
||||
compRoot.avatarAttemptCnt < 3) getDetails()
|
||||
})
|
||||
}
|
||||
function setDetails(data)
|
||||
{
|
||||
compRoot.has_avatar = data.avatar.length > 0
|
||||
if(compRoot.has_avatar)
|
||||
{
|
||||
contactAvatar.source =
|
||||
"data:image/png;base64," + data.avatar
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: if(visible && !has_avatar) getDetails()
|
||||
onVisibleChanged: if(visible && !has_avatar) getDetails()
|
||||
|
||||
Image
|
||||
{
|
||||
id: contactAvatar
|
||||
anchors.fill: parent
|
||||
visible: compRoot.has_avatar
|
||||
}
|
||||
|
||||
ColorHash
|
||||
{
|
||||
anchors.fill: parent
|
||||
visible: !compRoot.has_avatar
|
||||
hash: compRoot.gxs_id
|
||||
}
|
||||
}
|
@ -28,21 +28,20 @@ Item
|
||||
property var md
|
||||
property bool is_contact: cntDt.md.is_contact
|
||||
|
||||
ColorHash
|
||||
AvatarOrColorHash
|
||||
{
|
||||
id: colorHash
|
||||
id: topFace
|
||||
|
||||
gxs_id: cntDt.md.gxs_id
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
height: 150
|
||||
hash: cntDt.md.gxs_id
|
||||
}
|
||||
|
||||
Column
|
||||
{
|
||||
anchors.top: colorHash.bottom
|
||||
anchors.top: topFace.bottom
|
||||
anchors.topMargin: 6
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
@ -54,6 +53,13 @@ Item
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 6
|
||||
|
||||
ColorHash
|
||||
{
|
||||
hash: cntDt.md.gxs_id
|
||||
height: parent.height - 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Text
|
||||
{
|
||||
text: cntDt.md.name
|
||||
@ -62,7 +68,6 @@ Item
|
||||
|
||||
Image
|
||||
{
|
||||
|
||||
source: cntDt.is_contact ?
|
||||
"qrc:/icons/rating.png" :
|
||||
"qrc:/icons/rating-unrated.png"
|
||||
|
@ -25,6 +25,7 @@
|
||||
<file>TrustedNodeDetails.qml</file>
|
||||
<file>ClipboardWrapper.qml</file>
|
||||
<file>ContactDetails.qml</file>
|
||||
<file>ColorHash.qml</file>
|
||||
<file>icons/rating-unrated.png</file>
|
||||
<file>icons/rating.png</file>
|
||||
<file>TimedPopup.qml</file>
|
||||
|
Loading…
Reference in New Issue
Block a user