@agimon-ai/po-author 0.0.0-alpha.79 → 0.0.0-alpha.80

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.
@@ -1,7 +1,7 @@
1
1
  import { apiResponse, createApiClient, decodeBase64, defineChannelFile, defineFileLinks, defineFill, defineGlobalStore, defineNativePlugin, defineSessionStore, defineSlotFile, defineToolRenderer, defineWebLifecycle, encodeBase64, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
2
2
  import { Store } from "@tanstack/store";
3
3
  import { Image } from "react-native-unistyles/components/native/Image";
4
- import { AnnotationSurface, Badge, Button, EmptyState, Markdown, MessageItem, MessageItemBody, MessageItemHeader, MessageItemStatus, SectionLabel, SegmentedControl, Sheet, SheetBody, SheetContent, SheetDescription, SheetHeader, SheetTitle, Spinner, Textarea, TrashIcon, collapseLines, fontOf, resultTextLines, selectionTick, toolTone } from "@agimon-ai/po-native-components";
4
+ import { AnnotationSurface, Badge, Button, EmptyState, Markdown, MessageItem, MessageItemBody, MessageItemHeader, MessageItemStatus, SectionLabel, SegmentedControl, Sheet, SheetBody, SheetContent, SheetDescription, SheetHeader, SheetTitle, Spinner, Textarea, TrashIcon, collapseLines, fontOf, resultTextLines, selectionTick, sheetsYielded, toolTone } from "@agimon-ai/po-native-components";
5
5
  import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
6
6
  import { AppState } from "react-native";
7
7
  import { View } from "react-native-unistyles/components/native/View";
@@ -1249,6 +1249,28 @@ async function saveAuthorNativeStructured(sessionId, path, file, signal) {
1249
1249
  }
1250
1250
  //#endregion
1251
1251
  //#region src/extensions/workspaces/sessions/(frontend)/_lib/authorMarkdownText.ts
1252
+ const AUTHOR_MARKDOWN_FORMATS = [
1253
+ {
1254
+ format: "bold",
1255
+ label: "Bold",
1256
+ glyph: "B"
1257
+ },
1258
+ {
1259
+ format: "heading",
1260
+ label: "Heading",
1261
+ glyph: "H"
1262
+ },
1263
+ {
1264
+ format: "link",
1265
+ label: "Link",
1266
+ glyph: "↗"
1267
+ },
1268
+ {
1269
+ format: "list",
1270
+ label: "List",
1271
+ glyph: "≡"
1272
+ }
1273
+ ];
1252
1274
  const HEADING = /^#{1,6} /;
1253
1275
  const LIST_ITEM = /^(?:[-*+]|\d+[.)]) /;
1254
1276
  /**
@@ -2382,6 +2404,27 @@ const s$1 = StyleSheet.create((theme, rt) => ({
2382
2404
  }
2383
2405
  }));
2384
2406
  //#endregion
2407
+ //#region src/extensions/workspaces/sessions/(frontend)/_components/AuthorFormattingSheet.native.tsx
2408
+ function AuthorFormattingSheet({ open, onOpenChange, onFormat, onDismiss, disabled = false }) {
2409
+ return /* @__PURE__ */ jsx(Sheet, {
2410
+ open,
2411
+ onOpenChange,
2412
+ children: /* @__PURE__ */ jsxs(SheetContent, {
2413
+ onDismiss,
2414
+ children: [/* @__PURE__ */ jsx(SheetHeader, {
2415
+ closeLabel: "Close formatting",
2416
+ children: /* @__PURE__ */ jsx(SheetTitle, { children: "Formatting" })
2417
+ }), /* @__PURE__ */ jsxs(SheetBody, { children: [/* @__PURE__ */ jsx(SheetDescription, { children: "Choose how to format the selected text." }), AUTHOR_MARKDOWN_FORMATS.map(({ format, label }) => /* @__PURE__ */ jsx(Button, {
2418
+ variant: "ghost",
2419
+ size: "card",
2420
+ disabled,
2421
+ onPress: () => onFormat(format),
2422
+ children: label
2423
+ }, format))] })]
2424
+ })
2425
+ });
2426
+ }
2427
+ //#endregion
2385
2428
  //#region src/extensions/workspaces/sessions/(frontend)/_components/AuthorDocumentView.native.tsx
