WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 6e0b121

Browse files
authored
Merge pull request #35 from swarno-tech/rewrite
Key board shortcuts
2 parents b44a6c4 + 25a3e2b commit 6e0b121

File tree

3 files changed

+193
-81
lines changed

3 files changed

+193
-81
lines changed
Lines changed: 157 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// lib/features/workspace/pages/workspace_desktop.dart (Fully Modified)
2-
3-
import 'package:cookethflow/core/helpers/responsive_layout.helper.dart' as rh;
42
import 'package:cookethflow/core/providers/supabase_provider.dart';
3+
import 'package:cookethflow/core/utils/enums.dart';
54
import 'package:cookethflow/features/workspace/pages/canvas_page.dart';
65
import 'package:cookethflow/features/workspace/providers/canvas_provider.dart';
76
import 'package:cookethflow/features/workspace/providers/workspace_provider.dart';
@@ -10,85 +9,177 @@ import 'package:cookethflow/features/workspace/widgets/node_editing_toolbox.dart
109
import 'package:cookethflow/features/workspace/widgets/toolbar.dart';
1110
import 'package:cookethflow/features/workspace/widgets/undo_redo_button.dart';
1211
import 'package:cookethflow/features/workspace/widgets/workspace_drawer.dart';
12+
import 'package:cookethflow/features/workspace/widgets/workspace_shortcuts.dart'; // shortcut file
1313
import 'package:cookethflow/features/workspace/widgets/zoom_control_button.dart';
1414
import 'package:flutter/material.dart';
1515
import 'package:provider/provider.dart';
1616
import 'package:flutter_screenutil/flutter_screenutil.dart';
1717
import 'package:cookethflow/features/workspace/widgets/object_text_editor.dart';
1818
import 'package:vector_math/vector_math_64.dart' as vector_math;
1919

20-
class WorkspaceDesktop extends StatelessWidget {
20+
class WorkspaceDesktop extends StatefulWidget {
2121
const WorkspaceDesktop({super.key});
2222

2323
@override
24-
Widget build(BuildContext context) {
25-
bool isDesktop =
26-
rh.ResponsiveLayoutHelper.getDeviceType(context) ==
27-
rh.DeviceType.desktop;
28-
29-
return Consumer2<WorkspaceProvider,SupabaseService>(builder: (context, provider,suprovider, child) {
30-
return Scaffold(
31-
backgroundColor: provider.currentWorkspaceColor,
32-
body: Padding(
33-
padding: EdgeInsets.symmetric(horizontal: 40.w, vertical: 40.h),
34-
child: Stack(
35-
clipBehavior: Clip.none,
36-
children: [
37-
const CanvasPage(),
38-
39-
const WorkspaceDrawer(),
40-
SizedBox(width: 20.w),
41-
Positioned(top: 0, left: 0.21.sw, child: UndoRedoButton(su: suprovider,)),
42-
// MODIFIED: Pass the WorkspaceProvider instance to the button
43-
Positioned(top: 0, right: 0.001.sw, child: ExportProjectButton(su: suprovider, wp: provider)),
44-
45-
Positioned(right: 0, top: 0.10.sh, child: ToolBar()),
46-
47-
Positioned(
48-
bottom: 0.h,
49-
right: 0.w,
50-
child: ZoomControlButton(),
51-
),
24+
_WorkspaceDesktopState createState() => _WorkspaceDesktopState();
25+
}
5226

53-
Consumer2<WorkspaceProvider, CanvasProvider>(
54-
builder: (context, workspaceProvider, canvasProvider, child) {
55-
return ListenableBuilder(
56-
listenable: canvasProvider.transformationController,
57-
builder: (context, child) {
58-
if (workspaceProvider.shouldShowObjectToolbox) {
59-
final selectedObject = workspaceProvider.canvasObjects[
60-
workspaceProvider.currentlySelectedObjectId!]!;
61-
final objectBounds = selectedObject.getBounds();
62-
final matrix =
63-
canvasProvider.transformationController.value;
27+
class _WorkspaceDesktopState extends State<WorkspaceDesktop> {
28+
final FocusNode _focusNode = FocusNode();
6429

65-
final transformedTopCenter = matrix.transform3(
66-
vector_math.Vector3(objectBounds.topCenter.dx,
67-
objectBounds.topCenter.dy, 0));
30+
@override
31+
void initState() {
32+
super.initState();
33+
// Request focus when the widget is first built
34+
_focusNode.requestFocus();
35+
}
6836

69-
final screenPosition = Offset(
70-
transformedTopCenter.x, transformedTopCenter.y);
37+
@override
38+
void dispose() {
39+
// Clean up the focus node when the widget is disposed
40+
_focusNode.dispose();
41+
super.dispose();
42+
}
7143

72-
const double toolboxWidth = 240;
73-
const double toolboxHeight = 48;
44+
@override
45+
Widget build(BuildContext context) {
46+
// Define actions
47+
final Map<Type, Action<Intent>> actions = {
48+
PointerIntent: CallbackAction<PointerIntent>(
49+
onInvoke: (intent) {
50+
final provider = Provider.of<WorkspaceProvider>(
51+
context,
52+
listen: false,
53+
);
54+
provider.changeDrawMode(DrawMode.pointer);
55+
return null;
56+
},
57+
),
58+
PanIntent: CallbackAction<PanIntent>(
59+
onInvoke: (intent) {
60+
final provider = Provider.of<WorkspaceProvider>(
61+
context,
62+
listen: false,
63+
);
64+
provider.changeDrawMode(DrawMode.hand);
65+
return null;
66+
},
67+
),
68+
TextIntent: CallbackAction<TextIntent>(
69+
onInvoke: (intent) {
70+
final provider = Provider.of<WorkspaceProvider>(
71+
context,
72+
listen: false,
73+
);
74+
provider.changeDrawMode(DrawMode.textBox);
75+
return null;
76+
},
77+
),
78+
};
7479

75-
return Positioned(
76-
left: screenPosition.dx - (toolboxWidth / 2),
77-
top: screenPosition.dy - toolboxHeight - 15,
78-
child: const NodeEditingToolbox(),
79-
);
80-
}
81-
return const SizedBox.shrink();
82-
},
83-
);
84-
},
80+
return Consumer2<WorkspaceProvider, SupabaseService>(
81+
builder: (context, provider, suprovider, child) {
82+
return Shortcuts(
83+
shortcuts: workspaceShortCut,
84+
child: Actions(
85+
actions: actions,
86+
child: Focus(
87+
focusNode: _focusNode,
88+
child: Scaffold(
89+
backgroundColor: provider.currentWorkspaceColor,
90+
body: GestureDetector(
91+
onTap: () {
92+
// This ensures focus is regained when the user taps on the canvas
93+
_focusNode.requestFocus();
94+
},
95+
child: Padding(
96+
padding: EdgeInsets.symmetric(
97+
horizontal: 40.w,
98+
vertical: 40.h,
99+
),
100+
child: Stack(
101+
clipBehavior: Clip.none,
102+
children: [
103+
const CanvasPage(),
104+
const WorkspaceDrawer(),
105+
SizedBox(width: 20.w),
106+
Positioned(
107+
top: 0,
108+
left: 0.21.sw,
109+
child: UndoRedoButton(su: suprovider),
110+
),
111+
Positioned(
112+
top: 0,
113+
right: 0.001.sw,
114+
child: ExportProjectButton(
115+
su: suprovider,
116+
wp: provider,
117+
),
118+
),
119+
Positioned(right: 0, top: 0.10.sh, child: ToolBar()),
120+
Positioned(
121+
bottom: 0.h,
122+
right: 0.w,
123+
child: ZoomControlButton(),
124+
),
125+
Consumer2<WorkspaceProvider, CanvasProvider>(
126+
builder: (
127+
context,
128+
workspaceProvider,
129+
canvasProvider,
130+
child,
131+
) {
132+
return ListenableBuilder(
133+
listenable:
134+
canvasProvider.transformationController,
135+
builder: (context, child) {
136+
if (workspaceProvider.shouldShowObjectToolbox) {
137+
final selectedObject =
138+
workspaceProvider
139+
.canvasObjects[workspaceProvider
140+
.currentlySelectedObjectId!]!;
141+
final objectBounds =
142+
selectedObject.getBounds();
143+
final matrix =
144+
canvasProvider
145+
.transformationController
146+
.value;
147+
final transformedTopCenter = matrix
148+
.transform3(
149+
vector_math.Vector3(
150+
objectBounds.topCenter.dx,
151+
objectBounds.topCenter.dy,
152+
0,
153+
),
154+
);
155+
final screenPosition = Offset(
156+
transformedTopCenter.x,
157+
transformedTopCenter.y,
158+
);
159+
const double toolboxWidth = 240;
160+
const double toolboxHeight = 48;
161+
return Positioned(
162+
left:
163+
screenPosition.dx - (toolboxWidth / 2),
164+
top: screenPosition.dy - toolboxHeight - 15,
165+
child: const NodeEditingToolbox(),
166+
);
167+
}
168+
return const SizedBox.shrink();
169+
},
170+
);
171+
},
172+
),
173+
const ObjectTextEditor(),
174+
],
175+
),
176+
),
177+
),
85178
),
86-
87-
const ObjectTextEditor(),
88-
],
179+
),
89180
),
90-
),
91-
);
92-
});
181+
);
182+
},
183+
);
93184
}
94-
}
185+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// it is the file to control the keyboard shortcuts
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter/services.dart';
4+
5+
6+
// define intents
7+
class PointerIntent extends Intent {}
8+
9+
class PanIntent extends Intent {}
10+
11+
class TextIntent extends Intent {}
12+
13+
// define shortcuts
14+
15+
final Map<LogicalKeySet, Intent> workspaceShortCut = {
16+
LogicalKeySet(LogicalKeyboardKey.keyP): PointerIntent(),
17+
LogicalKeySet(LogicalKeyboardKey.keyA): PanIntent(),
18+
LogicalKeySet(LogicalKeyboardKey.keyT): TextIntent(),
19+
};
20+
21+

pubspec.lock

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,10 @@ packages:
181181
dependency: transitive
182182
description:
183183
name: fake_async
184-
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
184+
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
185185
url: "https://pub.dev"
186186
source: hosted
187-
version: "1.3.2"
187+
version: "1.3.3"
188188
ffi:
189189
dependency: transitive
190190
description:
@@ -553,10 +553,10 @@ packages:
553553
dependency: transitive
554554
description:
555555
name: intl
556-
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
556+
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
557557
url: "https://pub.dev"
558558
source: hosted
559-
version: "0.19.0"
559+
version: "0.20.2"
560560
jwt_decode:
561561
dependency: transitive
562562
description:
@@ -569,26 +569,26 @@ packages:
569569
dependency: transitive
570570
description:
571571
name: leak_tracker
572-
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
572+
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
573573
url: "https://pub.dev"
574574
source: hosted
575-
version: "10.0.8"
575+
version: "11.0.1"
576576
leak_tracker_flutter_testing:
577577
dependency: transitive
578578
description:
579579
name: leak_tracker_flutter_testing
580-
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
580+
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
581581
url: "https://pub.dev"
582582
source: hosted
583-
version: "3.0.9"
583+
version: "3.0.10"
584584
leak_tracker_testing:
585585
dependency: transitive
586586
description:
587587
name: leak_tracker_testing
588-
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
588+
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
589589
url: "https://pub.dev"
590590
source: hosted
591-
version: "3.0.1"
591+
version: "3.0.2"
592592
lints:
593593
dependency: transitive
594594
description:
@@ -1054,10 +1054,10 @@ packages:
10541054
dependency: transitive
10551055
description:
10561056
name: test_api
1057-
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
1057+
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
10581058
url: "https://pub.dev"
10591059
source: hosted
1060-
version: "0.7.4"
1060+
version: "0.7.6"
10611061
typed_data:
10621062
dependency: transitive
10631063
description:
@@ -1158,10 +1158,10 @@ packages:
11581158
dependency: "direct main"
11591159
description:
11601160
name: vector_math
1161-
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
1161+
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
11621162
url: "https://pub.dev"
11631163
source: hosted
1164-
version: "2.1.4"
1164+
version: "2.2.0"
11651165
vm_service:
11661166
dependency: transitive
11671167
description:
@@ -1219,5 +1219,5 @@ packages:
12191219
source: hosted
12201220
version: "2.1.0"
12211221
sdks:
1222-
dart: ">=3.7.2 <4.0.0"
1222+
dart: ">=3.8.0-0 <4.0.0"
12231223
flutter: ">=3.27.0"

0 commit comments

Comments
 (0)