@nbtca/prompt 1.5.10 → 1.5.11
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
|
@@ -51,8 +51,6 @@ npm run check
|
|
|
51
51
|
`check` runs formatting, lint, full TypeScript validation, tests, build, package
|
|
52
52
|
consumer checks and dependency audit.
|
|
53
53
|
|
|
54
|
-
Project guides and release notes live in the [Wiki](https://github.com/nbtca/Prompt/wiki).
|
|
55
|
-
|
|
56
54
|
## License
|
|
57
55
|
|
|
58
56
|
MIT
|
package/dist/app/views/home.js
CHANGED
|
@@ -5,9 +5,9 @@ import { padEndV, visualWidth, wrapAnsiWithIndent } from '../../core/text.js';
|
|
|
5
5
|
import { peekNextClassLine, peekTodayLines, peekWeekAheadInfo, peekUnresolvedCount, } from '../../features/schedule-view.js';
|
|
6
6
|
import { loadCalendarOrThrow, peekCalendar, toDisplayEvent, renderEventBrief, } from '../../features/calendar.js';
|
|
7
7
|
import { weekdayShortLabel } from '../../features/schedule-render.js';
|
|
8
|
-
import { addLocalDays } from '../../core/calendar-day.js';
|
|
9
8
|
import { passiveFooterHint } from '../chrome.js';
|
|
10
|
-
import {
|
|
9
|
+
import { campusDateTime, campusIsoDate } from '@nbtca/nbtcal/timetable';
|
|
10
|
+
import { isoDayDifference, localDayDifference, parseLocalDate } from '../../core/calendar-day.js';
|
|
11
11
|
import { loadingLines } from '../../core/components/spinner.js';
|
|
12
12
|
const WEEKDAYS = [1, 2, 3, 4, 5, 6, 7];
|
|
13
13
|
function wrappedIndentedLines(label, cols, style) {
|
|
@@ -20,10 +20,11 @@ function wrappedRenderedLines(line, cols) {
|
|
|
20
20
|
const content = line.startsWith(space.indent) ? line.slice(space.indent.length) : line;
|
|
21
21
|
return wrappedIndentedLines(content, cols, (value) => value);
|
|
22
22
|
}
|
|
23
|
+
const DAY_MS = 86_400_000;
|
|
23
24
|
const DAY_PROGRESS_WIDTH = 20;
|
|
24
25
|
function renderDayProgress(now, cols) {
|
|
25
|
-
const
|
|
26
|
-
const fraction = Math.min(1, Math.max(0,
|
|
26
|
+
const midnight = campusDateTime(campusIsoDate(now), '00:00');
|
|
27
|
+
const fraction = Math.min(1, Math.max(0, (now.getTime() - midnight.getTime()) / DAY_MS));
|
|
27
28
|
const pct = Math.round(fraction * 100);
|
|
28
29
|
const percentage = `${pct}%`;
|
|
29
30
|
const width = Number.isFinite(cols) ? Math.max(1, Math.floor(cols)) : Number.POSITIVE_INFINITY;
|
|
@@ -149,8 +150,14 @@ function calendarSnapshot(cal, weekAheadInfo) {
|
|
|
149
150
|
.map((event) => renderEventBrief(toDisplayEvent(event), now));
|
|
150
151
|
if (!weekAheadInfo)
|
|
151
152
|
return { eventLines };
|
|
152
|
-
const
|
|
153
|
-
const
|
|
153
|
+
const { weekStart } = weekAheadInfo;
|
|
154
|
+
const monday = campusDateTime(weekStart, '00:00');
|
|
155
|
+
const daySet = new Set(cal
|
|
156
|
+
.inRange(new Date(monday.getTime() - DAY_MS), new Date(monday.getTime() + 8 * DAY_MS))
|
|
157
|
+
.map((event) => 1 +
|
|
158
|
+
(event.isAllDay
|
|
159
|
+
? localDayDifference(parseLocalDate(weekStart), event.start)
|
|
160
|
+
: isoDayDifference(weekStart, campusIsoDate(event.start)))));
|
|
154
161
|
return {
|
|
155
162
|
eventLines,
|
|
156
163
|
weekAhead: {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { createTimetableSchedule, } from '@nbtca/nbtcal/timetable';
|
|
1
|
+
import { campusIsoDate, createTimetableSchedule, } from '@nbtca/nbtcal/timetable';
|
|
2
2
|
import { c, type, space, glyph } from '../../core/theme.js';
|
|
3
3
|
import { pickIcon } from '../../core/icons.js';
|
|
4
4
|
import { t, fmt } from '../../i18n/index.js';
|
|
5
5
|
import { renderListFieldWithContext } from '../fields/list-field.js';
|
|
6
6
|
import { renderNextClassBanner, renderWeekGrid, renderUnresolvedItems, renderTodayTimeline, weekdayShortLabel, renderTermDensity, renderMeetingDetail, renderDayTimeline, renderDaySwitcher, } from '../../features/schedule-render.js';
|
|
7
7
|
import { sanitizeTerminalLine, visualWidth, wrapAnsiWithIndent } from '../../core/text.js';
|
|
8
|
-
import {
|
|
8
|
+
import { isoDayDifference } from '../../core/calendar-day.js';
|
|
9
9
|
import { loadingLines } from '../../core/components/spinner.js';
|
|
10
10
|
function heading(label) {
|
|
11
11
|
return `${space.indent}${type.heading(label)}`;
|
|
@@ -90,7 +90,7 @@ function hubPreGridLines(state, now, cols) {
|
|
|
90
90
|
lines.push(heading(trans.timetable.termNotStarted));
|
|
91
91
|
lines.push(hint(fmt(trans.timetable.termStartsIn, {
|
|
92
92
|
date: state.weekOne,
|
|
93
|
-
days: String(
|
|
93
|
+
days: String(daysUntil(now, state.weekOne)),
|
|
94
94
|
})));
|
|
95
95
|
lines.push('');
|
|
96
96
|
lines.push(heading(trans.timetable.termPreviewWeek));
|
|
@@ -160,7 +160,7 @@ const TERM_PROGRESS_WIDTH = 20;
|
|
|
160
160
|
function renderTermProgressBar(w, cols) {
|
|
161
161
|
if (!w.nextBreakStart)
|
|
162
162
|
return null;
|
|
163
|
-
const totalWeeks = Math.max(1, Math.round(
|
|
163
|
+
const totalWeeks = Math.max(1, Math.round(isoDayDifference(w.weekOneMonday, w.nextBreakStart) / 7));
|
|
164
164
|
const currentWeek = w.currentWeek;
|
|
165
165
|
const labelText = fmt(t().timetable.weekLabel2, { week: `${currentWeek}/${totalWeeks}` });
|
|
166
166
|
const label = type.hint(labelText);
|
|
@@ -177,8 +177,8 @@ function renderTermProgressBar(w, cols) {
|
|
|
177
177
|
? [`${indent}${bar} ${label}`]
|
|
178
178
|
: [`${indent}${bar}`, ...hintLines(labelText, cols)];
|
|
179
179
|
}
|
|
180
|
-
function
|
|
181
|
-
return Math.max(0,
|
|
180
|
+
function daysUntil(now, date) {
|
|
181
|
+
return Math.max(0, isoDayDifference(campusIsoDate(now), date));
|
|
182
182
|
}
|
|
183
183
|
function renderPublicBody(state, now, bodyRows, cols) {
|
|
184
184
|
const trans = t();
|
|
@@ -202,7 +202,7 @@ function renderPublicBody(state, now, bodyRows, cols) {
|
|
|
202
202
|
if (w.nextBreakStart && w.nextBreakTitle) {
|
|
203
203
|
lines.push(...hintLines(fmt(trans.timetable.daysUntilBreak, {
|
|
204
204
|
title: sanitizeTerminalLine(w.nextBreakTitle),
|
|
205
|
-
days: String(
|
|
205
|
+
days: String(daysUntil(now, w.nextBreakStart)),
|
|
206
206
|
}), cols));
|
|
207
207
|
}
|
|
208
208
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createTimetableSchedule } from '@nbtca/nbtcal/timetable';
|
|
1
|
+
import { campusDateTime, campusIsoDate, createTimetableSchedule } from '@nbtca/nbtcal/timetable';
|
|
2
2
|
import { countdownParts, isCountdownUrgent } from './calendar-query.js';
|
|
3
3
|
import { c, type, space, glyph } from '../core/theme.js';
|
|
4
4
|
import { pickIcon } from '../core/icons.js';
|
|
@@ -64,25 +64,6 @@ export function renderNextClassBanner(next, now, cols = Number.POSITIVE_INFINITY
|
|
|
64
64
|
}
|
|
65
65
|
return styleWhen(compactWhen);
|
|
66
66
|
}
|
|
67
|
-
export function renderTodayClasses(meetings, periods, now) {
|
|
68
|
-
const trans = t();
|
|
69
|
-
const sorted = [...meetings].sort((a, b) => a.startPeriod - b.startPeriod);
|
|
70
|
-
if (sorted.length === 0)
|
|
71
|
-
return `${space.indent}${type.hint(trans.timetable.noClassToday)}`;
|
|
72
|
-
const dot = pickIcon('·', '-');
|
|
73
|
-
const marker = pickIcon('▸', '>');
|
|
74
|
-
const lines = sorted.map((m) => {
|
|
75
|
-
const time = span(m, periods);
|
|
76
|
-
const startStr = periods.find((p) => p.period === m.startPeriod)?.start ?? '00:00';
|
|
77
|
-
const endStr = periods.find((p) => p.period === m.endPeriod)?.end ?? '23:59';
|
|
78
|
-
const nowStr = `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
|
|
79
|
-
const live = nowStr >= startStr && nowStr <= endStr;
|
|
80
|
-
const head = live ? `${type.active(marker)} ` : ' ';
|
|
81
|
-
const loc = m.location ? ` ${dot} ${type.hint(m.location)}` : '';
|
|
82
|
-
return `${space.indent}${head}${type.hint(time)} ${live ? type.active(m.courseName) : type.body(m.courseName)}${loc}`;
|
|
83
|
-
});
|
|
84
|
-
return lines.join('\n');
|
|
85
|
-
}
|
|
86
67
|
export function weekdayShortLabel(wd) {
|
|
87
68
|
const trans = t();
|
|
88
69
|
const labels = [
|
|
@@ -101,7 +82,8 @@ function renderTimeline(meetings, periods, now, isToday, alwaysShowLocation, cur
|
|
|
101
82
|
const sorted = [...meetings].sort((a, b) => a.startPeriod - b.startPeriod);
|
|
102
83
|
if (sorted.length === 0)
|
|
103
84
|
return `${space.indent}${type.hint(trans.timetable.noClassToday)}`;
|
|
104
|
-
const
|
|
85
|
+
const today = campusIsoDate(now);
|
|
86
|
+
const minute = Math.floor(now.getTime() / 60_000) * 60_000;
|
|
105
87
|
const dot = pickIcon('·', '-');
|
|
106
88
|
const rule = pickIcon('─', '-');
|
|
107
89
|
const midConnector = pickIcon('┼', '+');
|
|
@@ -110,8 +92,9 @@ function renderTimeline(meetings, periods, now, isToday, alwaysShowLocation, cur
|
|
|
110
92
|
const lines = sorted.map((m, i) => {
|
|
111
93
|
const startStr = periods.find((p) => p.period === m.startPeriod)?.start ?? '00:00';
|
|
112
94
|
const endStr = periods.find((p) => p.period === m.endPeriod)?.end ?? '23:59';
|
|
113
|
-
const
|
|
114
|
-
const
|
|
95
|
+
const end = campusDateTime(today, endStr);
|
|
96
|
+
const isLive = isToday && campusDateTime(today, startStr).getTime() <= minute && minute <= end.getTime();
|
|
97
|
+
const isDone = isToday && minute > end.getTime();
|
|
115
98
|
const isCursor = cursorPeriod !== undefined && m.startPeriod <= cursorPeriod && cursorPeriod <= m.endPeriod;
|
|
116
99
|
const connector = i === 0 ? topConnector : midConnector;
|
|
117
100
|
const marker = isLive ? type.active(pickIcon('▶', '>')) : ' ';
|
|
@@ -124,9 +107,6 @@ function renderTimeline(meetings, periods, now, isToday, alwaysShowLocation, cur
|
|
|
124
107
|
compactStatusText = statusText;
|
|
125
108
|
}
|
|
126
109
|
else if (isLive) {
|
|
127
|
-
const end = new Date(now);
|
|
128
|
-
const [eh, em] = endStr.split(':').map((x) => Number.parseInt(x, 10));
|
|
129
|
-
end.setHours(eh !== undefined && Number.isFinite(eh) ? eh : 0, em !== undefined && Number.isFinite(em) ? em : 0, 0, 0);
|
|
130
110
|
const remaining = countdownParts(end, now);
|
|
131
111
|
const mins = remaining.days * 1440 + remaining.hours * 60 + remaining.minutes;
|
|
132
112
|
statusText = `${trans.timetable.classLive} ${dot} ${fmt(trans.timetable.minutesRemaining, { minutes: String(mins) })}`;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createTimetableSchedule } from '@nbtca/nbtcal/timetable';
|
|
2
|
-
import { addLocalDays, parseLocalMonday } from '../core/calendar-day.js';
|
|
1
|
+
import { campusDateTime, campusIsoDate, createTimetableSchedule, } from '@nbtca/nbtcal/timetable';
|
|
3
2
|
import { renderNextClassBanner, renderTodayTimeline } from './schedule-render.js';
|
|
4
3
|
import { loadCurrentPointer, loadTimetableCache } from './schedule-store.js';
|
|
5
4
|
import { sanitizeTimetable } from './timetable-sanitize.js';
|
|
6
5
|
const WEEKDAYS = [1, 2, 3, 4, 5, 6, 7];
|
|
6
|
+
const WEEK_MS = 7 * 86_400_000;
|
|
7
7
|
function loadCachedTimetable() {
|
|
8
8
|
const pointer = loadCurrentPointer();
|
|
9
9
|
if (!pointer)
|
|
@@ -69,8 +69,8 @@ export function peekWeekAheadInfo(now = new Date()) {
|
|
|
69
69
|
if (week < 1)
|
|
70
70
|
return null;
|
|
71
71
|
const classDays = WEEKDAYS.map((weekday) => schedule.meetingsOnDay(week, weekday).length > 0);
|
|
72
|
-
const
|
|
73
|
-
return {
|
|
72
|
+
const weekStart = campusDateTime(cached.weekOneMonday, '00:00').getTime() + (week - 1) * WEEK_MS;
|
|
73
|
+
return { weekStart: campusIsoDate(new Date(weekStart)), classDays };
|
|
74
74
|
}
|
|
75
75
|
catch {
|
|
76
76
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nbtca/prompt",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"interactive"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@nbtca/docs": "^0.3.
|
|
50
|
-
"@nbtca/nbtcal": "^0.4.
|
|
49
|
+
"@nbtca/docs": "^0.3.1",
|
|
50
|
+
"@nbtca/nbtcal": "^0.4.1",
|
|
51
51
|
"chalk": "^5.6.2",
|
|
52
52
|
"cheerio": "1.0.0",
|
|
53
53
|
"fetch-cookie": "^3.2.0",
|