GhostWipe report: chronological order, mobile layout, Ruby branding
Messages within each channel now sort oldest-first (history()/purge() return newest-first, which read backwards). Added a real mobile layout: below 700px the sidebar stacks above the message view and its channel list becomes a horizontally-scrolling chip strip instead of a cramped vertical column. Report title/footer and the Discord log embeds now carry Ruby branding alongside the GhostWipe module name. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
039e85d65a
commit
fdf41cfcbc
2 changed files with 41 additions and 7 deletions
|
|
@ -309,6 +309,9 @@ class GhostWipe(commands.Cog):
|
||||||
"messages": [],
|
"messages": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# channel.history()/purge() return newest-first; the report reads far
|
||||||
|
# more naturally in actual conversation order.
|
||||||
|
collected.sort(key=lambda m: m.created_at)
|
||||||
messages = [self._serialize_message(m) for m in collected]
|
messages = [self._serialize_message(m) for m in collected]
|
||||||
return {
|
return {
|
||||||
"id": str(channel.id),
|
"id": str(channel.id),
|
||||||
|
|
@ -541,7 +544,7 @@ class GhostWipe(commands.Cog):
|
||||||
if top:
|
if top:
|
||||||
breakdown = "\n".join(f"**{c['name']}** — {c['message_count']}" for c in top)
|
breakdown = "\n".join(f"**{c['name']}** — {c['message_count']}" for c in top)
|
||||||
embed.add_field(name="Per-Channel Breakdown", value=breakdown, inline=False)
|
embed.add_field(name="Per-Channel Breakdown", value=breakdown, inline=False)
|
||||||
embed.set_footer(text=f"GhostWipe v{self.__version__}")
|
embed.set_footer(text=f"Ruby · GhostWipe v{self.__version__}")
|
||||||
|
|
||||||
file_obj = None
|
file_obj = None
|
||||||
if conf["attach_html_report"]:
|
if conf["attach_html_report"]:
|
||||||
|
|
@ -903,7 +906,7 @@ class GhostWipe(commands.Cog):
|
||||||
f"{humanize_number(stats.get('total_messages_deleted', 0))} messages deleted",
|
f"{humanize_number(stats.get('total_messages_deleted', 0))} messages deleted",
|
||||||
inline=False,
|
inline=False,
|
||||||
)
|
)
|
||||||
embed.set_footer(text=f"GhostWipe v{self.__version__}")
|
embed.set_footer(text=f"Ruby · GhostWipe v{self.__version__}")
|
||||||
await ctx.send(embed=embed)
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
@ghostwipe.command(name="history")
|
@ghostwipe.command(name="history")
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ STYLE = r"""
|
||||||
--danger: #f04747;
|
--danger: #f04747;
|
||||||
--warn: #faa61a;
|
--warn: #faa61a;
|
||||||
--ok: #3ba55d;
|
--ok: #3ba55d;
|
||||||
|
--ruby: #e0115f;
|
||||||
--radius: 10px;
|
--radius: 10px;
|
||||||
--shadow: 0 8px 24px rgba(0,0,0,0.35);
|
--shadow: 0 8px 24px rgba(0,0,0,0.35);
|
||||||
}
|
}
|
||||||
|
|
@ -171,12 +172,42 @@ html, body {
|
||||||
padding: 8px 20px; border-top: 1px solid var(--border); color: var(--text-faint);
|
padding: 8px 20px; border-top: 1px solid var(--border); color: var(--text-faint);
|
||||||
font-size: 11px; text-align: center; flex-shrink: 0;
|
font-size: 11px; text-align: center; flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
.brand-ruby { color: var(--ruby); font-weight: 700; }
|
||||||
::-webkit-scrollbar { width: 10px; }
|
::-webkit-scrollbar { width: 10px; }
|
||||||
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 6px; }
|
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 6px; }
|
||||||
::-webkit-scrollbar-track { background: transparent; }
|
::-webkit-scrollbar-track { background: transparent; }
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 700px) {
|
||||||
#sidebar { width: 200px; }
|
html, body { font-size: 15px; }
|
||||||
#header .stats { gap: 12px; }
|
#header { padding: 12px 14px; gap: 10px; }
|
||||||
|
.avatar, .avatar-fallback { width: 40px; height: 40px; }
|
||||||
|
#header .username { font-size: 14px; }
|
||||||
|
#header .id-block { min-width: 0; }
|
||||||
|
#header .stats { order: 3; width: 100%; margin-left: 0; justify-content: space-around; gap: 10px; }
|
||||||
|
#header .stat .num { font-size: 16px; }
|
||||||
|
#header .meta-row { order: 4; }
|
||||||
|
|
||||||
|
/* Stack sidebar above main content, and turn the channel list into a
|
||||||
|
horizontally-scrolling strip of chips instead of a tall vertical list —
|
||||||
|
the classic mobile pattern for a channel/tab picker. */
|
||||||
|
#body { flex-direction: column; }
|
||||||
|
#sidebar {
|
||||||
|
width: 100%; max-height: none;
|
||||||
|
border-right: none; border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
#sidebar .sidebar-title { padding: 10px 14px 4px; }
|
||||||
|
#channel-list {
|
||||||
|
display: flex; flex-direction: row; flex-wrap: nowrap;
|
||||||
|
overflow-x: auto; -webkit-overflow-scrolling: touch;
|
||||||
|
gap: 6px; padding: 4px 10px;
|
||||||
|
}
|
||||||
|
.ch-item { flex: 0 0 auto; margin-bottom: 0; }
|
||||||
|
.ch-item .ch-name { white-space: nowrap; }
|
||||||
|
#search-wrap { padding: 8px 10px; }
|
||||||
|
|
||||||
|
#main { width: 100%; }
|
||||||
|
.panel-header { padding: 10px 14px; }
|
||||||
|
.panel-body { padding: 12px 14px; }
|
||||||
|
.attachment-img { max-width: 100%; }
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -398,7 +429,7 @@ def generate_report_html(
|
||||||
main_content = '<div class="empty-state">Nothing was deleted for this event.</div>'
|
main_content = '<div class="empty-state">Nothing was deleted for this event.</div>'
|
||||||
sidebar_content = '<div class="empty-state" style="padding:20px 10px;">No channels affected.</div>'
|
sidebar_content = '<div class="empty-state" style="padding:20px 10px;">No channels affected.</div>'
|
||||||
|
|
||||||
title = f"GhostWipe Report — {html_lib.escape(member_name)}"
|
title = f"Ruby — GhostWipe Report — {html_lib.escape(member_name)}"
|
||||||
|
|
||||||
doc = f"""<!doctype html>
|
doc = f"""<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
@ -442,7 +473,7 @@ def generate_report_html(
|
||||||
{main_content}
|
{main_content}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">Generated by GhostWipe {html_lib.escape(version)} · {html_lib.escape(generated_at or event_time_str)}</div>
|
<div id="footer"><span class="brand-ruby">Ruby</span> · GhostWipe v{html_lib.escape(version)} · {html_lib.escape(generated_at or event_time_str)}</div>
|
||||||
</div>
|
</div>
|
||||||
<script>{SEARCH_SCRIPT}</script>
|
<script>{SEARCH_SCRIPT}</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue