plusui-native-core 0.1.8 → 0.1.10
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.
- package/Core/CMakeLists.txt +2 -1
- package/Core/Features/Bindings/ARCHITECTURE.md +328 -0
- package/Core/Features/Bindings/CustomBindings/custom_bindings.cpp +53 -0
- package/Core/Features/Bindings/CustomBindings/custom_bindings.ts +35 -0
- package/Core/Features/Bindings/EXAMPLE_USAGE.hpp +143 -0
- package/Core/Features/Bindings/EXAMPLE_USAGE.tsx +210 -0
- package/Core/Features/Bindings/IPC_GUIDE.md +325 -0
- package/Core/Features/Bindings/NativeBindings/native_bindings.cpp +30 -0
- package/Core/Features/Bindings/NativeBindings/native_bindings.ts +29 -0
- package/Core/Features/Bindings/UNIFIED_SYSTEM.md +351 -0
- package/Core/Features/FileDrop/filedrop.cpp +316 -0
- package/Core/Features/FileDrop/filedrop.css +421 -0
- package/Core/Features/FileDrop/filedrop.ts +269 -0
- package/Core/include/plusui/bindings.hpp +65 -0
- package/Core/include/plusui/custom_bindings.hpp +17 -0
- package/Core/include/plusui/filedrop.hpp +77 -0
- package/Core/include/plusui/native_bindings.hpp +19 -0
- package/package.json +1 -1
package/Core/CMakeLists.txt
CHANGED
|
@@ -19,7 +19,8 @@ else()
|
|
|
19
19
|
add_definitions(-DPLUSUI_GTK)
|
|
20
20
|
endif()
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Features/Bindings/NativeBindings/native_bindings.cpp
|
|
23
|
+
Features/Bindings/CustomBindings/custom_bindings.cpp
|
|
23
24
|
Features/App/app.cpp
|
|
24
25
|
Features/Window/window.cpp
|
|
25
26
|
Features/WindowManager/window_manager.cpp
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# PlusUI Binding System Architecture
|
|
2
|
+
|
|
3
|
+
## Complete Flow Diagram
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
7
|
+
│ DEVELOPER WORKFLOW │
|
|
8
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
9
|
+
|
|
10
|
+
1. Define Bindings in C++
|
|
11
|
+
┌──────────────────────────────────────────────────┐
|
|
12
|
+
│ // src/features/myapp.hpp │
|
|
13
|
+
│ #include <plusui/bindings.hpp> │
|
|
14
|
+
│ │
|
|
15
|
+
│ // Methods (Frontend → Backend) │
|
|
16
|
+
│ PLUSUI_BIND(getUserName, string, void) │
|
|
17
|
+
│ PLUSUI_BIND(calculate, int, int, int) │
|
|
18
|
+
│ │
|
|
19
|
+
│ // Events (Backend → Frontend, start with "on") │
|
|
20
|
+
│ PLUSUI_BIND(onDataUpdated, void, json) │
|
|
21
|
+
└──────────────────────────────────────────────────┘
|
|
22
|
+
↓
|
|
23
|
+
|
|
24
|
+
2. Run Code Generation
|
|
25
|
+
┌──────────────────────────────────────────────────┐
|
|
26
|
+
│ $ plusui generate │
|
|
27
|
+
│ │
|
|
28
|
+
│ plusui-bindgen: │
|
|
29
|
+
│ - Scans all C++ files │
|
|
30
|
+
│ - Finds PLUSUI_BIND macros │
|
|
31
|
+
│ - Detects native core usage │
|
|
32
|
+
│ - Generates TypeScript bindings │
|
|
33
|
+
│ - Generates C++ metadata │
|
|
34
|
+
└──────────────────────────────────────────────────┘
|
|
35
|
+
↓
|
|
36
|
+
|
|
37
|
+
3. Generated Files
|
|
38
|
+
┌──────────────────────────────────────────────────┐
|
|
39
|
+
│ src/Bindings/ │
|
|
40
|
+
│ ├── bindings.gen.ts ← Import this! │
|
|
41
|
+
│ ├── bindings.gen.hpp ← C++ metadata │
|
|
42
|
+
│ ├── NativeBindings/ ← Core features │
|
|
43
|
+
│ │ ├── CPP_IO/ │
|
|
44
|
+
│ │ └── WEB_IO/ │
|
|
45
|
+
│ └── CustomBindings/ ← Your features │
|
|
46
|
+
│ ├── CPP_IO/ │
|
|
47
|
+
│ └── WEB_IO/ │
|
|
48
|
+
└──────────────────────────────────────────────────┘
|
|
49
|
+
↓
|
|
50
|
+
|
|
51
|
+
4. Use in TypeScript
|
|
52
|
+
┌──────────────────────────────────────────────────┐
|
|
53
|
+
│ import { plusui } from './bindings.gen'; │
|
|
54
|
+
│ │
|
|
55
|
+
│ // Call backend │
|
|
56
|
+
│ const name = await plusui.myapp.getUserName(); │
|
|
57
|
+
│ const result = await plusui.myapp.calculate(5,3);│
|
|
58
|
+
│ │
|
|
59
|
+
│ // Listen to events │
|
|
60
|
+
│ plusui.myapp.onDataUpdated((data) => { │
|
|
61
|
+
│ updateUI(data); │
|
|
62
|
+
│ }); │
|
|
63
|
+
└──────────────────────────────────────────────────┘
|
|
64
|
+
↓
|
|
65
|
+
|
|
66
|
+
5. Build & Run
|
|
67
|
+
┌──────────────────────────────────────────────────┐
|
|
68
|
+
│ $ plusui build │
|
|
69
|
+
│ │
|
|
70
|
+
│ - Compiles C++ with CMake │
|
|
71
|
+
│ - Bundles frontend with Vite │
|
|
72
|
+
│ - Links bindings at runtime │
|
|
73
|
+
│ - Creates single executable │
|
|
74
|
+
└──────────────────────────────────────────────────┘
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
78
|
+
│ RUNTIME FLOW │
|
|
79
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
80
|
+
|
|
81
|
+
Frontend → Backend (Method Call)
|
|
82
|
+
──────────────────────────────────
|
|
83
|
+
|
|
84
|
+
TypeScript:
|
|
85
|
+
plusui.myapp.getUserName()
|
|
86
|
+
↓
|
|
87
|
+
Generated binding class calls:
|
|
88
|
+
invoke("myapp.getUserName", [])
|
|
89
|
+
↓
|
|
90
|
+
WebView bridge serializes:
|
|
91
|
+
{ id: 1, method: "myapp.getUserName", params: [] }
|
|
92
|
+
↓
|
|
93
|
+
IPC via window.__invoke__
|
|
94
|
+
↓
|
|
95
|
+
C++:
|
|
96
|
+
Binding dispatcher receives JSON
|
|
97
|
+
↓
|
|
98
|
+
Routes to registered handler
|
|
99
|
+
↓
|
|
100
|
+
Executes: getUserName()
|
|
101
|
+
↓
|
|
102
|
+
Returns: "John Doe"
|
|
103
|
+
↓
|
|
104
|
+
Serializes result to JSON
|
|
105
|
+
↓
|
|
106
|
+
WebView bridge sends back:
|
|
107
|
+
{ id: 1, result: "John Doe" }
|
|
108
|
+
↓
|
|
109
|
+
TypeScript:
|
|
110
|
+
Promise resolves with "John Doe"
|
|
111
|
+
↓
|
|
112
|
+
const name = "John Doe" ✓
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
Backend → Frontend (Event Emission)
|
|
116
|
+
────────────────────────────────────
|
|
117
|
+
|
|
118
|
+
C++:
|
|
119
|
+
plusui::bindings::emitToFrontend("onDataUpdated", {
|
|
120
|
+
{"count", 42},
|
|
121
|
+
{"status", "active"}
|
|
122
|
+
})
|
|
123
|
+
↓
|
|
124
|
+
Serializes JSON data
|
|
125
|
+
↓
|
|
126
|
+
WebView dispatches CustomEvent:
|
|
127
|
+
new CustomEvent("plusui:binding:myapp.onDataUpdated", {
|
|
128
|
+
detail: { count: 42, status: "active" }
|
|
129
|
+
})
|
|
130
|
+
↓
|
|
131
|
+
TypeScript:
|
|
132
|
+
window.addEventListener receives event
|
|
133
|
+
↓
|
|
134
|
+
Generated binding routes to handlers:
|
|
135
|
+
plusui.myapp.onDataUpdated((data) => { ... })
|
|
136
|
+
↓
|
|
137
|
+
Handler executes with typed data:
|
|
138
|
+
data.count === 42
|
|
139
|
+
data.status === "active" ✓
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
143
|
+
│ TYPE SYSTEM │
|
|
144
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
145
|
+
|
|
146
|
+
PLUSUI_BIND(methodName, returnType, ...paramTypes)
|
|
147
|
+
│ │ │
|
|
148
|
+
│ │ └─→ Parameter types (0-N)
|
|
149
|
+
│ └──────────────→ Return type
|
|
150
|
+
└──────────────────────────→ Method/Event name
|
|
151
|
+
|
|
152
|
+
Auto-Detection Rules:
|
|
153
|
+
• Name starts with "on" + returnType is void = EVENT
|
|
154
|
+
• Otherwise = METHOD
|
|
155
|
+
|
|
156
|
+
Type Mapping Table:
|
|
157
|
+
┌──────────────────┬─────────────────┬─────────────────┐
|
|
158
|
+
│ C++ Type │ TS Type │ Example │
|
|
159
|
+
├──────────────────┼─────────────────┼─────────────────┤
|
|
160
|
+
│ void │ void │ (no return) │
|
|
161
|
+
│ bool │ boolean │ true, false │
|
|
162
|
+
│ int, float │ number │ 42, 3.14 │
|
|
163
|
+
│ string │ string │ "hello" │
|
|
164
|
+
│ json │ any │ {}, [] │
|
|
165
|
+
└──────────────────┴─────────────────┴─────────────────┘
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
169
|
+
│ BINDING CATEGORIES │
|
|
170
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
171
|
+
|
|
172
|
+
NativeBindings (Core Framework)
|
|
173
|
+
────────────────────────────────
|
|
174
|
+
Auto-detected from imports:
|
|
175
|
+
import { window, app, display } from 'plusui-native-core';
|
|
176
|
+
|
|
177
|
+
Features:
|
|
178
|
+
• Window - minimize, maximize, show, hide, setTitle, etc.
|
|
179
|
+
• App - quit, ready, getVersion, etc.
|
|
180
|
+
• Display - getAll, getPrimary, etc.
|
|
181
|
+
• Clipboard - readText, writeText, etc.
|
|
182
|
+
• Keyboard - registerShortcut, etc.
|
|
183
|
+
• Menu - create, show, etc.
|
|
184
|
+
• Tray - create, setIcon, setTooltip, etc.
|
|
185
|
+
• Browser - open, etc.
|
|
186
|
+
|
|
187
|
+
Location: node_modules/plusui-native-core/Core/Features/
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
CustomBindings (Your App Logic)
|
|
191
|
+
────────────────────────────────
|
|
192
|
+
Defined by you with PLUSUI_BIND:
|
|
193
|
+
|
|
194
|
+
Examples:
|
|
195
|
+
• Database operations
|
|
196
|
+
• Authentication/authorization
|
|
197
|
+
• File system operations
|
|
198
|
+
• Network requests
|
|
199
|
+
• Plugin systems
|
|
200
|
+
• Custom business logic
|
|
201
|
+
|
|
202
|
+
Location: Your project src/ files
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
206
|
+
│ GENERATED FILE STRUCTURE │
|
|
207
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
208
|
+
|
|
209
|
+
src/Bindings/
|
|
210
|
+
├── bindings.gen.ts # ← MAIN IMPORT
|
|
211
|
+
│ export const plusui = {
|
|
212
|
+
│ window: WindowBindings,
|
|
213
|
+
│ app: AppBindings,
|
|
214
|
+
│ myFeature: MyFeatureBindings,
|
|
215
|
+
│ ...
|
|
216
|
+
│ }
|
|
217
|
+
│
|
|
218
|
+
├── bindings.gen.hpp # C++ metadata
|
|
219
|
+
├── bindings.report.json # Generation report
|
|
220
|
+
│
|
|
221
|
+
├── NativeBindings/
|
|
222
|
+
│ ├── CPP_IO/
|
|
223
|
+
│ │ ├── core.bindings.gen.hpp # Core registration
|
|
224
|
+
│ │ └── core.bindings.gen.cpp # Implementation stub
|
|
225
|
+
│ └── WEB_IO/
|
|
226
|
+
│ └── core.bindings.gen.ts # Core TS classes
|
|
227
|
+
│
|
|
228
|
+
└── CustomBindings/
|
|
229
|
+
├── CPP_IO/
|
|
230
|
+
│ ├── custom.bindings.gen.hpp # Custom registration
|
|
231
|
+
│ └── custom.bindings.gen.cpp # Implementation stub
|
|
232
|
+
└── WEB_IO/
|
|
233
|
+
└── custom.bindings.gen.ts # Custom TS classes
|
|
234
|
+
|
|
235
|
+
include/Bindings/ # Mirrored C++ headers
|
|
236
|
+
├── bindings.gen.hpp
|
|
237
|
+
├── NativeBindings/...
|
|
238
|
+
└── CustomBindings/...
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
242
|
+
│ BEST PRACTICES │
|
|
243
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
244
|
+
|
|
245
|
+
1. ✅ Use PLUSUI_BIND for everything
|
|
246
|
+
❌ Don't mix with manual bindings
|
|
247
|
+
|
|
248
|
+
2. ✅ Events start with "on" prefix
|
|
249
|
+
✓ onDataChanged, onError, onProgress
|
|
250
|
+
✗ dataChanged, error, progress
|
|
251
|
+
|
|
252
|
+
3. ✅ Group related bindings in files
|
|
253
|
+
src/features/
|
|
254
|
+
├── database.hpp (DB bindings)
|
|
255
|
+
├── auth.hpp (Auth bindings)
|
|
256
|
+
└── files.hpp (File bindings)
|
|
257
|
+
|
|
258
|
+
4. ✅ Use json for complex data
|
|
259
|
+
PLUSUI_BIND(getUser, json, int)
|
|
260
|
+
❌ Not: (string, string, int, bool, ...)
|
|
261
|
+
|
|
262
|
+
5. ✅ Run generate after changes
|
|
263
|
+
$ plusui generate
|
|
264
|
+
|
|
265
|
+
6. ✅ Clean up event listeners
|
|
266
|
+
const unsub = plusui.feature.onEvent(...);
|
|
267
|
+
return () => unsub();
|
|
268
|
+
|
|
269
|
+
7. ✅ Handle errors gracefully
|
|
270
|
+
try {
|
|
271
|
+
await plusui.feature.method();
|
|
272
|
+
} catch (error) {
|
|
273
|
+
// Handle error
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
278
|
+
│ COMPARISON │
|
|
279
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
280
|
+
|
|
281
|
+
Old System (❌ Deprecated)
|
|
282
|
+
──────────────────────────
|
|
283
|
+
• Multiple macros: PLUSUI_METHOD, PLUSUI_EVENT, PLUSUI_SERVICE
|
|
284
|
+
• Confusing overlap between Events and Bindings docs
|
|
285
|
+
• Manual type mapping
|
|
286
|
+
• Inconsistent naming
|
|
287
|
+
|
|
288
|
+
New System (✅ Recommended)
|
|
289
|
+
───────────────────────────
|
|
290
|
+
• Single macro: PLUSUI_BIND
|
|
291
|
+
• Clear distinction: methods vs events (naming convention)
|
|
292
|
+
• Auto-generated types
|
|
293
|
+
• Simple, unified system
|
|
294
|
+
• One import: import { plusui } from './bindings.gen'
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
298
|
+
│ QUICK REFERENCE │
|
|
299
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
300
|
+
|
|
301
|
+
Define Binding:
|
|
302
|
+
PLUSUI_BIND(name, returnType, ...paramTypes)
|
|
303
|
+
|
|
304
|
+
Methods (Frontend → Backend):
|
|
305
|
+
PLUSUI_BIND(getUserData, json, int)
|
|
306
|
+
|
|
307
|
+
Events (Backend → Frontend):
|
|
308
|
+
PLUSUI_BIND(onUserLoggedIn, void, json)
|
|
309
|
+
|
|
310
|
+
Generate:
|
|
311
|
+
$ plusui generate
|
|
312
|
+
|
|
313
|
+
Use in TypeScript:
|
|
314
|
+
import { plusui } from './bindings.gen';
|
|
315
|
+
|
|
316
|
+
// Methods
|
|
317
|
+
await plusui.feature.method(args);
|
|
318
|
+
|
|
319
|
+
// Events
|
|
320
|
+
const unsub = plusui.feature.onEvent((data) => { });
|
|
321
|
+
|
|
322
|
+
Emit from C++:
|
|
323
|
+
plusui::bindings::emitToFrontend("onEvent", jsonData);
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
═══════════════════════════════════════════════════════════════════════
|
|
327
|
+
Simple. Type-Safe. Bidirectional. 🚀
|
|
328
|
+
═══════════════════════════════════════════════════════════════════════
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#include <plusui/bindings.hpp>
|
|
2
|
+
#include <map>
|
|
3
|
+
#include <string>
|
|
4
|
+
|
|
5
|
+
namespace plusui {
|
|
6
|
+
namespace bindings {
|
|
7
|
+
|
|
8
|
+
// Runtime method registry (advanced use)
|
|
9
|
+
static std::map<std::string, InvokeHandler> runtime_methods;
|
|
10
|
+
|
|
11
|
+
// Runtime event registry (advanced use)
|
|
12
|
+
static std::map<std::string, EventHandler> runtime_events;
|
|
13
|
+
|
|
14
|
+
void registerMethod(const std::string& name, InvokeHandler handler) {
|
|
15
|
+
runtime_methods[name] = handler;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
void registerEvent(const std::string& name, EventHandler handler) {
|
|
19
|
+
runtime_events[name] = handler;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void emitToFrontend(const std::string& name, const json& data) {
|
|
23
|
+
// Emit event to frontend via webview
|
|
24
|
+
// Implementation depends on webview instance
|
|
25
|
+
// This will be wired up by the generated binding code
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
json invokeFromFrontend(const std::string& name, const json& params) {
|
|
29
|
+
auto it = runtime_methods.find(name);
|
|
30
|
+
if (it != runtime_methods.end()) {
|
|
31
|
+
return it->second(params);
|
|
32
|
+
}
|
|
33
|
+
return json{"error", "Method not found: " + name};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
std::vector<std::string> getRegisteredMethods() {
|
|
37
|
+
std::vector<std::string> result;
|
|
38
|
+
for (const auto& pair : runtime_methods) {
|
|
39
|
+
result.push_back(pair.first);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
std::vector<std::string> getRegisteredEvents() {
|
|
45
|
+
std::vector<std::string> result;
|
|
46
|
+
for (const auto& pair : runtime_events) {
|
|
47
|
+
result.push_back(pair.first);
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
} // namespace bindings
|
|
53
|
+
} // namespace plusui
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CustomBindings - Runtime Registration
|
|
3
|
+
*
|
|
4
|
+
* This file provides runtime binding registration for advanced use cases.
|
|
5
|
+
* Most users should use PLUSUI_BIND macro for compile-time bindings.
|
|
6
|
+
*
|
|
7
|
+
* Use this for:
|
|
8
|
+
* - Dynamic runtime method registration
|
|
9
|
+
* - Plugin systems
|
|
10
|
+
* - Hot-reloading scenarios
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export type BindingHandler = (params: unknown[]) => Promise<unknown> | unknown;
|
|
14
|
+
export type EventHandler = (data: unknown) => void;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Register a method at runtime (advanced)
|
|
18
|
+
*/
|
|
19
|
+
export function registerMethod(name: string, handler: BindingHandler): void {
|
|
20
|
+
const w = typeof window !== 'undefined' ? window as any : globalThis as any;
|
|
21
|
+
if (!w.__plusui_runtime_methods__) {
|
|
22
|
+
w.__plusui_runtime_methods__ = new Map<string, BindingHandler>();
|
|
23
|
+
}
|
|
24
|
+
w.__plusui_runtime_methods__.set(name, handler);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Register an event listener at runtime (advanced)
|
|
29
|
+
*/
|
|
30
|
+
export function registerEvent(name: string, handler: EventHandler): () => void {
|
|
31
|
+
const eventName = `plusui:binding:${name}`;
|
|
32
|
+
const listener = (e: Event) => handler((e as CustomEvent).detail);
|
|
33
|
+
window.addEventListener(eventName, listener);
|
|
34
|
+
return () => window.removeEventListener(eventName, listener);
|
|
35
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Using the Unified PLUSUI_BIND System
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to create custom bindings
|
|
5
|
+
* for a simple task management app.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
#include <plusui/bindings.hpp>
|
|
10
|
+
#include <string>
|
|
11
|
+
#include <vector>
|
|
12
|
+
|
|
13
|
+
namespace taskapp {
|
|
14
|
+
|
|
15
|
+
using json = nlohmann::json;
|
|
16
|
+
|
|
17
|
+
//========================================
|
|
18
|
+
// Frontend → Backend Methods
|
|
19
|
+
//========================================
|
|
20
|
+
|
|
21
|
+
// Get all tasks
|
|
22
|
+
PLUSUI_BIND(getAllTasks, json, void)
|
|
23
|
+
|
|
24
|
+
// Add a new task
|
|
25
|
+
PLUSUI_BIND(addTask, int, string, string)
|
|
26
|
+
|
|
27
|
+
// Complete a task
|
|
28
|
+
PLUSUI_BIND(completeTask, bool, int)
|
|
29
|
+
|
|
30
|
+
// Delete a task
|
|
31
|
+
PLUSUI_BIND(deleteTask, bool, int)
|
|
32
|
+
|
|
33
|
+
// Get task by ID
|
|
34
|
+
PLUSUI_BIND(getTask, json, int)
|
|
35
|
+
|
|
36
|
+
//========================================
|
|
37
|
+
// Backend → Frontend Events
|
|
38
|
+
// (Names starting with "on")
|
|
39
|
+
//========================================
|
|
40
|
+
|
|
41
|
+
// Fired when a task is added
|
|
42
|
+
PLUSUI_BIND(onTaskAdded, void, json)
|
|
43
|
+
|
|
44
|
+
// Fired when a task is completed
|
|
45
|
+
PLUSUI_BIND(onTaskCompleted, void, int)
|
|
46
|
+
|
|
47
|
+
// Fired when a task is deleted
|
|
48
|
+
PLUSUI_BIND(onTaskDeleted, void, int)
|
|
49
|
+
|
|
50
|
+
// Fired when tasks are reordered
|
|
51
|
+
PLUSUI_BIND(onTasksReordered, void, json)
|
|
52
|
+
|
|
53
|
+
//========================================
|
|
54
|
+
// Implementation (would be in .cpp file)
|
|
55
|
+
//========================================
|
|
56
|
+
|
|
57
|
+
struct Task {
|
|
58
|
+
int id;
|
|
59
|
+
std::string title;
|
|
60
|
+
std::string description;
|
|
61
|
+
bool completed;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
static std::vector<Task> tasks;
|
|
65
|
+
static int nextId = 1;
|
|
66
|
+
|
|
67
|
+
// Methods
|
|
68
|
+
json getAllTasks() {
|
|
69
|
+
json result = json::array();
|
|
70
|
+
for (const auto& task : tasks) {
|
|
71
|
+
result.push_back({
|
|
72
|
+
{"id", task.id},
|
|
73
|
+
{"title", task.title},
|
|
74
|
+
{"description", task.description},
|
|
75
|
+
{"completed", task.completed}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
int addTask(const std::string& title, const std::string& description) {
|
|
82
|
+
Task task = {
|
|
83
|
+
.id = nextId++,
|
|
84
|
+
.title = title,
|
|
85
|
+
.description = description,
|
|
86
|
+
.completed = false
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
tasks.push_back(task);
|
|
90
|
+
|
|
91
|
+
// Emit event to frontend
|
|
92
|
+
plusui::bindings::emitToFrontend("onTaskAdded", {
|
|
93
|
+
{"id", task.id},
|
|
94
|
+
{"title", task.title},
|
|
95
|
+
{"description", task.description},
|
|
96
|
+
{"completed", task.completed}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return task.id;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
bool completeTask(int id) {
|
|
103
|
+
for (auto& task : tasks) {
|
|
104
|
+
if (task.id == id) {
|
|
105
|
+
task.completed = true;
|
|
106
|
+
|
|
107
|
+
// Emit event
|
|
108
|
+
plusui::bindings::emitToFrontend("onTaskCompleted", id);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
bool deleteTask(int id) {
|
|
116
|
+
auto it = std::find_if(tasks.begin(), tasks.end(),
|
|
117
|
+
[id](const Task& t) { return t.id == id; });
|
|
118
|
+
|
|
119
|
+
if (it != tasks.end()) {
|
|
120
|
+
tasks.erase(it);
|
|
121
|
+
|
|
122
|
+
// Emit event
|
|
123
|
+
plusui::bindings::emitToFrontend("onTaskDeleted", id);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
json getTask(int id) {
|
|
130
|
+
for (const auto& task : tasks) {
|
|
131
|
+
if (task.id == id) {
|
|
132
|
+
return {
|
|
133
|
+
{"id", task.id},
|
|
134
|
+
{"title", task.title},
|
|
135
|
+
{"description", task.description},
|
|
136
|
+
{"completed", task.completed}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return nullptr;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
} // namespace taskapp
|