@agent-native/core-corpus 0.211.0-nightly-20261020183616 → 0.211.0
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/corpus/README.md +1 -1
- package/corpus/templates/analytics/CHANGELOG.md +18 -0
- package/corpus/templates/clips/CHANGELOG.md +11 -24
- package/corpus/templates/clips/actions/create-recording-upload.ts +5 -1
- package/corpus/templates/clips/changelog/2026-10-16-agent-uploads-can-use-free-clips-storage.md +6 -0
- package/corpus/templates/clips/server/lib/recording-upload-ticket.ts +8 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +2 -0
- package/corpus/templates/content/CHANGELOG.md +12 -0
- package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +4 -0
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +56 -2
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +6 -46
- package/corpus/templates/content/app/components/editor/database/ContentTable.tsx +2 -1
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +28 -13
- package/corpus/templates/content/app/components/editor/database/database-cell-comments.tsx +515 -0
- package/corpus/templates/content/app/components/editor/database/database-item-comments.tsx +5 -43
- package/corpus/templates/content/app/components/editor/property-comments.tsx +35 -4
- package/corpus/templates/content/app/components/editor/property-date-format.ts +45 -0
- package/corpus/templates/content/app/global.css +23 -0
- package/corpus/templates/content/app/i18n-data.ts +1 -0
- package/corpus/templates/content/docs/product/capabilities/content.comment.page-owned.md +5 -1
- package/corpus/templates/design/CHANGELOG.md +2 -0
- package/corpus/templates/dispatch/CHANGELOG.md +4 -0
- package/corpus/templates/mail/CHANGELOG.md +14 -0
- package/corpus/templates/plan/CHANGELOG.md +4 -0
- package/package.json +1 -1
- package/corpus/templates/analytics/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/assets/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/brain/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/calendar/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/chat/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/clips/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/content/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/crm/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/design/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/design/.generated/bridge/native-builtin-metadata.generated.ts +0 -301
- package/corpus/templates/design/.generated/bridge/native-worker-source.generated.ts +0 -6
- package/corpus/templates/dispatch/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/forms/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/mail/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/plan/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
- package/corpus/templates/slides/.deploy-tmp/agent-native-provided-plugins.mjs +0 -10
package/corpus/README.md
CHANGED
|
@@ -7,6 +7,13 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
7
7
|
|
|
8
8
|
### Fixed
|
|
9
9
|
|
|
10
|
+
- Blog signup attribution excludes signups before the first visit and URLs on unrelated hosts
|
|
11
|
+
- Collapsed Analytics navigation starts at the top with more space between icons.
|
|
12
|
+
- Content keeps successful coverage dates and missing-day gaps, and Search Console setup validates paths before saving
|
|
13
|
+
- Private GitHub repositories can be indexed with an organization-scoped GitHub token
|
|
14
|
+
- Search Console preserves historical backfill after empty results and keeps daily collection paused when editing properties.
|
|
15
|
+
- Search Console refreshes historical coverage when properties change and advances normally after empty results
|
|
16
|
+
- Search Console setup keeps saved properties readable and supports disabling collection with invalid drafts.
|
|
10
17
|
- Blog article credits include direct and wrapped author references.
|
|
11
18
|
- Content collection recovers abandoned runs, avoids duplicate work, and preserves missing author names.
|
|
12
19
|
- Daily content metrics recover collection gaps and keep omitted Search Console values uncollected.
|
|
@@ -14,6 +21,10 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
14
21
|
|
|
15
22
|
## 2026-10-19
|
|
16
23
|
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Import from Sigma lists every workbook you can see in Sigma, with search. Workbooks already migrated show greyed out with their owner and open the dashboard in a new tab, so nobody migrates the same workbook twice.
|
|
27
|
+
|
|
17
28
|
### Fixed
|
|
18
29
|
|
|
19
30
|
- Composer focus remains safe when an editor changes during navigation.
|
|
@@ -25,6 +36,10 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
25
36
|
|
|
26
37
|
- Apps no longer keep server functions and databases warm by default; set `AGENT_NATIVE_ENABLE_KEEP_WARM=1` to opt in.
|
|
27
38
|
|
|
39
|
+
### Security
|
|
40
|
+
|
|
41
|
+
- Creating or revoking a public analytics key now asks you to approve it every time the agent or another app tries it.
|
|
42
|
+
|
|
28
43
|
## 2026-10-17
|
|
29
44
|
|
|
30
45
|
### Added
|
|
@@ -47,6 +62,7 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
47
62
|
|
|
48
63
|
### Added
|
|
49
64
|
|
|
65
|
+
- The Content dashboard can show signups per blog article, collected once a day behind a BigQuery cost cap that a dry run measures first
|
|
50
66
|
- Click a table row to see its numbers broken down by app, or another column, in a side panel.
|
|
51
67
|
- Connect a personal Sigma account to import its dashboards
|
|
52
68
|
- First-party charts can read a scheduled warehouse events model instead of the raw event table, so repeat loads reuse BigQuery's cache between model rebuilds.
|
|
@@ -104,6 +120,8 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
104
120
|
|
|
105
121
|
### Added
|
|
106
122
|
|
|
123
|
+
- A Content dashboard lists every blog article with its author, pageviews, and search clicks, and says when a source failed or isn't set up instead of showing zero
|
|
124
|
+
- Data sources has a Google Search Console card that shows the service account to grant and turns on daily collection
|
|
107
125
|
- Analytics can collect daily GA4 pageviews and Search Console clicks and impressions for each blog article
|
|
108
126
|
- Analytics can collect your blog article list once a day into its own tables, ready for the Content view
|
|
109
127
|
- Click any bar, line point, funnel stage or slice on the first-party dashboard to open the underlying records in a pop-up, with filter, SQL and CSV export.
|
|
@@ -3,10 +3,20 @@
|
|
|
3
3
|
All notable user-facing changes to Clips are documented here. Open it any time
|
|
4
4
|
from the command menu (Cmd+K → "What's new") or from Settings.
|
|
5
5
|
|
|
6
|
+
## 2026-10-20
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- Locally saved desktop recordings now appear in the recovery list with upload and storage setup actions.
|
|
11
|
+
|
|
6
12
|
## 2026-10-19
|
|
7
13
|
|
|
8
14
|
### Fixed
|
|
9
15
|
|
|
16
|
+
- Agents see a clip's frames as soon as it finishes processing instead of a cached "still processing" answer.
|
|
17
|
+
- Chapter list times now match the player's clock, and each chapter shows a focus ring when you tab to it.
|
|
18
|
+
- Editing a comment puts the cursor after its text, and Reply on another notification moves the cursor to its reply box.
|
|
19
|
+
- Video imports use clearer labels, YouTube links work without connected storage, and embedded players stay clear of timeline hover previews.
|
|
10
20
|
- Screen Memory can transcribe desktop recordings without a separate FFmpeg install.
|
|
11
21
|
|
|
12
22
|
### Changed
|
|
@@ -57,6 +67,7 @@ from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
57
67
|
|
|
58
68
|
### Fixed
|
|
59
69
|
|
|
70
|
+
- Recordings uploaded by a connected agent can now use free Clips storage, like recordings made in the app.
|
|
60
71
|
- An agent upload too large for free hosted storage is now refused before it starts, with the size limit that applies.
|
|
61
72
|
- Agents connected to Clips over MCP can now import a transcript file, instead of getting an unknown-tool error.
|
|
62
73
|
- Clips keeps meeting transcripts recoverable while a save or notes finalization is still in progress.
|
|
@@ -1616,28 +1627,4 @@ from the command menu (Cmd+K → "What's new") or from Settings.
|
|
|
1616
1627
|
- Fixed the Mac menu bar popover so it opens reliably after launch at login.
|
|
1617
1628
|
- Localized Clips Settings changelog and extension sidebar labels in every supported interface language.
|
|
1618
1629
|
|
|
1619
|
-
## 2026-06-24
|
|
1620
|
-
|
|
1621
|
-
### Added
|
|
1622
|
-
|
|
1623
|
-
- Added a language picker and localized app chrome for supported languages.
|
|
1624
|
-
- Clips now includes a language picker with Simplified Chinese support for core navigation, empty states, and settings.
|
|
1625
|
-
|
|
1626
|
-
### Improved
|
|
1627
|
-
|
|
1628
|
-
- Chrome extension setup now shows a clear all-done confirmation when permissions are ready.
|
|
1629
|
-
- Settings now link directly to Agent settings for model, API key, automation, and voice preferences.
|
|
1630
|
-
- Settings now puts What's new in a compact sidebar, prioritizes Builder.io setup, and lets you manage S3 storage and AI provider keys in place.
|
|
1631
|
-
- Shared clips now expose their full console log stream (all levels, redacted) to connected agents, not just warnings and errors
|
|
1632
|
-
- Shared clips now expose their full fetch/XHR network request stream (method, sanitized URL, status, duration) to connected agents, not just failed requests
|
|
1633
|
-
|
|
1634
|
-
### Fixed
|
|
1635
|
-
|
|
1636
|
-
- Archive and spaces navigation is more resilient when sidebar count loading fails.
|
|
1637
|
-
- Inline Slack playback controls no longer shift when adjusting volume, and compact clip times stay on one line.
|
|
1638
|
-
|
|
1639
|
-
### Changed
|
|
1640
|
-
|
|
1641
|
-
- The Chrome extension option now only appears on supported Clips hosts unless a custom deployment explicitly enables it.
|
|
1642
|
-
|
|
1643
1630
|
For the full list of updates, see the [changelog folder](./changelog/).
|
|
@@ -82,7 +82,11 @@ export default defineAction({
|
|
|
82
82
|
// The ticket comes first: if it is refused or fails to save, no recording
|
|
83
83
|
// is left stranded in "uploading" with nothing able to finish it.
|
|
84
84
|
const recordingId = nanoid();
|
|
85
|
-
const ticket = await createRecordingUploadTicket(
|
|
85
|
+
const ticket = await createRecordingUploadTicket(
|
|
86
|
+
ownerEmail,
|
|
87
|
+
recordingId,
|
|
88
|
+
getRequestContext()?.authUserId,
|
|
89
|
+
);
|
|
86
90
|
let created: Awaited<ReturnType<typeof createRecording.run>>;
|
|
87
91
|
try {
|
|
88
92
|
created = await createRecording.run(
|
|
@@ -27,6 +27,8 @@ export interface RecordingUploadTicket extends Record<string, unknown> {
|
|
|
27
27
|
tokenHash: string;
|
|
28
28
|
reservedAt: number;
|
|
29
29
|
expiresAt: number;
|
|
30
|
+
/** The creator's auth user id, which a hosted-storage reservation is held under. */
|
|
31
|
+
authUserId?: string;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
interface RecordingUploadTickets extends Record<string, unknown> {
|
|
@@ -37,6 +39,7 @@ export interface RecordingUploadTicketOwner {
|
|
|
37
39
|
recordingId: string;
|
|
38
40
|
ownerEmail: string;
|
|
39
41
|
orgId: string;
|
|
42
|
+
authUserId?: string;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
function tokenHash(token: string): string {
|
|
@@ -180,6 +183,7 @@ async function compareAndSwapTickets(
|
|
|
180
183
|
export async function createRecordingUploadTicket(
|
|
181
184
|
ownerEmail: string,
|
|
182
185
|
recordingId: string,
|
|
186
|
+
authUserId?: string,
|
|
183
187
|
): Promise<RecordingUploadTicket & { token: string }> {
|
|
184
188
|
const token = `${TOKEN_PREFIX}${encodeOwner(ownerEmail)}.${crypto.randomBytes(32).toString("base64url")}`;
|
|
185
189
|
const reservedAt = Date.now();
|
|
@@ -188,6 +192,7 @@ export async function createRecordingUploadTicket(
|
|
|
188
192
|
tokenHash: tokenHash(token),
|
|
189
193
|
reservedAt,
|
|
190
194
|
expiresAt: reservedAt + RECORDING_UPLOAD_TICKET_TTL_MS,
|
|
195
|
+
...(authUserId ? { authUserId } : {}),
|
|
191
196
|
};
|
|
192
197
|
|
|
193
198
|
for (let attempt = 0; attempt < MAX_CAS_ATTEMPTS; attempt += 1) {
|
|
@@ -296,5 +301,8 @@ export async function requireRecordingUploadTicketOwner(
|
|
|
296
301
|
recordingId,
|
|
297
302
|
ownerEmail: verified.ownerEmail,
|
|
298
303
|
orgId: recording.organizationId,
|
|
304
|
+
...(typeof verified.ticket.authUserId === "string"
|
|
305
|
+
? { authUserId: verified.ticket.authUserId }
|
|
306
|
+
: {}),
|
|
299
307
|
};
|
|
300
308
|
}
|
|
@@ -510,6 +510,7 @@ export async function handleRecordingChunk(
|
|
|
510
510
|
recordingId?: string;
|
|
511
511
|
ownerEmail?: string;
|
|
512
512
|
orgId?: string;
|
|
513
|
+
authUserId?: string;
|
|
513
514
|
},
|
|
514
515
|
) {
|
|
515
516
|
const recordingId =
|
|
@@ -579,6 +580,7 @@ export async function handleRecordingChunk(
|
|
|
579
580
|
if (override?.ownerEmail) {
|
|
580
581
|
ownerEmail = override.ownerEmail;
|
|
581
582
|
orgId = override.orgId;
|
|
583
|
+
authUserId = override.authUserId;
|
|
582
584
|
} else {
|
|
583
585
|
try {
|
|
584
586
|
const context = await getEventOwnerContext(event);
|
|
@@ -5,6 +5,16 @@ time from the command menu (Cmd+K → "What's new").
|
|
|
5
5
|
|
|
6
6
|
## 2026-10-19
|
|
7
7
|
|
|
8
|
+
### Improved
|
|
9
|
+
|
|
10
|
+
- Database views can filter one property more than once, number filters add ≥ and ≤, and filter chips name their operator, like "Status: is not done".
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Edits made from a block's menu or a table's row and column menus, such as deleting a table, adding a row or turning off the header row, are now saved instead of coming back after a reload
|
|
15
|
+
- Starting a comment puts the cursor in the comment box, ready to type.
|
|
16
|
+
- Table row and column options now appear for the row or column under the pointer, Escape selects the cell before leaving the editor, wide tables keep their add-column control on screen on phones, and a tap near a table's edge on a touch screen edits the cell there instead of adding a row or column
|
|
17
|
+
|
|
8
18
|
### Changed
|
|
9
19
|
|
|
10
20
|
- Apps no longer keep server functions and databases warm by default; set `AGENT_NATIVE_ENABLE_KEEP_WARM=1` to opt in.
|
|
@@ -32,6 +42,8 @@ time from the command menu (Cmd+K → "What's new").
|
|
|
32
42
|
|
|
33
43
|
### Fixed
|
|
34
44
|
|
|
45
|
+
- Opening a page in a new tab while another tab is still saving no longer sends a second save or files a copy to History.
|
|
46
|
+
- Typing steadily in one tab no longer makes another open tab show "This page changed elsewhere" after its edits saved.
|
|
35
47
|
- Reopening a page after someone else renamed it no longer adds a copy of your edits to Version History
|
|
36
48
|
|
|
37
49
|
## 2026-10-12
|
|
@@ -742,6 +742,8 @@ interface CommentsSidebarOptions {
|
|
|
742
742
|
surface?: CommentSurface;
|
|
743
743
|
/** Closes the anchored popover; shown as its header close button. */
|
|
744
744
|
onClose?: () => void;
|
|
745
|
+
/** Extra header actions for each comment thread's card. */
|
|
746
|
+
renderThreadActions?: (thread: CommentThread) => ReactNode;
|
|
745
747
|
}
|
|
746
748
|
|
|
747
749
|
type CommentsSidebarProps = CommentsSidebarOptions &
|
|
@@ -813,6 +815,7 @@ export function CommentsSidebar({
|
|
|
813
815
|
presentation = "inline",
|
|
814
816
|
surface: surfaceProp,
|
|
815
817
|
onClose,
|
|
818
|
+
renderThreadActions,
|
|
816
819
|
}: CommentsSidebarProps) {
|
|
817
820
|
const surface: CommentSurface =
|
|
818
821
|
surfaceProp ?? (presentation === "history" ? "panel" : "rail");
|
|
@@ -1846,6 +1849,7 @@ export function CommentsSidebar({
|
|
|
1846
1849
|
resolved={Boolean(thread.resolved)}
|
|
1847
1850
|
surface={surface}
|
|
1848
1851
|
onClose={onClose}
|
|
1852
|
+
threadActions={renderThreadActions?.(thread)}
|
|
1849
1853
|
currentUserEmail={currentUserEmail}
|
|
1850
1854
|
quote={thread.quotedText}
|
|
1851
1855
|
propertyTarget={
|
|
@@ -448,12 +448,14 @@ export interface PageEditorSession {
|
|
|
448
448
|
|
|
449
449
|
/**
|
|
450
450
|
* Opens the Page with its Comments showing: one thread when `threadId` is
|
|
451
|
-
* set,
|
|
451
|
+
* set, a new comment on the Property `propertyId` names, otherwise the list.
|
|
452
|
+
* A new `key` asks again.
|
|
452
453
|
*/
|
|
453
454
|
export interface PageCommentIntent {
|
|
454
455
|
key: number;
|
|
455
456
|
documentId: string;
|
|
456
457
|
threadId?: string | null;
|
|
458
|
+
propertyId?: string;
|
|
457
459
|
}
|
|
458
460
|
|
|
459
461
|
export interface PageEditorSurfaceProps extends DocumentEditorProps {
|
|
@@ -7390,6 +7392,7 @@ function PageEditorSessionBody({
|
|
|
7390
7392
|
)
|
|
7391
7393
|
? pagePropertiesQuery.data.properties
|
|
7392
7394
|
: undefined;
|
|
7395
|
+
const pagePropertiesFailed = !pageProperties && pagePropertiesQuery.isError;
|
|
7393
7396
|
const documentLayoutRef = useRef<HTMLDivElement>(null);
|
|
7394
7397
|
const commentLaneRef = useRef<HTMLElement>(null);
|
|
7395
7398
|
const anchoredCommentRef = useRef<HTMLElement>(null);
|
|
@@ -7774,6 +7777,7 @@ function PageEditorSessionBody({
|
|
|
7774
7777
|
],
|
|
7775
7778
|
);
|
|
7776
7779
|
const handledCommentDeepLinkRef = useRef<string | null>(null);
|
|
7780
|
+
const handledPropertyCommentLinkRef = useRef<string | null>(null);
|
|
7777
7781
|
|
|
7778
7782
|
const startPropertyComment = useCallback(
|
|
7779
7783
|
(property: DocumentProperty) => {
|
|
@@ -7910,6 +7914,40 @@ function PageEditorSessionBody({
|
|
|
7910
7914
|
activateCommentThread(threadId, true);
|
|
7911
7915
|
}, [activateCommentThread, documentId, location.search, threads]);
|
|
7912
7916
|
|
|
7917
|
+
// A Collection that opens rows as full pages links here to start a comment
|
|
7918
|
+
// on one Property, as the row's peek does on a touch screen.
|
|
7919
|
+
useEffect(() => {
|
|
7920
|
+
const propertyId = new URLSearchParams(location.search).get(
|
|
7921
|
+
"commentProperty",
|
|
7922
|
+
);
|
|
7923
|
+
if (!propertyId) {
|
|
7924
|
+
handledPropertyCommentLinkRef.current = null;
|
|
7925
|
+
return;
|
|
7926
|
+
}
|
|
7927
|
+
const linkKey = `${documentId}:${propertyId}`;
|
|
7928
|
+
// Wait for the Properties; a failed read opens the list instead.
|
|
7929
|
+
if (
|
|
7930
|
+
handledPropertyCommentLinkRef.current === linkKey ||
|
|
7931
|
+
(!pageProperties && !pagePropertiesFailed)
|
|
7932
|
+
) {
|
|
7933
|
+
return;
|
|
7934
|
+
}
|
|
7935
|
+
handledPropertyCommentLinkRef.current = linkKey;
|
|
7936
|
+
const property = pageProperties?.find(
|
|
7937
|
+
(candidate) => candidate.definition.id === propertyId,
|
|
7938
|
+
);
|
|
7939
|
+
if (property && canComment) startPropertyComment(property);
|
|
7940
|
+
else handleUtilityPanelChange("comments");
|
|
7941
|
+
}, [
|
|
7942
|
+
canComment,
|
|
7943
|
+
documentId,
|
|
7944
|
+
handleUtilityPanelChange,
|
|
7945
|
+
location.search,
|
|
7946
|
+
pageProperties,
|
|
7947
|
+
pagePropertiesFailed,
|
|
7948
|
+
startPropertyComment,
|
|
7949
|
+
]);
|
|
7950
|
+
|
|
7913
7951
|
const handledCommentIntentRef = useRef<number | null>(null);
|
|
7914
7952
|
useEffect(() => {
|
|
7915
7953
|
if (
|
|
@@ -7917,7 +7955,7 @@ function PageEditorSessionBody({
|
|
|
7917
7955
|
handledCommentIntentRef.current === commentIntent.key
|
|
7918
7956
|
)
|
|
7919
7957
|
return;
|
|
7920
|
-
const threadId = commentIntent
|
|
7958
|
+
const { threadId, propertyId } = commentIntent;
|
|
7921
7959
|
if (threadId) {
|
|
7922
7960
|
// Wait for the thread; a thread that is gone opens the list instead.
|
|
7923
7961
|
if (!threads) return;
|
|
@@ -7926,14 +7964,30 @@ function PageEditorSessionBody({
|
|
|
7926
7964
|
activateCommentThread(threadId);
|
|
7927
7965
|
return;
|
|
7928
7966
|
}
|
|
7967
|
+
} else if (propertyId) {
|
|
7968
|
+
// Wait for the Properties; one that is gone, or a failed read, opens
|
|
7969
|
+
// the list instead.
|
|
7970
|
+
if (!pageProperties && !pagePropertiesFailed) return;
|
|
7971
|
+
handledCommentIntentRef.current = commentIntent.key;
|
|
7972
|
+
const property = pageProperties?.find(
|
|
7973
|
+
(candidate) => candidate.definition.id === propertyId,
|
|
7974
|
+
);
|
|
7975
|
+
if (property && canComment) {
|
|
7976
|
+
startPropertyComment(property);
|
|
7977
|
+
return;
|
|
7978
|
+
}
|
|
7929
7979
|
}
|
|
7930
7980
|
handledCommentIntentRef.current = commentIntent.key;
|
|
7931
7981
|
handleUtilityPanelChange("comments");
|
|
7932
7982
|
}, [
|
|
7933
7983
|
activateCommentThread,
|
|
7984
|
+
canComment,
|
|
7934
7985
|
commentIntent,
|
|
7935
7986
|
documentId,
|
|
7936
7987
|
handleUtilityPanelChange,
|
|
7988
|
+
pageProperties,
|
|
7989
|
+
pagePropertiesFailed,
|
|
7990
|
+
startPropertyComment,
|
|
7937
7991
|
threads,
|
|
7938
7992
|
]);
|
|
7939
7993
|
|
|
@@ -171,6 +171,10 @@ import {
|
|
|
171
171
|
PropertyCommentControl,
|
|
172
172
|
usePropertyCommentRowState,
|
|
173
173
|
} from "./property-comments";
|
|
174
|
+
import {
|
|
175
|
+
formatPropertyDate,
|
|
176
|
+
formatPropertyDateTime,
|
|
177
|
+
} from "./property-date-format";
|
|
174
178
|
|
|
175
179
|
type TFunction = ReturnType<typeof useT>;
|
|
176
180
|
|
|
@@ -282,56 +286,12 @@ function slugify(value: string) {
|
|
|
282
286
|
return slug || `option-${Date.now()}`;
|
|
283
287
|
}
|
|
284
288
|
|
|
285
|
-
function formatDate(value: string) {
|
|
286
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
|
287
|
-
const [year, month, day] = value.split("-").map(Number);
|
|
288
|
-
return new Intl.DateTimeFormat(undefined, {
|
|
289
|
-
month: "short",
|
|
290
|
-
day: "numeric",
|
|
291
|
-
year: "numeric",
|
|
292
|
-
}).format(new Date(year, month - 1, day));
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const date = new Date(value);
|
|
296
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
297
|
-
return new Intl.DateTimeFormat(undefined, {
|
|
298
|
-
month: "short",
|
|
299
|
-
day: "numeric",
|
|
300
|
-
year: "numeric",
|
|
301
|
-
}).format(date);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
function formatDateTime(value: string) {
|
|
305
|
-
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(value)) {
|
|
306
|
-
const [datePart, timePart] = value.split("T");
|
|
307
|
-
const [year, month, day] = datePart.split("-").map(Number);
|
|
308
|
-
const [hour, minute] = timePart.split(":").map(Number);
|
|
309
|
-
return new Intl.DateTimeFormat(undefined, {
|
|
310
|
-
month: "short",
|
|
311
|
-
day: "numeric",
|
|
312
|
-
year: "numeric",
|
|
313
|
-
hour: "numeric",
|
|
314
|
-
minute: "2-digit",
|
|
315
|
-
}).format(new Date(year, month - 1, day, hour, minute));
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const date = new Date(value);
|
|
319
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
320
|
-
return new Intl.DateTimeFormat(undefined, {
|
|
321
|
-
month: "short",
|
|
322
|
-
day: "numeric",
|
|
323
|
-
year: "numeric",
|
|
324
|
-
hour: "numeric",
|
|
325
|
-
minute: "2-digit",
|
|
326
|
-
}).format(date);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
289
|
function formatPropertyDateDisplayValue(
|
|
330
290
|
value: DocumentProperty["value"],
|
|
331
291
|
t?: TFunction,
|
|
332
292
|
) {
|
|
333
293
|
const includeTime = documentPropertyDateIncludesTime(value);
|
|
334
|
-
const formatter = includeTime ?
|
|
294
|
+
const formatter = includeTime ? formatPropertyDateTime : formatPropertyDate;
|
|
335
295
|
const start = documentPropertyDatePart(value, "start");
|
|
336
296
|
const end = documentPropertyDatePart(value, "end");
|
|
337
297
|
if (!start) return tWithFallback(t, "editor.properties.empty", "Empty");
|
|
@@ -392,7 +352,7 @@ export function displayValue(
|
|
|
392
352
|
}
|
|
393
353
|
|
|
394
354
|
if (type === "created_time" || type === "last_edited_time") {
|
|
395
|
-
return <span>{
|
|
355
|
+
return <span>{formatPropertyDateTime(propertyText(value))}</span>;
|
|
396
356
|
}
|
|
397
357
|
|
|
398
358
|
if (type === "person") {
|
|
@@ -42,7 +42,8 @@ function subscribeToNoHover(onChange: () => void) {
|
|
|
42
42
|
return () => media.removeEventListener("change", onChange);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
/** Whether no pointer on this device can hover, as on a phone. */
|
|
46
|
+
export function deviceCannotHover() {
|
|
46
47
|
return (
|
|
47
48
|
typeof window !== "undefined" &&
|
|
48
49
|
typeof window.matchMedia === "function" &&
|
|
@@ -301,8 +301,8 @@ import {
|
|
|
301
301
|
useContentTableSelectionGutter,
|
|
302
302
|
} from "./ContentTable";
|
|
303
303
|
import { databaseCanCreateItems, databaseCreateTarget } from "./create-target";
|
|
304
|
+
import { DatabaseCellComments } from "./database-cell-comments";
|
|
304
305
|
import {
|
|
305
|
-
DatabaseCellCommentMarker,
|
|
306
306
|
DatabaseItemCommentsContext,
|
|
307
307
|
DatabaseRowCommentCount,
|
|
308
308
|
type OpenDatabaseItemComments,
|
|
@@ -1931,7 +1931,11 @@ function DatabaseTable({
|
|
|
1931
1931
|
}
|
|
1932
1932
|
|
|
1933
1933
|
// Opens the row with its Comments showing, from a count or a cell marker.
|
|
1934
|
-
const previewItemComments: OpenDatabaseItemComments = (
|
|
1934
|
+
const previewItemComments: OpenDatabaseItemComments = (
|
|
1935
|
+
item,
|
|
1936
|
+
threadId,
|
|
1937
|
+
propertyId,
|
|
1938
|
+
) => {
|
|
1935
1939
|
if (openWorkspaceFiles(item)) return;
|
|
1936
1940
|
seedDatabaseItemDocumentCaches(queryClient, item);
|
|
1937
1941
|
prioritizeBuilderBodyHydrationForItem(item);
|
|
@@ -1941,18 +1945,19 @@ function DatabaseTable({
|
|
|
1941
1945
|
databaseId,
|
|
1942
1946
|
document.id,
|
|
1943
1947
|
);
|
|
1944
|
-
|
|
1945
|
-
()
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
);
|
|
1948
|
+
const link = threadId
|
|
1949
|
+
? `${path}&comment=${encodeURIComponent(threadId)}`
|
|
1950
|
+
: propertyId
|
|
1951
|
+
? `${path}&commentProperty=${encodeURIComponent(propertyId)}`
|
|
1952
|
+
: path;
|
|
1953
|
+
runPreviewTransition(() => void navigate(link));
|
|
1950
1954
|
return;
|
|
1951
1955
|
}
|
|
1952
1956
|
const intent: PageCommentIntent = {
|
|
1953
1957
|
key: ++previewCommentIntentSequenceRef.current,
|
|
1954
1958
|
documentId: item.document.id,
|
|
1955
1959
|
threadId,
|
|
1960
|
+
propertyId,
|
|
1956
1961
|
};
|
|
1957
1962
|
if (item.document.id === previewDocumentId) {
|
|
1958
1963
|
setPreviewCommentIntent(intent);
|
|
@@ -3672,7 +3677,12 @@ function DatabaseTable({
|
|
|
3672
3677
|
onOpenPage={openItemPage}
|
|
3673
3678
|
/>
|
|
3674
3679
|
) : (
|
|
3675
|
-
|
|
3680
|
+
// The read-only ChatGPT widget can't read or write Comments.
|
|
3681
|
+
<DatabaseItemCommentsContext.Provider
|
|
3682
|
+
value={
|
|
3683
|
+
document.mcpDirectoryWidgetReadOnly ? null : previewItemComments
|
|
3684
|
+
}
|
|
3685
|
+
>
|
|
3676
3686
|
<DatabaseTableView
|
|
3677
3687
|
startupAnchored={renderMode === "page"}
|
|
3678
3688
|
columnOrderIds={activeView.tableColumnOrderIds ?? []}
|
|
@@ -18687,7 +18697,7 @@ function DatabaseTableRow({
|
|
|
18687
18697
|
<div
|
|
18688
18698
|
key={property.definition.id}
|
|
18689
18699
|
className={cn(
|
|
18690
|
-
"flex min-w-0 hover:bg-muted/25",
|
|
18700
|
+
"group/cell relative flex min-w-0 hover:bg-muted/25",
|
|
18691
18701
|
databaseTableCellDensityClass(rowDensity),
|
|
18692
18702
|
wrapCells ? "items-start" : "items-center",
|
|
18693
18703
|
)}
|
|
@@ -18716,10 +18726,15 @@ function DatabaseTableRow({
|
|
|
18716
18726
|
) : (
|
|
18717
18727
|
value
|
|
18718
18728
|
)}
|
|
18719
|
-
<
|
|
18729
|
+
<DatabaseCellComments
|
|
18720
18730
|
item={item}
|
|
18721
|
-
|
|
18722
|
-
|
|
18731
|
+
property={itemProperty}
|
|
18732
|
+
rowSelected={selected}
|
|
18733
|
+
besideEditButton={
|
|
18734
|
+
canEdit &&
|
|
18735
|
+
itemProperty.editable &&
|
|
18736
|
+
itemProperty.definition.type === "relation"
|
|
18737
|
+
}
|
|
18723
18738
|
/>
|
|
18724
18739
|
</div>
|
|
18725
18740
|
);
|