Reading activity grid in Settings: months, weeks, days, hours with drill-down
Active reader time is now kept per user in small UTC buckets (6 minutes for 120 days, then hours, dropped after three years), seeded once from the visits the clock still remembers. Settings -> Reading activity shows them as a grid whose cells glow with their total and carry a start-to-end strip; month/week cells open their days, days open their hours. Finished chapters come from progress and work without the clock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c760141636
commit
fe8956087e
15 files changed
+657
-4
No files matched your search
@@ -575,3 +575,47 @@ kbd { display: inline-block; min-width: 24px; padding: 1px 7px; border: 1px soli
|
||||
background: var(--card2); font: 13px/1.5 ui-monospace, monospace; text-align: center; }
|
||||
@media (max-width: 480px) { .moment-dialog { padding: 12px; } .moment-actions .moment-hint { flex-basis: 100%; } .moment-actions .moment-hint:empty { display: none; } }
|
||||
.moment-extend { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-bottom: 8px; }
|
||||
|
||||
/* Reading activity grid (Settings → Reading activity). --g: cell glow 0…1, --a: strip segment glow 0…1. */
|
||||
.activity-toolbar { display: flex; flex-wrap: wrap; gap: 8px; justify-content: space-between; }
|
||||
.activity-nav { display: flex; align-items: center; gap: 8px; margin: 12px 0 4px; }
|
||||
.activity-title { min-width: 11em; text-align: center; }
|
||||
.activity-summary { margin: 6px 0 12px; }
|
||||
.activity-grid { display: flex; flex-direction: column; gap: 6px; }
|
||||
.activity-row { display: grid; grid-template-columns: 5.5em 1fr; gap: 8px; align-items: stretch; border-radius: 10px; }
|
||||
.activity-row.marked { background: color-mix(in srgb, var(--accent) 12%, transparent); outline: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
|
||||
.activity-row-label { color: var(--muted); font-size: 13px; align-self: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.activity-cells { display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: 6px; }
|
||||
.activity-head { color: var(--muted); font-size: 12px; text-align: center; }
|
||||
.activity-cell { position: relative; display: flex; flex-direction: column; justify-content: space-between; gap: 6px; min-height: 58px; padding: 6px 7px 7px;
|
||||
border: 1px solid var(--line); border-radius: 8px; color: var(--fg); font: inherit; text-align: left; cursor: pointer;
|
||||
background: color-mix(in srgb, var(--accent) calc(var(--g) * 42%), var(--card2));
|
||||
box-shadow: 0 0 calc(var(--g) * 12px) color-mix(in srgb, var(--accent) calc(var(--g) * 55%), transparent);
|
||||
transition: transform .12s, border-color .12s; }
|
||||
.activity-cell:hover, .activity-cell:focus-visible { border-color: var(--accent); transform: translateY(-1px); outline: none; }
|
||||
.activity-cell.hot { border-color: color-mix(in srgb, var(--accent) 70%, #fff); }
|
||||
.activity-cell.now { border-color: var(--fg); }
|
||||
.activity-cell.outside { opacity: .38; }
|
||||
.activity-cell.future { cursor: default; background: transparent; border-style: dashed; box-shadow: none; transform: none; }
|
||||
.view-hour .activity-cell { cursor: default; }
|
||||
.activity-label { font-size: 13px; font-weight: 600; line-height: 1.1; display: flex; flex-direction: column; }
|
||||
.activity-label small { font-weight: 400; color: var(--muted); font-size: 11px; }
|
||||
.activity-value { position: absolute; top: 6px; right: 7px; font-size: 11px; color: color-mix(in srgb, var(--fg) 80%, transparent); }
|
||||
.view-day .activity-value, .view-month .activity-value { position: static; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.activity-strip { display: flex; height: 9px; border-radius: 3px; overflow: hidden; background: color-mix(in srgb, var(--bg) 70%, transparent); }
|
||||
.activity-strip i { flex: 1; background: var(--accent); opacity: var(--a); }
|
||||
.activity-strip i.ahead { background: transparent; }
|
||||
.activity-strip i + i { box-shadow: inset 1px 0 0 color-mix(in srgb, var(--bg) 35%, transparent); }
|
||||
.view-month .activity-strip i + i, .view-week .activity-strip i + i { box-shadow: none; }
|
||||
.activity-tip { position: fixed; z-index: 50; max-width: 300px; padding: 10px 12px; border-radius: 10px; pointer-events: none;
|
||||
background: var(--card); border: 1px solid var(--line); box-shadow: 0 8px 24px rgba(0, 0, 0, .45); font-size: 13px; line-height: 1.45; }
|
||||
.activity-tip ul { margin: 4px 0 0; padding-left: 16px; }
|
||||
.activity-legend { margin-top: 12px; }
|
||||
@media (max-width: 760px) {
|
||||
.activity-row { grid-template-columns: 1fr; gap: 3px; }
|
||||
.activity-row.head .activity-row-label { display: none; }
|
||||
.view-month .activity-cells { grid-template-columns: repeat(6, minmax(0, 1fr)); }
|
||||
.activity-cell { min-height: 48px; padding: 5px; }
|
||||
.activity-value { display: none; }
|
||||
.activity-cells { gap: 4px; }
|
||||
}
|
||||
Reference in new issue
Block a user