From f92c077e0e7fa370a2a43c32c2435e15b7f2cd43 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 20:19:03 +0900
Subject: [PATCH 01/14] Update App.tsx
make big reset/shuffle buttons for kids
---
src/App.tsx | 52 ++++++++++++++++++++++++++++------------------------
1 file changed, 28 insertions(+), 24 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 21cde67..31e64d6 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -306,30 +306,34 @@ export const App = observer(() => {
gap={5}
>
{vm.mode === Mode.Play && (
-
-
-
-
-
- )}
+
+ {/* 처음 상태로 리셋 */}
+
+
+ {/* 랜덤 섞기(셔플) */}
+
+
+)}
+
{vm.mode === Mode.Edit && (
<>
Date: Sat, 6 Dec 2025 20:29:53 +0900
Subject: [PATCH 02/14] Update App.tsx
trigger pages deploy
---
src/App.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/App.tsx b/src/App.tsx
index 31e64d6..0afbb79 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -305,6 +305,7 @@ export const App = observer(() => {
]}
gap={5}
>
+ // trigger pages deploy
{vm.mode === Mode.Play && (
Date: Sat, 6 Dec 2025 20:45:51 +0900
Subject: [PATCH 03/14] Create deploy.yml
Add GitHub Pages deploy workflow
---
.github/workflows/deploy.yml | 50 ++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 .github/workflows/deploy.yml
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..26e61e9
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,50 @@
+name: Deploy Vite app to GitHub Pages
+
+on:
+ push:
+ branches: [ master ]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: "pages"
+ cancel-in-progress: true
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: yarn
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Build Vite app
+ run: yarn build
+
+ - name: Upload build artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: dist
+
+ deploy:
+ needs: build
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
From ae0f98e69844b03dd6e43ca1626895a273bff8e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 21:49:28 +0900
Subject: [PATCH 04/14] Update App.tsx
const clockwise = rightClick;
---
src/App.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/App.tsx b/src/App.tsx
index 0afbb79..2a2b049 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -156,7 +156,7 @@ export class AppViewModel extends BaseViewModel {
) {
if (this.mode === Mode.Solve) return;
- const clockwise = !rightClick;
+ const clockwise = rightClick;
if (this.mode === Mode.Play) {
this.state = this.state.rotate(corner, clockwise);
From 9438fd7671ad44cc4b51edda1d7941296bdb3b7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 22:31:14 +0900
Subject: [PATCH 05/14] Update App.tsx
---
src/App.tsx | 65 +++++++++++++++++++++++++++++++++++------------------
1 file changed, 43 insertions(+), 22 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 2a2b049..e94c290 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -37,6 +37,15 @@ export enum ExplodingState {
UnExploding,
Done,
}
+type CornerIndex = 0 | 1 | 2 | 3;
+
+// 각 코너별로 "push(밀기)가 clockwise(true)인지 counterclockwise(false)인지"
+const PUSH_DIR: Record = {
+ 0: true, // corner 0에서 push=clockwise
+ 1: true, // corner 1에서 push=clockwise
+ 2: true, // corner 2에서 push=clockwise
+ 3: true, // corner 3에서 push=clockwise
+};
export class AppViewModel extends BaseViewModel {
state = State.solved();
@@ -149,24 +158,31 @@ export class AppViewModel extends BaseViewModel {
);
}
- handleCornerClick(
- corner: 0 | 1 | 2 | 3,
- _side: 0 | 1 | 2 | undefined,
- rightClick: boolean,
- ) {
- if (this.mode === Mode.Solve) return;
+ handleCornerClick(
+ corner: CornerIndex,
+ _side: 0 | 1 | 2 | undefined,
+ rightClick: boolean,
+) {
+ if (this.mode === Mode.Solve) return;
- const clockwise = rightClick;
+ // 쌤 규칙: 우클릭 = push(밀기, 바깥쪽), 좌클릭 = pull(당기기, 안쪽)
+ const isPush = rightClick;
- if (this.mode === Mode.Play) {
- this.state = this.state.rotate(corner, clockwise);
- }
+ // 이 코너에서 push일 때 실제 회전 방향(clockwise?)을 가져옴
+ const pushIsClockwise = PUSH_DIR[corner];
- if (this.mode === Mode.Edit) {
- this.state = this.state.rotateCorner(corner, clockwise);
- }
+ // push면 PUSH_DIR대로, pull이면 그 반대로
+ const clockwise = isPush ? pushIsClockwise : !pushIsClockwise;
+
+ if (this.mode === Mode.Play) {
+ this.state = this.state.rotate(corner, clockwise);
}
+ if (this.mode === Mode.Edit) {
+ this.state = this.state.rotateCorner(corner, clockwise);
+ }
+}
+
handleCenterClick(center: 0 | 1 | 2 | 3 | 4 | 5, _rightClick: boolean) {
this.doNotTurnPls = true;
@@ -443,15 +459,20 @@ export const App = observer(() => {
- vm.handleCornerClick(corner, side, false)}
- onCornerRightClick={(corner, side) =>
- vm.handleCornerClick(corner, side, true)
- }
- onCenterClick={(center) => vm.handleCenterClick(center, false)}
- onCenterRightClick={(center) => vm.handleCenterClick(center, true)}
- state={vm.mode === Mode.Solve ? vm.pathState : vm.state}
- />
+ {
+ console.log('LEFT CLICK', corner, side);
+ vm.handleCornerClick(corner, side, false);
+ }}
+ onCornerRightClick={(corner, side) => {
+ console.log('RIGHT CLICK', corner, side);
+ vm.handleCornerClick(corner, side, true);
+ }}
+ onCenterClick={(center) => vm.handleCenterClick(center, false)}
+ onCenterRightClick={(center) => vm.handleCenterClick(center, true)}
+ state={vm.mode === Mode.Solve ? vm.pathState : vm.state}
+/>
+
From fef0fabcc9a7942008f6190d5adb3d279c48c126 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 22:36:33 +0900
Subject: [PATCH 06/14] Update App.tsx
test
---
src/App.tsx | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index e94c290..b504dc6 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -158,27 +158,25 @@ export class AppViewModel extends BaseViewModel {
);
}
- handleCornerClick(
+handleCornerClick(
corner: CornerIndex,
_side: 0 | 1 | 2 | undefined,
rightClick: boolean,
) {
if (this.mode === Mode.Solve) return;
- // 쌤 규칙: 우클릭 = push(밀기, 바깥쪽), 좌클릭 = pull(당기기, 안쪽)
+ // 우클릭=push(바깥쪽), 좌클릭=pull(안쪽)
const isPush = rightClick;
- // 이 코너에서 push일 때 실제 회전 방향(clockwise?)을 가져옴
+ // 이 코너에서 push=clockwise?
const pushIsClockwise = PUSH_DIR[corner];
- // push면 PUSH_DIR대로, pull이면 그 반대로
+ // push는 지정된 방향, pull은 반대
const clockwise = isPush ? pushIsClockwise : !pushIsClockwise;
if (this.mode === Mode.Play) {
this.state = this.state.rotate(corner, clockwise);
- }
-
- if (this.mode === Mode.Edit) {
+ } else if (this.mode === Mode.Edit) {
this.state = this.state.rotateCorner(corner, clockwise);
}
}
From cf8985c0f46b68f4c183598832ca49d623df3564 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 22:43:06 +0900
Subject: [PATCH 07/14] Update App.tsx
test
---
src/App.tsx | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index b504dc6..1402667 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -40,13 +40,16 @@ export enum ExplodingState {
type CornerIndex = 0 | 1 | 2 | 3;
// 각 코너별로 "push(밀기)가 clockwise(true)인지 counterclockwise(false)인지"
+type CornerIndex = 0 | 1 | 2 | 3;
+
const PUSH_DIR: Record = {
- 0: true, // corner 0에서 push=clockwise
- 1: true, // corner 1에서 push=clockwise
- 2: true, // corner 2에서 push=clockwise
- 3: true, // corner 3에서 push=clockwise
+ 0: true,
+ 1: false, // 🔹 왼쪽 위 코너: push(우클릭)는 counterclockwise 쪽이 바깥
+ 2: true,
+ 3: true, // 🔹 오른쪽 위 코너: push(우클릭)는 clockwise 쪽이 바깥
};
+
export class AppViewModel extends BaseViewModel {
state = State.solved();
mode = Mode.Play;
From 0c46edaed6945ebd0347369dc90a2eed9709edd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 22:55:53 +0900
Subject: [PATCH 08/14] Update App.tsx
test
---
src/App.tsx | 53 ++++++++++++++++++++++++-----------------------------
1 file changed, 24 insertions(+), 29 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 1402667..04d19d2 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -24,6 +24,13 @@ import { action } from 'mobx';
import { createContext, useContext, useState } from 'react';
import { InfoDialog } from './components/dialogs/InfoDialog';
+const PUSH_DIR: Record<0 | 1 | 2 | 3, boolean> = {
+ 0: true,
+ 1: false, // 왼쪽 위 코너: 우클릭이 안쪽이었으니 반대로!
+ 2: true,
+ 3: true, // 오른쪽 위 코너: 우클릭이 이미 바깥쪽이므로 그대로
+};
+
const graph = genGraph();
export enum Mode {
@@ -37,18 +44,6 @@ export enum ExplodingState {
UnExploding,
Done,
}
-type CornerIndex = 0 | 1 | 2 | 3;
-
-// 각 코너별로 "push(밀기)가 clockwise(true)인지 counterclockwise(false)인지"
-type CornerIndex = 0 | 1 | 2 | 3;
-
-const PUSH_DIR: Record = {
- 0: true,
- 1: false, // 🔹 왼쪽 위 코너: push(우클릭)는 counterclockwise 쪽이 바깥
- 2: true,
- 3: true, // 🔹 오른쪽 위 코너: push(우클릭)는 clockwise 쪽이 바깥
-};
-
export class AppViewModel extends BaseViewModel {
state = State.solved();
@@ -161,28 +156,28 @@ export class AppViewModel extends BaseViewModel {
);
}
-handleCornerClick(
- corner: CornerIndex,
- _side: 0 | 1 | 2 | undefined,
- rightClick: boolean,
-) {
- if (this.mode === Mode.Solve) return;
+ handleCornerClick(
+ corner: 0 | 1 | 2 | 3,
+ _side: 0 | 1 | 2 | undefined,
+ rightClick: boolean,
+ ) {
+ if (this.mode === Mode.Solve) return;
- // 우클릭=push(바깥쪽), 좌클릭=pull(안쪽)
- const isPush = rightClick;
+ // 우클릭 = push(바깥쪽), 좌클릭 = pull(안쪽)
+ const isPush = rightClick;
- // 이 코너에서 push=clockwise?
- const pushIsClockwise = PUSH_DIR[corner];
+ // 이 코너에서 push(우클릭)가 어느 방향인지
+ const pushIsClockwise = PUSH_DIR[corner];
- // push는 지정된 방향, pull은 반대
- const clockwise = isPush ? pushIsClockwise : !pushIsClockwise;
+ // push는 그 방향, pull은 반대 방향
+ const clockwise = isPush ? pushIsClockwise : !pushIsClockwise;
- if (this.mode === Mode.Play) {
- this.state = this.state.rotate(corner, clockwise);
- } else if (this.mode === Mode.Edit) {
- this.state = this.state.rotateCorner(corner, clockwise);
+ if (this.mode === Mode.Play) {
+ this.state = this.state.rotate(corner, clockwise);
+ } else if (this.mode === Mode.Edit) {
+ this.state = this.state.rotateCorner(corner, clockwise);
+ }
}
-}
handleCenterClick(center: 0 | 1 | 2 | 3 | 4 | 5, _rightClick: boolean) {
this.doNotTurnPls = true;
From 8ff8145b5ee09f4920aa01780605b844e9c5720c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 23:19:50 +0900
Subject: [PATCH 09/14] Update App.tsx
test
---
src/App.tsx | 61 +++++++++++++++++++++++++++++------------------------
1 file changed, 34 insertions(+), 27 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 04d19d2..fc9d718 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -380,7 +380,7 @@ export const App = observer(() => {
>
{cubeColorKeys
.map((key) => ({ key, color: cubeColors[key] }))
- .map(({ key, color }) => (
+ .map(({ key, }) => (
)}
-
);
From 737fb2f23bd829d6ef3c78a41854f92a1c12a0d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sat, 6 Dec 2025 23:34:39 +0900
Subject: [PATCH 10/14] Update App.tsx
test
---
src/App.tsx | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index fc9d718..51bf4da 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -380,7 +380,8 @@ export const App = observer(() => {
>
{cubeColorKeys
.map((key) => ({ key, color: cubeColors[key] }))
- .map(({ key, }) => (
+ .map(({ key, color }) => (
+
)}
- {
state={vm.mode === Mode.Solve ? vm.pathState : vm.state}
/>
-
+
);
From 505860f6ddeead662989e4fa79b3e3e67b48184c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sun, 7 Dec 2025 01:24:07 +0900
Subject: [PATCH 13/14] Update App.tsx
test
---
src/App.tsx | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 0127a70..02b34c3 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,7 +1,7 @@
/* eslint-disable react/no-unknown-property */
import { Canvas } from '@react-three/fiber';
-import { TrackballControls } from '@react-three/drei';
+import { OrbitControls } from '@react-three/drei';
import { absolute, flexCenter, fullSize, padding } from './styles';
import { State, StateDto } from './graph/types';
@@ -48,6 +48,7 @@ export enum ExplodingState {
export class AppViewModel extends BaseViewModel {
state = State.solved();
mode = Mode.Play;
+ view: 'front' | 'corner' = 'front';
// this is possibly the sloppiest code I've ever written but this
// was the easiest hack I could come up with to fix the stupid turning bug
@@ -300,6 +301,8 @@ export const App = observer(() => {
icon={IconNames.InfoSign}
onClick={() => setShowDialog((p) => !p)}
/>
+
+
{
@@ -456,7 +459,13 @@ export const App = observer(() => {
-
+
{
console.log("LEFT CLICK", corner, side);
@@ -470,13 +479,16 @@ export const App = observer(() => {
onCenterRightClick={(center) => vm.handleCenterClick(center, true)}
state={vm.mode === Mode.Solve ? vm.pathState : vm.state}
/>
+
+
-
From 7ef9953d0127e0470115dcb1f5c7855d77187f9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?YE=3AME=5F=EC=98=88=EB=AF=B8?=
<161493755+YEMEHUB@users.noreply.github.com>
Date: Sun, 7 Dec 2025 01:33:47 +0900
Subject: [PATCH 14/14] Update App.tsx
test
---
src/App.tsx | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index 02b34c3..9f43aad 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -463,7 +463,7 @@ export const App = observer(() => {
rotation={
vm.view === 'front'
? [0, 0, 0]
- : [-Math.PI / 4, Math.PI / 4, 0] // 대각선에서 코너가 보이는 각도 (숫자는 필요하면 조금씩 조절)
+ : [Math.PI / 4, Math.PI / 4, 0] // 대각선에서 코너가 보이는 각도 (숫자는 필요하면 조금씩 조절)
}
>
{
target={[0, 0, 0]}
minPolarAngle={0.3} // 너무 위/아래는 막고
maxPolarAngle={Math.PI - 0.3}
- minAzimuthAngle={-Math.PI / 2.2} // 측면으로 너무 돌지 않게
- maxAzimuthAngle={Math.PI / 2.2}
+
/>