2386
2429
  const DRAFT_ID = "draft";
2387
2430
  /** One open document on the phone: the content to mark up, its notes, and one way to hand them to the agent. */
@@ -2395,6 +2438,18 @@ function AuthorDocumentView(props) {
2395
2438
  });
2396
2439
  const [sourceSelection, setSourceSelection] = useState();
2397
2440
  const sourceKey = `${props.name}\n${props.sourceSha256 ?? ""}`;
2441
+ const [formattingOpen, setFormattingOpen] = useState(false);
2442
+ const [formattingNotice, setFormattingNotice] = useState();
2443
+ const editor = useRef(null);
2444
+ const restoringSelection = useRef(false);
2445
+ const formattingRange = useRef(void 0);
2446
+ useEffect(() => {
2447
+ if (formattingRange.current?.key !== sourceKey || !props.edit || props.edit.saving) {
2448
+ formattingRange.current = void 0;
2449
+ setFormattingOpen(false);
2450
+ setFormattingNotice(void 0);
2451
+ }
2452
+ }, [sourceKey, props.edit]);
2398
2453
  const selectedRange = body.kind === "text" && sourceSelection?.key === sourceKey ? nativeAuthorTextRange(body.text, sourceSelection) : void 0;
2399
2454
  if (body.kind === "image" && !props.edit) return /* @__PURE__ */ jsx(AuthorCanvasWorkspace, {
2400
2455
  ...props,
@@ -2407,15 +2462,48 @@ function AuthorDocumentView(props) {
2407
2462
  const range = body.kind === "text" && note.sourceSha256 === props.sourceSha256 ? nativeAuthorTextRange(body.text, note.textRange) : void 0;
2408
2463
  return range === void 0 ? "Source selection: " : range.startLine === range.endLine ? `Line ${String(range.startLine)}: ` : `Lines ${String(range.startLine)} to ${String(range.endLine)}: `;
2409
2464
  };
2410
- const formatMarkdown = (format) => {
2465
+ const openFormatting = () => {
2411
2466
  if (props.edit?.text === void 0 || props.edit.saving || !props.onEditChange) return;
2467
+ formattingRange.current = {
2468
+ key: sourceKey,
2469
+ text: props.edit.text,
2470
+ range: { ...selection },
2471
+ restore: { ...selection }
2472
+ };
2473
+ setFormattingNotice(void 0);
2474
+ setFormattingOpen(true);
2475
+ };
2476
+ const formatMarkdown = (format) => {
2477
+ const snapshot = formattingRange.current;
2478
+ if (!snapshot || snapshot.resultText !== void 0 || props.edit?.text === void 0 || props.edit.saving || !props.onEditChange) return;
2479
+ if (snapshot.key !== sourceKey || snapshot.text !== props.edit.text) {
2480
+ setFormattingNotice("Text changed while formatting was open. Select it again.");
2481
+ setFormattingOpen(false);
2482
+ return;
2483
+ }
2412
2484
  const text = props.edit.text;
2413
- const edit = authorMarkdownFormat(text, Math.min(selection.start, text.length), Math.min(selection.end, text.length), format);
2414
- props.onEditChange(text.slice(0, edit.from) + edit.insert + text.slice(edit.to));
2415
- setSelection({
2485
+ const edit = authorMarkdownFormat(text, Math.min(snapshot.range.start, text.length), Math.min(snapshot.range.end, text.length), format);
2486
+ snapshot.resultText = text.slice(0, edit.from) + edit.insert + text.slice(edit.to);
2487
+ snapshot.restore = {
2416
2488
  start: edit.select.from,
2417
2489
  end: edit.select.to
2418
- });
2490
+ };
2491
+ props.onEditChange(snapshot.resultText);
2492
+ setSelection(snapshot.restore);
2493
+ setFormattingOpen(false);
2494
+ };
2495
+ const restoreAfterFormatting = () => {
2496
+ const snapshot = formattingRange.current;
2497
+ if (snapshot && snapshot.key === sourceKey && props.edit?.text === (snapshot.resultText ?? snapshot.text) && !props.edit.saving) {
2498
+ setSelection(snapshot.restore);
2499
+ restoringSelection.current = true;
2500
+ try {
2501
+ if (!sheetsYielded()) editor.current?.focus();
2502
+ } finally {
2503
+ restoringSelection.current = false;
2504
+ }
2505
+ }
2506
+ formattingRange.current = void 0;
2419
2507
  };
2420
2508
  const marks = nativeAuthorVisibleNotes([...notes.map((note, index) => ({
2421
2509
  id: note.id,
@@ -2637,6 +2725,13 @@ function AuthorDocumentView(props) {
2637
2725
  }) : null
2638
2726
  ]
2639
2727
  }),
2728
+ /* @__PURE__ */ jsx(AuthorFormattingSheet, {
2729
+ open: formattingOpen,
2730
+ onOpenChange: setFormattingOpen,
2731
+ onFormat: formatMarkdown,
2732
+ onDismiss: restoreAfterFormatting,
2733
+ disabled: props.edit?.saving || !props.onEditChange
2734
+ }),
2640
2735
  /* @__PURE__ */ jsxs(ScrollView, {
2641
2736
  style: s.scroll,
2642
2737
  contentContainerStyle: s.content,
@@ -2665,30 +2760,39 @@ function AuthorDocumentView(props) {
2665
2760
  }, fragment.id))
2666
2761
  }) : props.edit ? /* @__PURE__ */ jsxs(View, {
2667
2762
  style: s.notes,
2668
- children: [markdown ? /* @__PURE__ */ jsx(View, {
2669
- style: s.toolbar,
2670
- children: [
2671
- "bold",
2672
- "heading",
2673
- "list",
2674
- "link"
2675
- ].map((format) => /* @__PURE__ */ jsx(Button, {
2676
- variant: "ghost",
2677
- disabled: props.edit?.saving || !props.onEditChange,
2678
- accessibilityLabel: `Format ${format}`,
2679
- onPress: () => formatMarkdown(format),
2680
- children: format[0].toUpperCase() + format.slice(1)
2681
- }, format))
2682
- }) : null, /* @__PURE__ */ jsx(Textarea, {
2683
- accessibilityLabel: `Edit ${props.name}`,
2684
- rows: 16,
2685
- value: props.edit.text,
2686
- onChangeText: props.onEditChange,
2687
- selection: markdown ? selection : void 0,
2688
- onSelectionChange: markdown ? (event) => setSelection(event.nativeEvent.selection) : void 0,
2689
- disabled: props.edit.saving,
2690
- autoFocus: true
2691
- })]
2763
+ children: [
2764
+ markdown ? /* @__PURE__ */ jsx(View, {
2765
+ style: s.toolbar,
2766
+ children: /* @__PURE__ */ jsx(Button, {
2767
+ variant: "outline",
2768
+ size: "card",
2769
+ style: s.grow,
2770
+ accessibilityLabel: "Formatting",
2771
+ accessibilityState: { expanded: formattingOpen },
2772
+ disabled: props.edit?.saving || !props.onEditChange,
2773
+ onPress: openFormatting,
2774
+ children: "Formatting"
2775
+ })
2776
+ }) : null,
2777
+ formattingNotice ? /* @__PURE__ */ jsx(Text, {
2778
+ style: s.failed,
2779
+ accessibilityLiveRegion: "polite",
2780
+ children: formattingNotice
2781
+ }) : null,
2782
+ /* @__PURE__ */ jsx(Textarea, {
2783
+ ref: editor,
2784
+ accessibilityLabel: `Edit ${props.name}`,
2785
+ rows: 16,
2786
+ value: props.edit.text,
2787
+ onChangeText: props.onEditChange,
2788
+ selection: markdown ? selection : void 0,
2789
+ onSelectionChange: markdown ? (event) => {
2790
+ if (!formattingOpen && !restoringSelection.current) setSelection(event.nativeEvent.selection);
2791
+ } : void 0,
2792
+ disabled: props.edit.saving,
2793
+ autoFocus: true
2794
+ })
2795
+ ]
2692
2796
  }) : props.captureContent ? props.captureContent(annotation) : annotation,
2693
2797
  (notes.length === 0 || inspectingSource) && !draft && !props.edit ? /* @__PURE__ */ jsx(Text, {
2694
2798
  style: s.meta,