commit b7293d9b99f410902c63ba7d76119f6ef94c23d5
parent 281b02ef3bc2819d8f5f80decea26aed59cc2c4e
Author: minerva-jupiter <ryouturn@gmail.com>
Date: Thu, 23 Oct 2025 08:23:23 +0900
feat: add drawing stage and enhance chat progression(onComplete)
Diffstat:
5 files changed, 146 insertions(+), 14 deletions(-)
diff --git a/app/components/1_chat.tsx b/app/components/1_chat.tsx
@@ -6,7 +6,7 @@ import init, { chat } from '../../rust-wasm/pkg/rust_wasm.js';
const FirstChat: React.FC<StageProps> = ({ onComplete }) => {
return(
- <ChatPage/>
+ <ChatPage onComplete={onComplete}/>
)
};
@@ -114,7 +114,7 @@ const MessageInput: React.FC<{ onSend: (text: string) => void }> = ({ onSend })
-function ChatPage() {
+function ChatPage({onComplete}:StageProps) {
const [messages, setMessages] = useState<Message[]>(initialMessages);
const [ dict, setDict ] = useState<Uint8Array|undefined>(undefined);
const messagesEndRef = useRef<HTMLDivElement>(null);
@@ -136,6 +136,8 @@ function ChatPage() {
init();
}, []);
+ let talktimes = 1;
+
const handleSendMessage = useCallback((text: string) => {
console.log(dict);
if (text.trim() === '') return;
@@ -153,7 +155,12 @@ function ChatPage() {
sender: 'ai',
};
setMessages((prev) => [...prev, aiResponse]);
- }, [dict]);
+ talktimes += 1;
+ console.log("talktimes is "+talktimes);
+ if(talktimes >= 3){
+ onComplete();
+ }
+ }, [dict, onComplete]);
const pageContainerStyle: React.CSSProperties = {
display: 'flex',
diff --git a/app/components/2_draw.tsx b/app/components/2_draw.tsx
@@ -1,16 +1,126 @@
-import React from 'react';
+'use clinet'
+
+import React, { useState, useRef, useCallback } from 'react';
import { StageProps } from '../ctrl/page.tsx';
+import { Stage, Layer, Line as KonvaLine, Text } from 'react-konva';
+import type { KonvaEventObject } from 'konva/lib/Node';
+import type Konva from 'konva';
const SecondDraw: React.FC<StageProps> = ({ onComplete }) => {
return(
<div>
- <h1>
- this is SecondDraw
- </h1>
- <button type='button' onClick={onComplete}>onComplete</button>
+ <h1>this is draw</h1>
+ <DrawingApp onComplete={onComplete}/>
</div>
)
};
+type Tool = 'pen' | 'eraser';
+
+interface LineData {
+ tool: Tool;
+ points: number[]; // [x1, y1, x2, y2, ...] の形式
+}
+
+function DrawingApp({onComplete}:StageProps) {
+ const tool = 'pen';
+ const [lines, setLines] = useState<LineData[]>([]);
+ const isDrawing = useRef(false);
+
+ const stageRef = useRef<Konva.Stage | null>(null);
+
+ const getPointerPosition = (stage: Konva.Stage | null) => {
+ return stage?.getPointerPosition() ?? { x: 0, y: 0 };
+ };
+
+ /**
+ * マウス・タッチ開始時の処理
+ */
+ const handleMouseDown = useCallback((e: KonvaEventObject<MouseEvent | TouchEvent>) => {
+ isDrawing.current = true;
+ const stage = e.target.getStage();
+ if (stage) {
+ const pos = getPointerPosition(stage);
+ // 新しいラインを追加
+ setLines((prevLines) => [
+ ...prevLines,
+ { tool, points: [pos.x, pos.y] },
+ ]);
+ }
+ }, [tool]); // toolが変更されたら再生成
+
+ /**
+ * マウス・タッチ移動時の処理
+ */
+ const handleMouseMove = useCallback((e: KonvaEventObject<MouseEvent | TouchEvent>) => {
+ if (!isDrawing.current) {
+ return;
+ }
+
+ const stage = e.target.getStage();
+ if (!stage) return;
+
+ const point = getPointerPosition(stage);
+
+ setLines((prevLines) => {
+ // 1. 最後のラインのインデックスを取得
+ const lastLineIndex = prevLines.length - 1;
+ if (lastLineIndex < 0) return prevLines; // 念のためのチェック
+
+ const lastLine = prevLines[lastLineIndex];
+
+ // 2. 最後の LineData オブジェクトを不変に更新
+ const newLine: LineData = {
+ ...lastLine, // 既存のプロパティをコピー
+ // points配列に新しいポイントを追加して、新しい配列を作成
+ points: lastLine.points.concat([point.x, point.y]),
+ };
+
+ // 3. lines配列全体を不変に更新
+ return [
+ ...prevLines.slice(0, lastLineIndex), // 最後の要素以外はそのままコピー
+ newLine, // 完全に新しい LineData オブジェクトで置き換える
+ ];
+ });
+ }, []);
+
+ /**
+ * マウス・タッチ終了時の処理
+ */
+ const handleMouseUp = useCallback(() => {
+ isDrawing.current = false;
+ }, []);
+
+ return (
+ <div>
+ <Stage
+ width={globalThis.innerWidth}
+ height={globalThis.innerWidth}
+ onMouseDown={handleMouseDown}
+ onMouseMove={handleMouseMove}
+ onMouseUp={handleMouseUp}
+ onTouchStart={handleMouseDown}
+ onTouchMove={handleMouseMove}
+ onTouchEnd={handleMouseUp}
+ ref={stageRef}
+ >
+ <Layer>
+ <Text text="Just start drawing" x={5} y={30} fontSize={16} fill="#000" />
+ {lines.map((line, i) => (
+ <KonvaLine // `Line`がHTML要素と競合する可能性があるので`KonvaLine`としてインポート
+ key={i}
+ points={line.points}
+ stroke="#ffffff"
+ strokeWidth={5} // Eraserは少し太くする
+ tension={0.5}
+ lineCap="round"
+ lineJoin="round"
+ />
+ ))}
+ </Layer>
+ </Stage>
+ </div>
+ );
+};
export default SecondDraw;
diff --git a/package.json b/package.json
@@ -5,22 +5,23 @@
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack",
- "wasmbuild": "cd ./rust-wasm/ && wasm-pack build --target web",
+ "wasmbuild": "cd ./rust-wasm/ && wasm-pack build --target web",
"start": "next start",
"lint": "eslint"
},
"dependencies": {
+ "next": "15.5.5",
"react": "19.1.0",
"react-dom": "19.1.0",
- "next": "15.5.5"
+ "react-konva": "^19.0.10"
},
"devDependencies": {
- "typescript": "^5.9.3",
+ "@eslint/eslintrc": "^3.3.1",
"@types/node": "^20.19.22",
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"eslint": "^9.38.0",
"eslint-config-next": "15.5.5",
- "@eslint/eslintrc": "^3.3.1"
+ "typescript": "^5.9.3"
}
}
diff --git a/rust-wasm/pkg/rust_wasm_bg.wasm b/rust-wasm/pkg/rust_wasm_bg.wasm
Binary files differ.
diff --git a/rust-wasm/src/lib.rs b/rust-wasm/src/lib.rs
@@ -1,4 +1,4 @@
-use std::io::Cursor;
+use std::{io:: Cursor, usize};
use vibrato::{Dictionary, Tokenizer};
use wasm_bindgen::prelude::*;
@@ -14,6 +14,20 @@ pub fn chat(dict_data: &[u8], input: &str) -> Result<String, JsValue> {
worker.reset_sentence(input);
worker.tokenize();
- let ans : String= "馬鹿なことを言ってないで。".to_string();
+ let mut ans : String= "馬鹿なことを言ってないで。".to_string();
+
+ match worker.num_tokens() {
+ 1..5 => {
+ ans = "何を言っているの?".to_string();
+ },
+ 5..10 => {
+ ans = "そんなことができるわけないじゃない?".to_string();
+ },
+ 10..=usize::MAX => {
+ ans = "そんなこと思ってるんじゃないんでしょ?".to_string();
+ }
+ _ => {ans = "意味がわからない。".to_string();},
+ }
+
Ok(ans)
}