Skip to content

[MAT-240] 필기 시스템 packages로 분리 작업#262

Open
b0nsu wants to merge 11 commits intodevelopfrom
refactor/mat-240-drawing-extract
Open

[MAT-240] 필기 시스템 packages로 분리 작업#262
b0nsu wants to merge 11 commits intodevelopfrom
refactor/mat-240-drawing-extract

Conversation

@b0nsu
Copy link
Copy Markdown
Collaborator

@b0nsu b0nsu commented Apr 7, 2026

📌 Related Issue Number


✅ Key Changes

이번 PR에서 작업한 내용을 간략히 설명해주세요

  1. add @repo/pointer-native-drawing package

    • SCRAP 내부에 구현된 skia/drawing 기능을 유지보수를 위해 별도의 싱글톤 패키지로 추출 및 packages 추가
    • metro도 모듈이 중복 번들링 되지 않도록 단일 경로로 고정시킴
  2. migrate to shared package and remove unsupported props

    • packages 로 분리된 pointer-native-drawing 의 기능이 minimal 하여 지원되지 않는 기능들을 일시적으로 제거

b0nsu and others added 3 commits April 7, 2026 18:03
Draw/erase-only React Native Skia canvas module extracted as a shared monorepo package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rops

Replace local DrawingCanvas and smoothing utilities with @repo/pointer-native-drawing.
Remove undo/redo and textMode props not yet supported by the shared package.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent duplicate bundling of react, react-native, reanimated, and gesture-handler in pnpm monorepo.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@b0nsu b0nsu requested review from Copilot and sterdsterd April 7, 2026 09:41
@linear
Copy link
Copy Markdown

linear bot commented Apr 7, 2026

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pointer-admin Ready Ready Preview, Comment Apr 12, 2026 8:34am

@b0nsu b0nsu changed the title MAT-240 [MAT-240] 필기-시스템-packages-로-분리-작업 Apr 7, 2026
@b0nsu b0nsu changed the title [MAT-240] 필기-시스템-packages-로-분리-작업 [MAT-240] 필기 시스템 packages로 분리 작업 Apr 7, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Extracts the Scrap drawing/Skia logic into a new shared workspace package (@repo/pointer-native-drawing) and migrates the native app to consume it, while temporarily removing unsupported features.

Changes:

  • Added new @repo/pointer-native-drawing package (tsup build, TS config, Skia drawing canvas + path smoothing).
  • Migrated apps/native Scrap Skia utilities to re-export/use the shared package and removed legacy local drawing/smoothing modules.
  • Updated native UI/state wiring to drop undo/redo history props and adjusted Metro config to try to prevent singleton module double-bundling.

Reviewed changes

