Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions src/gxs/rsgenexchange.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,14 @@ class RsGenExchange : public RsNxsObserver, public RsTickingThread, public RsGxs
*/
virtual void service_tick() = 0;

/*!
*
* @return handle to token service handle for making
* request to this gxs service
*/
RsTokenService* getTokenService();
void threadTick() override; /// @see RsTickingThread
/*!
*
* @return handle to token service handle for making
* request to this gxs service
*/
RsTokenService* getTokenService();

void threadTick() override; /// @see RsTickingThread

/*!
* Policy bit pattern portion
Expand Down
53 changes: 52 additions & 1 deletion src/retroshare/rsgxsifacehelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class RsGxsIfaceHelper
mGxs(gxs), mTokenService(*gxs.getTokenService()), mMtx("GxsIfaceHelper")
{}

~RsGxsIfaceHelper() = default;
virtual ~RsGxsIfaceHelper() = default;

#ifdef TO_REMOVE
/*!
Expand Down Expand Up @@ -527,6 +527,57 @@ class RsGxsIfaceHelper
return st;
}

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two methods already exist (in the same form but slightly different names) in several GXS services that all derive from RsGxsIFaceHelper. It's fine to move them here indeed (since they do the same for all services) but they should be removed from the services (so you can keep the names without the "Blocking" suffix and therefore compilation compatibility).
See for instance p3GxsChannels -> RsGxsChannels -> RsGxsIFaceHelper and the method is p3GxsChannels::getChannelStatistics()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the helper methods to drop the ‘Blocking’ suffix (getServiceStatistics / getGroupStatistics) and kept the wiki call site aligned. Service-specific wrappers are still present where they’re part of public interfaces, but they can now delegate to the helper without new naming churn

* @brief Get service statistics synchronously (blocking call)
* @param stats Output parameter for service statistics
* @param maxWait Maximum time to wait for the operation in milliseconds (default: 10000ms)
* @return true if statistics were successfully retrieved, false on timeout or error
*
* This is a convenience wrapper around the async token-based API.
* It blocks the calling thread until results are available or timeout occurs.
* Use this for simple operations like notification counting in GUI code.
*/
bool getServiceStatistics(
GxsServiceStatistic& stats,
std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000))
{
uint32_t token;
if (!requestServiceStatistic(token))
return false;

auto status = waitToken(token, maxWait);
if (status != RsTokenService::COMPLETE)
return false;

return getServiceStatistic(token, stats);
}

/**
* @brief Get group statistics synchronously (blocking call)
* @param grpId The group ID to get statistics for
* @param stats Output parameter for group statistics
* @param maxWait Maximum time to wait for the operation in milliseconds (default: 10000ms)
* @return true if statistics were successfully retrieved, false on timeout or error
*
* This is a convenience wrapper around the async token-based API.
* It blocks the calling thread until results are available or timeout occurs.
*/
bool getGroupStatistics(
const RsGxsGroupId& grpId,
GxsGroupStatistic& stats,
std::chrono::milliseconds maxWait = std::chrono::milliseconds(10000))
{
uint32_t token;
if (!requestGroupStatistic(token, grpId))
return false;

auto status = waitToken(token, maxWait);
if (status != RsTokenService::COMPLETE)
return false;

return getGroupStatistic(token, stats);
}

private:
RsGxsIface& mGxs;
RsTokenService& mTokenService;
Expand Down
91 changes: 89 additions & 2 deletions src/retroshare/rswiki.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <string>
#include <list>
#include <vector>
#include <map>
#include <iostream>

#include "retroshare/rstokenservice.h"
Expand Down Expand Up @@ -67,8 +68,14 @@ extern RsWiki *rsWiki;
/** Wiki Event Codes */
enum class RsWikiEventCode : uint8_t
{
UPDATED_SNAPSHOT = 0x01,
UPDATED_COLLECTION = 0x02
UNKNOWN = 0x00,
UPDATED_SNAPSHOT = 0x01, // Existing page modified
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can add "UNKNOWN = 0x00," so that we can initialize this type with some value that "means" something.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added UNKNOWN = 0x00 to RsWikiEventCode to allow meaningful default initialization

UPDATED_COLLECTION = 0x02, // Existing wiki group modified
NEW_SNAPSHOT = 0x03, // First-time page creation
NEW_COLLECTION = 0x04, // New wiki group creation
SUBSCRIBE_STATUS_CHANGED = 0x05, // User subscribed/unsubscribed
NEW_COMMENT = 0x06, // New comment added
READ_STATUS_CHANGED = 0x07 // Read/unread status changed
};

/** Specific Wiki Event for UI updates */
Expand All @@ -80,12 +87,14 @@ struct RsGxsWikiEvent : public RsEvent

RsWikiEventCode mWikiEventCode;
RsGxsGroupId mWikiGroupId;
RsGxsMessageId mWikiMsgId;

