@d3lm/pr-stats 0.2.16 → 0.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Without flags, it covers PRs from the last 90 days across all repositories you c
|
|
|
27
27
|
|
|
28
28
|
- **Queue** lists the open PRs awaiting your review with their wait time, and below them the open PRs you already reviewed. A fresh review request moves a PR back into the awaiting list.
|
|
29
29
|
- **Your PRs** splits into your open PRs and a merged-and-closed report with merge-time, first-review, backlog, and outcome charts plus a reviewer leaderboard. The `t` key switches the sub-tabs.
|
|
30
|
-
- **
|
|
30
|
+
- **Reviews** counts the PRs you reviewed on request next to the review rounds they took, and charts your review times as a histogram, trend, heatmap, and weekly volume, plus review cycles, verdicts, an off-hours gauge, and the requests still waiting on you.
|
|
31
31
|
- **PR size** carries the same charts for PR sizes and adds a weekly net-lines trend.
|
|
32
32
|
- **Comments** holds a histogram of comments per PR, a scatter against PR size, and the most commented PRs.
|
|
33
33
|
|
|
@@ -116,7 +116,7 @@ The `r` key reloads the data by hand, and `R` refetches everything past the cach
|
|
|
116
116
|
|
|
117
117
|
## Notifications
|
|
118
118
|
|
|
119
|
-
The Desktop notifications row in the settings dialog makes the TUI send a desktop notification whenever a load finds a PR newly awaiting your review or a review re-requested from you after you already reviewed the PR. Every load diffs its review requests against the
|
|
119
|
+
The Desktop notifications row in the settings dialog makes the TUI send a desktop notification whenever a load finds a PR newly awaiting your review or a review re-requested from you after you already reviewed the PR. Every load diffs its review requests against the data shown before it. For the first load of a session that is the startup snapshot from the previous session, so a restart tells you what came in while the TUI was closed. Only a session without a snapshot, after `--no-cache` or on the first run, starts by recording what is already waiting without notifying about it. Manual reloads count as well, but the feature pairs naturally with auto reload, which lets the TUI watch your review queue from a spare terminal. The setting persists in `settings.json` in the cache directory.
|
|
120
120
|
|
|
121
121
|
```json
|
|
122
122
|
{
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
<key>CFBundlePackageType</key>
|
|
20
20
|
<string>APPL</string>
|
|
21
21
|
<key>CFBundleShortVersionString</key>
|
|
22
|
-
<string>0.2.
|
|
22
|
+
<string>0.2.18</string>
|
|
23
23
|
<key>CFBundleVersion</key>
|
|
24
|
-
<string>0.2.
|
|
24
|
+
<string>0.2.18</string>
|
|
25
25
|
<key>LSMinimumSystemVersion</key>
|
|
26
26
|
<string>13.0</string>
|
|
27
27
|
<key>LSUIElement</key>
|
|
Binary file
|
package/dist/tui-app.mjs
CHANGED
|
@@ -2472,7 +2472,7 @@ function RepoList({
|
|
|
2472
2472
|
}
|
|
2473
2473
|
|
|
2474
2474
|
// src/tui/state/browse.ts
|
|
2475
|
-
var TABS = ["1 Awaiting you", "2 Your PRs", "3
|
|
2475
|
+
var TABS = ["1 Awaiting you", "2 Your PRs", "3 Reviews", "4 PR size", "5 Comments"];
|
|
2476
2476
|
var initialBrowseState = {
|
|
2477
2477
|
tab: 0,
|
|
2478
2478
|
authoredTab: "open",
|
|
@@ -4670,7 +4670,8 @@ function useDeferredLoading(isLoading, { showDelay = 300, minDuration = 500 } =
|
|
|
4670
4670
|
|
|
4671
4671
|
// src/tui/hooks/useLoader.ts
|
|
4672
4672
|
import { useEffect as useEffect6, useRef as useRef4, useState as useState3 } from "react";
|
|
4673
|
-
function useLoader(options, noCache2,
|
|
4673
|
+
function useLoader(options, noCache2, callbacks = {}) {
|
|
4674
|
+
const { onSnapshot, onLoaded } = callbacks;
|
|
4674
4675
|
const [startupSnapshot] = useState3(() => noCache2 ? null : loadSnapshot(options));
|
|
4675
4676
|
const [raw, setRaw] = useState3(startupSnapshot);
|
|
4676
4677
|
const [appliedKey, setAppliedKey] = useState3(
|
|
@@ -4723,6 +4724,9 @@ function useLoader(options, noCache2, onLoaded) {
|
|
|
4723
4724
|
disposedRef.current = false;
|
|
4724
4725
|
if (!startedRef.current) {
|
|
4725
4726
|
startedRef.current = true;
|
|
4727
|
+
if (startupSnapshot !== null) {
|
|
4728
|
+
onSnapshot?.(startupSnapshot);
|
|
4729
|
+
}
|
|
4726
4730
|
void run(noCache2);
|
|
4727
4731
|
}
|
|
4728
4732
|
return () => {
|
|
@@ -5752,7 +5756,8 @@ function buildReviewView(raw, target, repo = null, width = 100, expanded = false
|
|
|
5752
5756
|
const results = repo === null ? raw.reviewResults : raw.reviewResults.filter((result) => result.pr.repo === repo);
|
|
5753
5757
|
const stats = computeReviewStats(results, { targetHours: target?.hours, now: raw.fetchedAt });
|
|
5754
5758
|
const strip = [
|
|
5755
|
-
countCell(stats.
|
|
5759
|
+
countCell(stats.cycles.length, "PRs reviewed"),
|
|
5760
|
+
countCell(stats.reviewed.length, "review rounds"),
|
|
5756
5761
|
countCell(stats.pending.length, "awaiting you", true),
|
|
5757
5762
|
countCell(stats.expired.length, "closed unreviewed", true),
|
|
5758
5763
|
[{ text: `${stats.unrequested.length} reviewed unasked (excluded)`, fg: theme.dim }]
|
|
@@ -7028,19 +7033,24 @@ function App({
|
|
|
7028
7033
|
const notifyReviewChanges = useReviewNotifications(notifications2, notifier, (message) => {
|
|
7029
7034
|
dispatchUi({ type: "openErrorReported", message });
|
|
7030
7035
|
});
|
|
7031
|
-
const { raw, isSnapshot, loading, load, error, stale, reload } = useLoader(options, noCache2,
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7036
|
+
const { raw, isSnapshot, loading, load, error, stale, reload } = useLoader(options, noCache2, {
|
|
7037
|
+
onSnapshot: (data) => {
|
|
7038
|
+
notifyReviewChanges(fetchParamsKey(options), data.reviewResults);
|
|
7039
|
+
},
|
|
7040
|
+
onLoaded: (data) => {
|
|
7041
|
+
dispatchBrowse({
|
|
7042
|
+
type: "dataLoaded",
|
|
7043
|
+
repos: {
|
|
7044
|
+
pending: buildPendingRepoOptions(data),
|
|
7045
|
+
open: buildOpenRepoOptions(data),
|
|
7046
|
+
review: buildReviewRepoOptions(data),
|
|
7047
|
+
size: buildSizeRepoOptions(data),
|
|
7048
|
+
comment: buildCommentRepoOptions(data),
|
|
7049
|
+
merged: buildMergedRepoOptions(data)
|
|
7050
|
+
}
|
|
7051
|
+
});
|
|
7052
|
+
notifyReviewChanges(fetchParamsKey(options), data.reviewResults);
|
|
7053
|
+
}
|
|
7044
7054
|
});
|
|
7045
7055
|
useAutoReload(autoReload2 ? reloadIntervalMs(reloadInterval2) : null, loading, reload);
|
|
7046
7056
|
const views = useViewModel(raw, options, width, browse.scopes, browse.grouped, browse.expanded, themeState);
|