Copilot reviewed 18 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/pointer-native-drawing/package.json Declares the new shared drawing package entrypoints/peers.
packages/pointer-native-drawing/tsup.config.ts Adds build config for ESM/CJS + externals.
packages/pointer-native-drawing/tsconfig.json TypeScript config for the shared package.
packages/pointer-native-drawing/src/index.ts Public exports for the shared package.
packages/pointer-native-drawing/src/DrawingCanvas.tsx New shared Skia drawing canvas implementation.
packages/pointer-native-drawing/src/smoothing.ts New shared path smoothing implementation.
apps/native/src/features/student/scrap/utils/skia/index.ts Re-exports drawing utilities from the shared package.
apps/native/src/features/student/scrap/utils/handwritingEncoder.ts Updates type imports to use the new re-export surface.
apps/native/src/features/student/scrap/hooks/useHandwritingManager.ts Updates ref type import path.
apps/native/src/features/student/scrap/screens/ScrapDetailScreen.tsx Swaps to shared DrawingCanvas import and removes history/text props.
apps/native/src/features/student/scrap/hooks/useDrawingState.ts Removes undo/redo history state plumbing.
apps/native/src/features/student/scrap/components/scrap/DrawingToolbar.tsx Removes undo/redo UI and props.
apps/native/src/features/student/problem/screens/ProblemScreen.tsx Removes history props wiring to the drawing toolbar/canvas.
apps/native/src/features/student/problem/components/ProblemDrawingToolbar.tsx Removes undo/redo UI and props.
apps/native/package.json Adds workspace dependency on @repo/pointer-native-drawing and bumps reanimated patch.
apps/native/metro.config.js Adds custom resolve logic intended to pin singleton modules to a single physical path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +640 to +644
getStrokes,
setStrokes: setStrokesFromOutside,
getTexts: () => [],
setTexts: () => {},
}),
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DrawingCanvasRef.getTexts() always returns an empty array and setTexts() is a no-op. The app still loads/saves handwriting texts via these methods (e.g., useHandwritingManager calls setTexts and later persists getTexts), so this will silently drop previously-saved text items on the next save. Either implement real text storage (even if not rendered) or remove these methods from the ref type and update callers to avoid persisting/overwriting text data.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +90
textMode?: boolean;
highlighterMode?: boolean;
highlighterWidth?: number;
enableZoomPan?: boolean;
minZoomScale?: number;
maxZoomScale?: number;
viewportTransform?: DrawingViewportTransform;
textFontPath?: unknown;
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DrawingCanvasProps still exposes several props (e.g. textMode, highlighterMode, zoom/pan options, viewportTransform, textFontPath) that are not used by the component implementation. This advertises unsupported behavior to consumers and makes migrations error-prone. Either remove these props from the public type for now or implement the corresponding behavior in DrawingCanvas.

Suggested change
textMode?: boolean;
highlighterMode?: boolean;
highlighterWidth?: number;
enableZoomPan?: boolean;
minZoomScale?: number;
maxZoomScale?: number;
viewportTransform?: DrawingViewportTransform;
textFontPath?: unknown;

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +28
SkPath,
SkPicture,
Skia,
StrokeCap,
StrokeJoin,
} from '@shopify/react-native-skia';
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SkPath/SkPicture appear to be used only as types in this module. Importing them as runtime values can break the ESM build if @shopify/react-native-skia doesn't export those names at runtime, and it also increases the chance of duplicate/unused imports. Prefer import type { SkPath, SkPicture } ... and keep only runtime values (e.g. Skia) as value imports.

Suggested change
SkPath,
SkPicture,
Skia,
StrokeCap,
StrokeJoin,
} from '@shopify/react-native-skia';
Skia,
StrokeCap,
StrokeJoin,
} from '@shopify/react-native-skia';
import type { SkPath, SkPicture } from '@shopify/react-native-skia';

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,57 @@
import { Skia, SkPath } from '@shopify/react-native-skia';
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SkPath is only used as a return type here; importing it as a runtime value can break the generated ESM output if @shopify/react-native-skia doesn't export SkPath at runtime. Prefer a type-only import (import type { SkPath } ...).

Suggested change
import { Skia, SkPath } from '@shopify/react-native-skia';
import { Skia } from '@shopify/react-native-skia';
import type { SkPath } from '@shopify/react-native-skia';