void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx) override
{
RsEvent::serial_process(j, ctx);
RS_SERIAL_PROCESS(mWikiEventCode);
RS_SERIAL_PROCESS(mWikiGroupId);
RS_SERIAL_PROCESS(mWikiMsgId);
}
};

Expand All @@ -94,6 +103,8 @@ struct RsWikiCollection: RsGxsGenericGroupData
std::string mDescription;
std::string mCategory;
std::string mHashTags;
// Map of moderator IDs to their termination timestamps (0 means active).
std::map<RsGxsId, rstime_t> mModeratorTerminationDates;
};

class RsWikiSnapshot
Expand Down Expand Up @@ -135,6 +146,82 @@ class RsWiki: public RsGxsIfaceHelper
virtual bool createCollection(RsWikiCollection &collection) = 0;
virtual bool updateCollection(const RsWikiCollection &collection) = 0;
virtual bool getCollections(const std::list<RsGxsGroupId> groupIds, std::vector<RsWikiCollection> &groups) = 0;

/* Moderator Management */
/**
* @brief Add a moderator to a wiki collection
* @param grpId The ID of the wiki collection/group
* @param moderatorId The ID of the user to add as moderator
* @return true if the moderator was successfully added, false otherwise
*/
virtual bool addModerator(const RsGxsGroupId& grpId, const RsGxsId& moderatorId) = 0;

/**
* @brief Remove a moderator from a wiki collection
* @param grpId The ID of the wiki collection/group
* @param moderatorId The ID of the moderator to remove
* @return true if the moderator was successfully removed, false otherwise
*/
virtual bool removeModerator(const RsGxsGroupId& grpId, const RsGxsId& moderatorId) = 0;

/**
* @brief Get the list of moderators for a wiki collection
* @param grpId The ID of the wiki collection/group
* @param moderators Output parameter that will contain the list of moderator IDs
* @return true if the list was successfully retrieved, false otherwise
*/
virtual bool getModerators(const RsGxsGroupId& grpId, std::list<RsGxsId>& moderators) = 0;

/**
* @brief Check if a user is an active moderator at a given time
* @param grpId The ID of the wiki collection/group
* @param authorId The ID of the user to check
* @param editTime The time at which to check moderator status
* @return true if the user is an active moderator at the specified time, false otherwise
*/
virtual bool isActiveModerator(const RsGxsGroupId& grpId, const RsGxsId& authorId, rstime_t editTime) = 0;

/* Content fetching for merge operations (Todo 3) */
/**
* @brief Get the latest page content for a snapshot lineage.
* @param grpId The group ID of the wiki collection.
* @param snapshotId The message ID of the snapshot (any edit in the lineage).
* @param content Output parameter for page content
* @return true if snapshot found and content retrieved
*/
virtual bool getSnapshotContent(const RsGxsGroupId& grpId,
const RsGxsMessageId& snapshotId,
std::string& content) = 0;

/**
* @brief Get page content from multiple snapshots efficiently (bulk fetch)
* @param grpId The group ID of the wiki collection.
* @param snapshotIds Vector of snapshot message IDs to fetch
* @param contents Output map of snapshotId -> content
* @return true if the operation completed successfully (contents may be empty)
*/
virtual bool getSnapshotsContent(const RsGxsGroupId& grpId,
const std::vector<RsGxsMessageId>& snapshotIds,
std::map<RsGxsMessageId, std::string>& contents) = 0;

/* Notification support */
/**
* @brief Get Wiki service statistics for notification counting
* @param stats Output parameter for service statistics including unread message counts
* @return true if statistics were successfully retrieved, false otherwise
*
* This method is designed for GUI notification systems to efficiently count
* new/unread messages across all Wiki collections.
*/
virtual bool getWikiStatistics(GxsServiceStatistic& stats) = 0;

/**
* @brief Update read status for a wiki snapshot/comment
* @param token Output token for async processing
* @param msgId Group/message identifier pair to update
* @param read True to mark as read, false to mark as unread
*/
virtual void setMessageReadStatus(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, bool read) = 0;
};

#endif
3 changes: 2 additions & 1 deletion src/rsitems/rswikiitems.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ void RsGxsWikiCollectionItem::clear()
collection.mDescription.clear();
collection.mCategory.clear();
collection.mHashTags.clear();
collection.mModeratorTerminationDates.clear();
}

void RsGxsWikiCollectionItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
{
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_DESCR ,collection.mDescription,"collection.mDescription") ;
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_CATEGORY,collection.mCategory ,"collection.mCategory") ;
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_HASH_TAG,collection.mHashTags ,"collection.mHashTags") ;
RsTypeSerializer::serial_process(j,ctx,collection.mModeratorTerminationDates,"collection.mModeratorTerminationDates") ;
}

void RsGxsWikiSnapshotItem::clear()
Expand All @@ -77,4 +79,3 @@ void RsGxsWikiCommentItem::serial_process(RsGenericSerializer::SerializeJob j,Rs
{
RsTypeSerializer::serial_process(j,ctx,TLV_TYPE_STR_COMMENT,comment.mComment,"comment.mComment") ;
}

Loading