8#include "imgui/imgui.h"
16 version_mgr_(nullptr),
17 approval_mgr_(nullptr),
19 selected_rom_sync_(-1),
20 selected_snapshot_(-1),
21 selected_proposal_(-1),
22 show_sync_details_(false),
23 show_snapshot_preview_(true),
25 filter_pending_only_(false) {
31 colors_.sync_applied = ImVec4(0.2f, 0.8f, 0.2f, 1.0f);
32 colors_.sync_pending = ImVec4(0.8f, 0.8f, 0.2f, 1.0f);
33 colors_.sync_error = ImVec4(0.8f, 0.2f, 0.2f, 1.0f);
34 colors_.proposal_pending = ImVec4(0.7f, 0.7f, 0.7f, 1.0f);
35 colors_.proposal_approved = ImVec4(0.2f, 0.8f, 0.2f, 1.0f);
36 colors_.proposal_rejected = ImVec4(0.8f, 0.3f, 0.3f, 1.0f);
37 colors_.proposal_applied = ImVec4(0.2f, 0.6f, 0.8f, 1.0f);
43 if (snapshot.texture_id) {
46 snapshot.texture_id =
nullptr;
61 if (!ImGui::Begin(
"Collaboration", p_open, ImGuiWindowFlags_None)) {
67 if (ImGui::BeginTabBar(
"CollaborationTabs")) {
68 if (ImGui::BeginTabItem(
"ROM Sync")) {
74 if (ImGui::BeginTabItem(
"Version History")) {
80 if (ImGui::BeginTabItem(
"Snapshots")) {
86 if (ImGui::BeginTabItem(
"Proposals")) {
92 if (ImGui::BeginTabItem(
"đ Approvals")) {
105 ImGui::TextWrapped(
"ROM Synchronization History");
109 if (ImGui::Button(
"Clear History")) {
120 int applied_count = 0;
121 int pending_count = 0;
125 if (sync.applied) applied_count++;
126 else if (!sync.error_message.empty()) error_count++;
127 else pending_count++;
130 ImGui::Text(
"Total: %zu | ",
rom_syncs_.size());
132 ImGui::TextColored(
colors_.sync_applied,
"Applied: %d", applied_count);
134 ImGui::TextColored(
colors_.sync_pending,
"Pending: %d", pending_count);
136 ImGui::TextColored(
colors_.sync_error,
"Errors: %d", error_count);
141 if (ImGui::BeginChild(
"SyncList", ImVec2(0, 0),
true)) {
142 for (
size_t i = 0; i <
rom_syncs_.size(); ++i) {
146 if (
auto_scroll_ && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
147 ImGui::SetScrollHereY(1.0f);
154 ImGui::TextWrapped(
"Shared Snapshots Gallery");
158 if (ImGui::Button(
"Clear Gallery")) {
169 if (ImGui::BeginChild(
"SnapshotGrid", ImVec2(0, 0),
true)) {
170 float thumbnail_size = 150.0f;
171 float padding = 10.0f;
172 float cell_size = thumbnail_size + padding;
174 int columns = std::max(1, (
int)((ImGui::GetContentRegionAvail().x) / cell_size));
176 for (
size_t i = 0; i <
snapshots_.size(); ++i) {
180 std::string sender_lower =
snapshots_[i].sender;
181 std::transform(search_lower.begin(), search_lower.end(), search_lower.begin(), ::tolower);
182 std::transform(sender_lower.begin(), sender_lower.end(), sender_lower.begin(), ::tolower);
184 if (sender_lower.find(search_lower) == std::string::npos &&
185 snapshots_[i].snapshot_type.find(search_lower) == std::string::npos) {
193 if ((i + 1) % columns != 0 && i <
snapshots_.size() - 1) {
202 ImGui::TextWrapped(
"AI Proposals & Suggestions");
206 if (ImGui::Button(
"Clear All")) {
217 int pending = 0, approved = 0, rejected = 0, applied = 0;
219 if (proposal.status ==
"pending") pending++;
220 else if (proposal.status ==
"approved") approved++;
221 else if (proposal.status ==
"rejected") rejected++;
222 else if (proposal.status ==
"applied") applied++;
227 ImGui::TextColored(
colors_.proposal_pending,
" | Pending: %d", pending);
229 ImGui::TextColored(
colors_.proposal_approved,
" | Approved: %d", approved);
231 ImGui::TextColored(
colors_.proposal_rejected,
" | Rejected: %d", rejected);
233 ImGui::TextColored(
colors_.proposal_applied,
" | Applied: %d", applied);
238 if (ImGui::BeginChild(
"ProposalList", ImVec2(0, 0),
true)) {
239 for (
size_t i = 0; i <
proposals_.size(); ++i) {
247 std::string sender_lower =
proposals_[i].sender;
248 std::string desc_lower =
proposals_[i].description;
249 std::transform(search_lower.begin(), search_lower.end(), search_lower.begin(), ::tolower);
250 std::transform(sender_lower.begin(), sender_lower.end(), sender_lower.begin(), ::tolower);
251 std::transform(desc_lower.begin(), desc_lower.end(), desc_lower.begin(), ::tolower);
253 if (sender_lower.find(search_lower) == std::string::npos &&
254 desc_lower.find(search_lower) == std::string::npos) {
266 ImGui::PushID(index);
270 const char* status_icon;
273 status_color =
colors_.sync_applied;
274 status_icon =
"[â]";
276 status_color =
colors_.sync_error;
277 status_icon =
"[â]";
279 status_color =
colors_.sync_pending;
280 status_icon =
"[âˇ]";
283 ImGui::TextColored(status_color,
"%s", status_icon);
287 ImGui::Text(
"%s - %s (%s)",
295 ImGui::TextWrapped(
"ROM Hash: %s", entry.
rom_hash.substr(0, 16).c_str());
307 ImGui::PushID(index);
313 ImGui::Image(entry.
texture_id, ImVec2(150, 150));
316 ImGui::BeginChild(
"SnapshotPlaceholder", ImVec2(150, 150),
true);
317 ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 50);
323 ImGui::TextWrapped(
"%s", entry.
sender.c_str());
328 if (ImGui::SmallButton(
"View")) {
333 if (ImGui::SmallButton(
"Export")) {
343 ImGui::PushID(index);
349 ImGui::TextColored(color,
"%s", icon);
353 bool is_open = ImGui::TreeNode(entry.
description.c_str());
358 ImGui::Text(
"From: %s", entry.
sender.c_str());
360 ImGui::Text(
"Status: %s", entry.
status.c_str());
368 if (entry.
status ==
"pending") {
370 if (ImGui::Button(
"â Approve")) {
374 if (ImGui::Button(
"â Reject")) {
378 if (ImGui::Button(
"âļ Apply Now")) {
405 if (proposal.proposal_id == proposal_id) {
406 proposal.status = status;
420 if (proposal.proposal_id == proposal_id) {
428 std::time_t time = timestamp / 1000;
429 std::tm* tm = std::localtime(&time);
432 std::strftime(buffer,
sizeof(buffer),
"%H:%M:%S", tm);
433 return std::string(buffer);
437 const char* units[] = {
"B",
"KB",
"MB",
"GB"};
439 double size =
static_cast<double>(bytes);
441 while (size >= 1024.0 && unit_index < 3) {
447 snprintf(buffer,
sizeof(buffer),
"%.1f %s", size, units[unit_index]);
448 return std::string(buffer);
452 if (status ==
"pending")
return "[âˇ]";
453 if (status ==
"approved")
return "[â]";
454 if (status ==
"rejected")
return "[â]";
455 if (status ==
"applied")
return "[âĻ]";
460 if (status ==
"pending")
return colors_.proposal_pending;
461 if (status ==
"approved")
return colors_.proposal_approved;
462 if (status ==
"rejected")
return colors_.proposal_rejected;
463 if (status ==
"applied")
return colors_.proposal_applied;
464 return ImVec4(0.7f, 0.7f, 0.7f, 1.0f);
469 ImGui::TextWrapped(
"Version management not initialized");
473 ImGui::TextWrapped(
"ROM Version History & Protection");
478 ImGui::Text(
"Total Snapshots: %zu", stats.total_snapshots);
480 ImGui::TextColored(
colors_.sync_applied,
"Safe Points: %zu", stats.safe_points);
482 ImGui::TextColored(
colors_.sync_pending,
"Auto-Backups: %zu", stats.auto_backups);
484 ImGui::Text(
"Storage Used: %s",
FormatFileSize(stats.total_storage_bytes).c_str());
489 if (ImGui::Button(
"đž Create Checkpoint")) {
497 if (ImGui::Button(
"đĄī¸ Mark Current as Safe Point")) {
502 if (ImGui::Button(
"đ Check for Corruption")) {
510 if (ImGui::BeginChild(
"VersionList", ImVec2(0, 0),
true)) {
513 for (
size_t i = 0; i < snapshots.size(); ++i) {
522 ImGui::TextWrapped(
"Approval management not initialized");
526 ImGui::TextWrapped(
"Proposal Approval System");
532 if (pending.empty()) {
533 ImGui::TextWrapped(
"No proposals pending approval.");
537 ImGui::Text(
"Pending Proposals: %zu", pending.size());
540 if (ImGui::BeginChild(
"ApprovalList", ImVec2(0, 0),
true)) {
541 for (
size_t i = 0; i < pending.size(); ++i) {
550 ImGui::PushID(index);
561 color =
colors_.proposal_approved;
567 ImGui::TextColored(color,
"%s", icon);
571 bool is_open = ImGui::TreeNode(snapshot.
description.c_str());
576 ImGui::Text(
"Creator: %s", snapshot.
creator.c_str());
578 ImGui::Text(
"Hash: %s", snapshot.
rom_hash.substr(0, 16).c_str());
582 ImGui::TextColored(
colors_.sync_applied,
"â Safe Point (Host Verified)");
588 if (ImGui::Button(
"âŠī¸ Restore This Version")) {
593 if (!snapshot.
is_safe_point && ImGui::Button(
"đĄī¸ Mark as Safe")) {
597 if (!snapshot.
is_safe_point && ImGui::Button(
"đī¸ Delete")) {
611 ImGui::PushID(index);
614 ImGui::TextColored(
colors_.proposal_pending,
"[âŗ]");
618 std::string short_id = status.
proposal_id.substr(0, 8);
619 bool is_open = ImGui::TreeNode(absl::StrFormat(
"Proposal %s", short_id.c_str()).c_str());
625 ImGui::Text(
"Snapshot Before: %s", status.
snapshot_before.substr(0, 8).c_str());
628 ImGui::TextWrapped(
"Votes:");
630 for (
const auto& [username, approved] : status.
votes) {
631 ImVec4 vote_color = approved ?
colors_.proposal_approved :
colors_.proposal_rejected;
632 const char* vote_icon = approved ?
"â" :
"â";
633 ImGui::TextColored(vote_color,
" %s %s", vote_icon, username.c_str());
639 if (ImGui::Button(
"â Approve")) {
644 if (ImGui::Button(
"â Reject")) {
649 if (ImGui::Button(
"âŠī¸ Rollback")) {
The Rom class is used to load, save, and modify Rom data.
void RenderVersionHistoryTab()
std::string FormatFileSize(size_t bytes)
ProposalEntry * GetProposal(const std::string &proposal_id)
net::RomVersionManager * version_mgr_
void RenderVersionSnapshot(const net::RomSnapshot &snapshot, int index)
void RenderProposalEntry(const ProposalEntry &entry, int index)
std::string FormatTimestamp(int64_t timestamp)
void AddSnapshot(const SnapshotEntry &entry)
bool show_snapshot_preview_
void AddProposal(const ProposalEntry &entry)
void UpdateProposalStatus(const std::string &proposal_id, const std::string &status)
void RenderProposalsTab()
const char * GetProposalStatusIcon(const std::string &status)
std::vector< ProposalEntry > proposals_
void RenderSnapshotsTab()
void RenderSnapshotEntry(const SnapshotEntry &entry, int index)
void AddRomSync(const RomSyncEntry &entry)
void RenderApprovalProposal(const net::ProposalApprovalManager::ApprovalStatus &status, int index)
struct yaze::gui::CollaborationPanel::@0 colors_
ImVec4 GetProposalStatusColor(const std::string &status)
void Render(bool *p_open=nullptr)
std::vector< RomSyncEntry > rom_syncs_
net::ProposalApprovalManager * approval_mgr_
void RenderRomSyncEntry(const RomSyncEntry &entry, int index)
std::vector< SnapshotEntry > snapshots_
bool filter_pending_only_
void Initialize(Rom *rom, net::RomVersionManager *version_mgr, net::ProposalApprovalManager *approval_mgr)
Manages proposal approval workflow for collaborative sessions.
std::vector< ApprovalStatus > GetPendingProposals() const
Manages ROM versioning, snapshots, and rollback capabilities.
absl::StatusOr< std::string > CreateSnapshot(const std::string &description, const std::string &creator, bool is_checkpoint=false)
std::string GetCurrentHash() const
absl::StatusOr< bool > DetectCorruption()
absl::Status RestoreSnapshot(const std::string &snapshot_id)
absl::Status MarkAsSafePoint(const std::string &snapshot_id)
absl::Status DeleteSnapshot(const std::string &snapshot_id)
std::vector< RomSnapshot > GetSnapshots(bool safe_points_only=false) const
Main namespace for the application.
Represents an AI-generated proposal.
std::string proposal_data
Represents a ROM synchronization event.
std::string error_message
Represents a shared snapshot (image, map state, etc.)
std::string snapshot_type
std::string snapshot_before
std::map< std::string, bool > votes
Represents a versioned snapshot of ROM state.