Copilot uses AI. Check for mistakes.
Comment on lines 614 to 639
@@ -638,10 +634,8 @@ const ScrapDetailScreen = () => {
ref={canvasRef}
strokeColor='#1E1E21'
strokeWidth={drawingState.strokeWidth}
textMode={drawingState.isTextMode}
eraserMode={drawingState.isEraserMode}
eraserSize={drawingState.eraserSize}
onHistoryChange={drawingState.setHistoryState}
/>
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Text mode is still exposed in the UI (DrawingToolbar uses isTextMode/onTextModePress), but DrawingCanvas is no longer passed textMode and the shared DrawingCanvas implementation doesn’t appear to implement text input. This makes the Text button misleading and can result in unexpected behavior (e.g., still drawing strokes while the UI indicates text mode). Either remove/disable text mode in this screen/state, or reintroduce proper text support via the shared package.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +51
// 싱글턴 패키지는 항상 apps/native 기준 경로로 resolve
const base = moduleName.split('/')[0];
if (singletonMap[base]) {
return { type: 'sourceFile', filePath: require.resolve(moduleName) };
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The singleton-resolve logic computes singletonMap but doesn’t use it when resolving: for singleton packages you return require.resolve(moduleName), which may still resolve to different physical copies depending on Node resolution/hoisting and won’t reliably prevent duplicate bundling in a pnpm monorepo. Use the computed singleton base path when resolving (e.g., require.resolve(moduleName, { paths: [singletonMap[base]] }) or an equivalent Metro resolver approach) so the path is actually pinned.

Suggested change
// 싱글턴 패키지는 항상 apps/native 기준 경로로 resolve
const base = moduleName.split('/')[0];
if (singletonMap[base]) {
return { type: 'sourceFile', filePath: require.resolve(moduleName) };
// 싱글턴 패키지는 항상 고정된 단일 설치 경로 기준으로 resolve
const base = moduleName.startsWith('@')
? moduleName.split('/').slice(0, 2).join('/')
: moduleName.split('/')[0];
if (singletonMap[base]) {
return {
type: 'sourceFile',
filePath: require.resolve(moduleName, { paths: [singletonMap[base]] }),
};

Copilot uses AI. Check for mistakes.
b0nsu and others added 3 commits April 8, 2026 10:54
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
git-subtree-dir: packages/pointer-native-drawing
git-subtree-split: ac29ede5c13e2f9f769c47c846bb2d03d262720f
@b0nsu b0nsu closed this Apr 8, 2026
- Rename to @repo/pointer-native-drawing, set private:true
- Fix package.json exports (./package.json) and codegenConfig for Fabric codegen
- Fix StylusInputView native event name and ivar access
- Fix codegen spec (remove interfaceOnly, use Double[])
- Set iOS deployment target to 15.1
- Add backgroundColor/children props to DrawingCanvas for overlay pattern
- Migrate ProblemScreen to DrawingCanvas children API
- Remove deleted API references (setTexts/getTexts, TextItem, DrawingViewportTransform)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@b0nsu b0nsu reopened this Apr 9, 2026
b0nsu and others added 3 commits April 12, 2026 16:25
…3a9a7f

503a9a7f docs: update README with current API, props table, and architecture
a51f5597 refactor: move height buffer logic from document to viewport controller
5d98e76e refactor: unify eraser phase state machine with draw lifecycle
3c4ef476 fix: correct eraser onEnd comment to match actual phaseShared behavior
105bfbf5 fix: correct API names in feature-spec-check doc
584cfe71 fix: address review findings — dep array, gesture finalize, pinch dead commit
ede72be6 docs: add feature spec check with implementation status
46477517 fix: canvas height expansion buffer uses viewport height
a6c8e492 feat: update example app with tool selector, undo/redo, zoom toggle
f1b338a5 refactor: pinch/pan gesture coordination with worklet SharedValue
02331abc fix: onEdit prop missing in CanvasOverlayLayer + dependency array corrections
5e5e41c0 Merge branch 'refactor/drawingcanvas-decomposition-v2' into main
5e4acd93 refactor: decompose DrawingCanvas into responsibility-based modules
d644d3f8 Merge branch 'fix/canvas-input-clamp' into main
0a447308 fix: address 8 bugs from pre-merge code review
db7d072d fix: clamp draw/erase input coordinates to canvas bounds
102fc879 fix: textbox move boundary clamping and new textbox selection overlay
6e2689eb fix: add body tap gesture to TextBoxSelectionOverlay for edit re-entry
36bb1739 fix: auto-commit on tool switch, suppress draw in textbox mode, dismiss commits editing
118678f1 refactor: rewrite TextBox selection overlay with all-RNGH gestures
c67517a7 fix: resolve TextBox stale closure, blur race, and canvas bounds (B1/B2/G1-G3)
d263a5fe fix: adversarial review — endSession, textBoxesRef, Paragraph dispose
97b346a8 fix: address code review findings (CRITICAL 1 + HIGH 3)
a8b94c5a fix: address production readiness feedback (4 items)
e42cf07d feat: add TextBox edit, resize, and move (1-4, 1-5, 1-6)
f5111a26 feat: add undo/redo HistoryManager and TextBox MVP (create + delete)
72898ed9 fix: pinch zoom focal-point anchoring, finger-lift jump, and rendering bugs
82738bff feat: add zoom/pan support with enableZoomPan prop
160a5012 Merge branch 'feature/native-path-builder'
5cd9f75c refactor: extract smoothing factor constant, remove unused velocity recomputation, fix SkPath dispose
45f2b26f Merge pull request #1 from team-ppointer/feature/native-path-builder
0bf4eae2 docs: add rendering pipeline analysis and native technology guide
559df493 fix: strokeWidth prop now correctly applied in fixed-width mode
718b2019 refactor: remove TuningPanel, update pen sizes to 0.2/0.75/1.45mm
3b0d3a1f refactor: 1€ filter to RNGH only + trim tuning panel
cb62aeb9 refactor: move 1€ filter to RNGH adapter only (finger/60Hz input)
d4ad482e fix: migrate C++ to SkPathBuilder API + fix podspec header resolution
c7a4b9c2 fix: thread targetSpacing through native buildCenterlinePath
9ee97bb3 feat: add 1€ filter for stylus input smoothing
735aebfc fix: reduce prefix/tail overlap to 1 sample to minimize AA seam
c9ac6ac8 feat: add DPI-aware buildCenterlinePath for fixed-width rendering
6d7cd561 feat: add iOS predicted touches for lower-latency live rendering
66d69d12 refactor: deprecate variable-width rendering, use fixed-width only
8fa22881 docs: add JSDoc for nativeBuildCenterlinePath and packPoints
1aaceab2 fix: address third-round review findings
7b4c7e8f fix: address second-round review findings
98b739b7 fix: address remaining review findings for native path builder
17a95829 feat: add native C++ JSI path builder with Skia integration
1a2c93ff feat: add fixed-width mode, eraser cursor, and children overlay pattern
5c4c4429 Perf/memory optimization and fix live stroke end-taper artifact
ca80947f Stabilize sample pipeline: recompute velocities, smooth centerline, EMA continuity
8ee16e35 Add example app for testing drawing features on iOS
05dc0708 Fix RN 0.85 + Skia 2.6.x compatibility and add pencilOnly prop
19d2f959 Fix codegen event array types: ReadonlyArray<Double> → Double[]

git-subtree-dir: packages/pointer-native-drawing
git-subtree-split: 503a9a7f746cb4fc56475b7dd3ddece0de2330eb
…/mat-240-drawing-extract

# Conflicts:
#	packages/pointer-native-drawing/ios/StylusInputView.mm
#	packages/pointer-native-drawing/src/DrawingCanvas.tsx
#	packages/pointer-native-drawing/src/specs/StylusInputViewNativeComponent.ts
…indicator

- Update pointer-native-drawing package to latest (subtree pull)
- Add pencilOnly prop to both ScrapDetailScreen and ProblemScreen
- Enable enableZoomPan on both screens
- Add scroll indicator with black style to DrawingCanvas
- Fix ProblemScreen minCanvasHeight to screenHeight * 2
- Rename text mode props (isTextMode -> isTextBoxMode, activeTool)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add undo/redo buttons to DrawingToolbar and ProblemDrawingToolbar
- Add strokeColor state to useDrawingState with lastColor persistence
- Save/load textBoxes in useHandwritingManager (getTextBoxes/setTextBoxes)
- Add lastColor field to handwritingEncoder for color restoration
- Export TextBoxData type from skia index
- Wire onUndoStateChange callback to both screens

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants