windscout 0.4.3 → 0.4.4

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
@@ -98,7 +98,7 @@ Both modes show an **availability grid**: one row per country, and ✓ / ✗ for
98
98
  ╰─────────────────────────┴────────────────────────┴─────────┴───────────┴─────╯
99
99
  ```
100
100
 
101
- While scanning, press `tab` to switch between the availability grid and the speed or latency ranking. In connect-only mode the scan starts on the availability grid.
101
+ While scanning, press `tab` to switch between the availability grid and the speed or latency ranking. Press `p` (or `space`) to pause: the current attempt finishes, the VPN disconnects, and the scan waits until you press `p` again. Paused time doesn't count toward elapsed or remaining. In connect-only mode the scan starts on the availability grid.
102
102
 
103
103
  ## Output
104
104
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "windscout",
3
- "version": "0.4.3",
3
+ "version": "0.4.4",
4
4
  "description": "Find which Windscribe locations and protocols work from your network, ranked by speed (unofficial)",
5
5
  "type": "module",
6
6
  "bin": {
package/windscout.js CHANGED
@@ -599,12 +599,14 @@ async function scan(countries, protocols, timeout, tty) {
599
599
  const started = now();
600
600
  let done = 0, attemptStart = now(), current = "", step = "", frame = 0, finishedCountries = [];
601
601
  let view = speedTest ? "ranking" : "availability"; // tab switches
602
+ // pause lands between attempts, so the VPN is disconnected while waiting; idle = seconds spent paused
603
+ let paused = false, waiting = false, waitStart = 0, idle = 0, resume = () => {};
602
604
 
603
605
  const render = () => {
604
606
  const rows = out.rows || 24;
605
- const elapsed = now() - started;
607
+ const elapsed = now() - started - idle - (waiting ? now() - waitStart : 0);
606
608
  // smooth bar: count the running attempt as partially done
607
- const partial = Math.min(0.95, (now() - attemptStart) / attemptSeconds(timeout));
609
+ const partial = waiting ? 0 : Math.min(0.95, (now() - attemptStart) / attemptSeconds(timeout));
608
610
  const fraction = (done + (done < total ? partial : 0)) / total;
609
611
  const eta = (total - done) * (done ? elapsed / done : attemptSeconds(timeout));
610
612
  const spinner = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"[frame++ % 10];
@@ -640,8 +642,9 @@ async function scan(countries, protocols, timeout, tty) {
640
642
  "",
641
643
  stop
642
644
  ? yellow(" stopping after the current attempt…")
645
+ : waiting ? yellow(" paused · VPN disconnected · press p to resume")
643
646
  : ` ${cyan(spinner)} ${bold(current)}`,
644
- stop ? "" : ` ${dim(step)} ${dim("·")} ${duration(now() - attemptStart)}`,
647
+ stop || waiting ? "" : ` ${dim(step)} ${dim("·")} ${duration(now() - attemptStart)}${paused ? yellow(" · pausing after this attempt") : ""}`,
645
648
  null,
646
649
  centerIn(stats, inner),
647
650
  ], {
@@ -658,7 +661,7 @@ async function scan(countries, protocols, timeout, tty) {
658
661
  while (vw(txt) > width && failed.length) txt = txt.slice(0, -8) + "…"; // ponytail: crude trim, fine for a status line
659
662
  lines.push("", centerIn(txt, width));
660
663
  }
661
- lines.push("", centerIn(dim(`tab ${view === "ranking" ? "availability" : "ranking"} view · q stop · q twice force quit`), width), "", centerIn(dim(repoLink), width));
664
+ lines.push("", centerIn(dim(`tab ${view === "ranking" ? "availability" : "ranking"} view · p ${paused ? "resume" : "pause"} · q stop · q twice force quit`), width), "", centerIn(dim(repoLink), width));
662
665
  draw(lines);
663
666
  };
664
667
 
@@ -669,12 +672,17 @@ async function scan(countries, protocols, timeout, tty) {
669
672
  if (key.name === "tab") {
670
673
  view = view === "ranking" ? "availability" : "ranking";
671
674
  render();
675
+ } else if (key.name === "p" || key.name === "space") {
676
+ paused = !paused;
677
+ if (!paused) resume();
678
+ render();
672
679
  } else if (key.name === "q" || key.name === "escape" || (key.ctrl && key.name === "c")) {
673
680
  if (stop++) { // second press: bail out now
674
681
  leaveScreen();
675
682
  console.error(`stopped. the VPN may still be connecting: run '${CLI} disconnect'`);
676
683
  process.exit(130);
677
684
  }
685
+ resume(); // a paused scan stops right away
678
686
  render();
679
687
  }
680
688
  });
@@ -686,6 +694,11 @@ async function scan(countries, protocols, timeout, tty) {
686
694
 
687
695
  outer: for (const loc of countries) {
688
696
  for (const proto of protocols) {
697
+ if (paused && !stop) {
698
+ waiting = true, waitStart = now();
699
+ await new Promise((r) => (resume = r));
700
+ waiting = false, idle += now() - waitStart;
701
+ }
689
702
  if (stop) break outer;
690
703
  current = `${flag(loc)} ${countryName(loc)} ${dim("·")} ${proto}`;
691
704
  attemptStart = now();