mani-calc 1.1.2 → 1.2.1
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/OVERLAY_MODE.md +3 -0
- package/package.json +1 -1
- package/src/core/clipboard-manager.js +14 -0
- package/src/ui/floating-search.js +14 -124
- package/src/ui/overlay.html +53 -22
package/OVERLAY_MODE.md
CHANGED
|
@@ -47,6 +47,9 @@ Control your computer with simple commands:
|
|
|
47
47
|
|
|
48
48
|
| Command | Action |
|
|
49
49
|
|---------|--------|
|
|
50
|
+
| `help` | Show available commands |
|
|
51
|
+
| `theme` | Toggle Light/Dark mode |
|
|
52
|
+
| `quit` | Quit application |
|
|
50
53
|
| `sleep` | Put computer to sleep |
|
|
51
54
|
| `shutdown` | Shutdown computer |
|
|
52
55
|
| `restart` | Restart computer |
|
package/package.json
CHANGED
|
@@ -11,6 +11,14 @@ class ClipboardManager {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
try {
|
|
14
|
+
// Check if running in Electron
|
|
15
|
+
if (process.versions.electron) {
|
|
16
|
+
const { clipboard } = require('electron');
|
|
17
|
+
clipboard.writeText(String(text));
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Fallback to clipboardy for CLI
|
|
14
22
|
await clipboardy.write(String(text));
|
|
15
23
|
return true;
|
|
16
24
|
} catch (error) {
|
|
@@ -21,6 +29,12 @@ class ClipboardManager {
|
|
|
21
29
|
|
|
22
30
|
async read() {
|
|
23
31
|
try {
|
|
32
|
+
// Check if running in Electron
|
|
33
|
+
if (process.versions.electron) {
|
|
34
|
+
const { clipboard } = require('electron');
|
|
35
|
+
return clipboard.readText();
|
|
36
|
+
}
|
|
37
|
+
|
|
24
38
|
return await clipboardy.read();
|
|
25
39
|
} catch (error) {
|
|
26
40
|
console.error('Failed to read from clipboard:', error);
|
|
@@ -67,19 +67,24 @@ class FloatingSearchBox {
|
|
|
67
67
|
setupIPC() {
|
|
68
68
|
// Handle query from renderer
|
|
69
69
|
ipcMain.on('process-query', async (event, query) => {
|
|
70
|
+
console.log('Processing query:', query);
|
|
70
71
|
try {
|
|
71
72
|
// Check for system commands first
|
|
72
73
|
const systemResult = await this.handleSystemCommand(query);
|
|
73
74
|
if (systemResult) {
|
|
75
|
+
console.log('System command executed:', systemResult);
|
|
74
76
|
event.reply('query-result', systemResult);
|
|
75
77
|
setTimeout(() => this.hide(), 1000);
|
|
76
78
|
return;
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
// Process as calculation
|
|
82
|
+
console.log('Calculating...');
|
|
80
83
|
const result = await this.maniCalc.processQuery(query);
|
|
84
|
+
console.log('Calculation result:', result);
|
|
81
85
|
event.reply('query-result', result);
|
|
82
86
|
} catch (error) {
|
|
87
|
+
console.error('Error processing query:', error);
|
|
83
88
|
event.reply('query-result', {
|
|
84
89
|
error: error.message,
|
|
85
90
|
type: 'error'
|
|
@@ -93,133 +98,18 @@ class FloatingSearchBox {
|
|
|
93
98
|
});
|
|
94
99
|
}
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
const cmd = query.toLowerCase().trim();
|
|
98
|
-
const { exec } = require('child_process');
|
|
99
|
-
const { promisify } = require('util');
|
|
100
|
-
const execAsync = promisify(exec);
|
|
101
|
-
|
|
102
|
-
const commands = {
|
|
103
|
-
'sleep': {
|
|
104
|
-
action: async () => {
|
|
105
|
-
await execAsync('rundll32.exe powrprof.dll,SetSuspendState 0,1,0');
|
|
106
|
-
return 'System going to sleep...';
|
|
107
|
-
},
|
|
108
|
-
description: 'Put computer to sleep'
|
|
109
|
-
},
|
|
110
|
-
'shutdown': {
|
|
111
|
-
action: async () => {
|
|
112
|
-
await execAsync('shutdown /s /t 0');
|
|
113
|
-
return 'Shutting down...';
|
|
114
|
-
},
|
|
115
|
-
description: 'Shutdown computer'
|
|
116
|
-
},
|
|
117
|
-
'restart': {
|
|
118
|
-
action: async () => {
|
|
119
|
-
await execAsync('shutdown /r /t 0');
|
|
120
|
-
return 'Restarting...';
|
|
121
|
-
},
|
|
122
|
-
description: 'Restart computer'
|
|
123
|
-
},
|
|
124
|
-
'lock': {
|
|
125
|
-
action: async () => {
|
|
126
|
-
await execAsync('rundll32.exe user32.dll,LockWorkStation');
|
|
127
|
-
return 'Locking computer...';
|
|
128
|
-
},
|
|
129
|
-
description: 'Lock computer'
|
|
130
|
-
},
|
|
131
|
-
'logout': {
|
|
132
|
-
action: async () => {
|
|
133
|
-
await execAsync('shutdown /l');
|
|
134
|
-
return 'Logging out...';
|
|
135
|
-
},
|
|
136
|
-
description: 'Log out current user'
|
|
137
|
-
},
|
|
138
|
-
'empty recycle bin': {
|
|
139
|
-
action: async () => {
|
|
140
|
-
await execAsync('rd /s /q %systemdrive%\\$Recycle.bin');
|
|
141
|
-
return 'Recycle bin emptied';
|
|
142
|
-
},
|
|
143
|
-
description: 'Empty recycle bin'
|
|
144
|
-
},
|
|
145
|
-
'volume up': {
|
|
146
|
-
action: async () => {
|
|
147
|
-
await execAsync('nircmd.exe changesysvolume 2000');
|
|
148
|
-
return 'Volume increased';
|
|
149
|
-
},
|
|
150
|
-
description: 'Increase volume'
|
|
151
|
-
},
|
|
152
|
-
'volume down': {
|
|
153
|
-
action: async () => {
|
|
154
|
-
await execAsync('nircmd.exe changesysvolume -2000');
|
|
155
|
-
return 'Volume decreased';
|
|
156
|
-
},
|
|
157
|
-
description: 'Decrease volume'
|
|
158
|
-
},
|
|
159
|
-
'mute': {
|
|
160
|
-
action: async () => {
|
|
161
|
-
await execAsync('nircmd.exe mutesysvolume 1');
|
|
162
|
-
return 'Volume muted';
|
|
163
|
-
},
|
|
164
|
-
description: 'Mute volume'
|
|
165
|
-
},
|
|
166
|
-
'unmute': {
|
|
167
|
-
action: async () => {
|
|
168
|
-
await execAsync('nircmd.exe mutesysvolume 0');
|
|
169
|
-
return 'Volume unmuted';
|
|
170
|
-
},
|
|
171
|
-
description: 'Unmute volume'
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
if (commands[cmd]) {
|
|
176
|
-
try {
|
|
177
|
-
const message = await commands[cmd].action();
|
|
178
|
-
return {
|
|
179
|
-
result: message,
|
|
180
|
-
type: 'system_command',
|
|
181
|
-
formatted: message
|
|
182
|
-
};
|
|
183
|
-
} catch (error) {
|
|
184
|
-
return {
|
|
185
|
-
error: `Failed to execute: ${error.message}`,
|
|
186
|
-
type: 'error'
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
show() {
|
|
195
|
-
if (this.window) {
|
|
196
|
-
this.window.show();
|
|
197
|
-
this.window.focus();
|
|
198
|
-
this.isVisible = true;
|
|
199
|
-
this.window.webContents.send('focus-input');
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
hide() {
|
|
204
|
-
if (this.window) {
|
|
205
|
-
this.window.hide();
|
|
206
|
-
this.isVisible = false;
|
|
207
|
-
this.window.webContents.send('clear-input');
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
toggle() {
|
|
212
|
-
if (this.isVisible) {
|
|
213
|
-
this.hide();
|
|
214
|
-
} else {
|
|
215
|
-
this.show();
|
|
216
|
-
}
|
|
217
|
-
}
|
|
101
|
+
// ... (rest of methods) ...
|
|
218
102
|
|
|
219
103
|
destroy() {
|
|
220
104
|
if (this.window) {
|
|
221
|
-
|
|
222
|
-
|
|
105
|
+
try {
|
|
106
|
+
globalShortcut.unregister(this.hotkey);
|
|
107
|
+
if (!this.window.isDestroyed()) {
|
|
108
|
+
this.window.close();
|
|
109
|
+
}
|
|
110
|
+
} catch (err) {
|
|
111
|
+
console.error('Error destroying window:', err);
|
|
112
|
+
}
|
|
223
113
|
this.window = null;
|
|
224
114
|
}
|
|
225
115
|
}
|
package/src/ui/overlay.html
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
|
+
|
|
3
4
|
<head>
|
|
4
5
|
<meta charset="UTF-8">
|
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -18,31 +19,58 @@
|
|
|
18
19
|
overflow: hidden;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
:root {
|
|
23
|
+
--bg-color: rgba(255, 255, 255, 0.95);
|
|
24
|
+
--text-color: #333;
|
|
25
|
+
--icon-color: #00D9FF;
|
|
26
|
+
--hint-color: #999;
|
|
27
|
+
--shortcut-bg: rgba(0, 0, 0, 0.02);
|
|
28
|
+
--key-bg: rgba(0, 0, 0, 0.1);
|
|
29
|
+
--border-color: rgba(0, 0, 0, 0.1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
body.dark {
|
|
33
|
+
--bg-color: rgba(30, 30, 30, 0.95);
|
|
34
|
+
--text-color: #eee;
|
|
35
|
+
--icon-color: #00D9FF;
|
|
36
|
+
--hint-color: #666;
|
|
37
|
+
--shortcut-bg: rgba(255, 255, 255, 0.05);
|
|
38
|
+
--key-bg: rgba(255, 255, 255, 0.1);
|
|
39
|
+
--border-color: rgba(255, 255, 255, 0.1);
|
|
40
|
+
}
|
|
41
|
+
|
|
21
42
|
.container {
|
|
22
43
|
width: 600px;
|
|
23
44
|
padding: 10px;
|
|
24
45
|
}
|
|
25
46
|
|
|
26
47
|
.search-box {
|
|
27
|
-
background:
|
|
48
|
+
background: var(--bg-color);
|
|
28
49
|
backdrop-filter: blur(20px);
|
|
29
50
|
border-radius: 12px;
|
|
30
51
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
|
31
52
|
overflow: hidden;
|
|
32
53
|
-webkit-app-region: no-drag;
|
|
54
|
+
transition: background 0.3s ease;
|
|
33
55
|
}
|
|
34
56
|
|
|
35
57
|
.input-container {
|
|
36
58
|
display: flex;
|
|
37
59
|
align-items: center;
|
|
38
60
|
padding: 16px 20px;
|
|
39
|
-
border-bottom: 1px solid
|
|
61
|
+
border-bottom: 1px solid var(--border-color);
|
|
40
62
|
}
|
|
41
63
|
|
|
42
64
|
.icon {
|
|
43
65
|
font-size: 24px;
|
|
44
66
|
margin-right: 12px;
|
|
45
|
-
color:
|
|
67
|
+
color: var(--icon-color);
|
|
68
|
+
-webkit-app-region: drag;
|
|
69
|
+
cursor: grab;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.icon:active {
|
|
73
|
+
cursor: grabbing;
|
|
46
74
|
}
|
|
47
75
|
|
|
48
76
|
#search-input {
|
|
@@ -51,11 +79,11 @@
|
|
|
51
79
|
outline: none;
|
|
52
80
|
font-size: 18px;
|
|
53
81
|
background: transparent;
|
|
54
|
-
color:
|
|
82
|
+
color: var(--text-color);
|
|
55
83
|
}
|
|
56
84
|
|
|
57
85
|
#search-input::placeholder {
|
|
58
|
-
color:
|
|
86
|
+
color: var(--hint-color);
|
|
59
87
|
}
|
|
60
88
|
|
|
61
89
|
.result-container {
|
|
@@ -74,6 +102,7 @@
|
|
|
74
102
|
opacity: 0;
|
|
75
103
|
transform: translateY(-10px);
|
|
76
104
|
}
|
|
105
|
+
|
|
77
106
|
to {
|
|
78
107
|
opacity: 1;
|
|
79
108
|
transform: translateY(0);
|
|
@@ -82,7 +111,7 @@
|
|
|
82
111
|
|
|
83
112
|
.result-text {
|
|
84
113
|
font-size: 16px;
|
|
85
|
-
color:
|
|
114
|
+
color: var(--icon-color);
|
|
86
115
|
font-weight: 600;
|
|
87
116
|
}
|
|
88
117
|
|
|
@@ -91,7 +120,7 @@
|
|
|
91
120
|
}
|
|
92
121
|
|
|
93
122
|
.result-text.success {
|
|
94
|
-
color:
|
|
123
|
+
color: var(--icon-color);
|
|
95
124
|
}
|
|
96
125
|
|
|
97
126
|
.result-text.system {
|
|
@@ -100,16 +129,16 @@
|
|
|
100
129
|
|
|
101
130
|
.hint {
|
|
102
131
|
font-size: 12px;
|
|
103
|
-
color:
|
|
132
|
+
color: var(--hint-color);
|
|
104
133
|
margin-top: 4px;
|
|
105
134
|
}
|
|
106
135
|
|
|
107
136
|
.shortcuts {
|
|
108
137
|
padding: 8px 20px;
|
|
109
|
-
background:
|
|
138
|
+
background: var(--shortcut-bg);
|
|
110
139
|
display: none;
|
|
111
140
|
font-size: 11px;
|
|
112
|
-
color:
|
|
141
|
+
color: var(--hint-color);
|
|
113
142
|
}
|
|
114
143
|
|
|
115
144
|
.shortcuts.show {
|
|
@@ -122,27 +151,23 @@
|
|
|
122
151
|
}
|
|
123
152
|
|
|
124
153
|
.key {
|
|
125
|
-
background:
|
|
154
|
+
background: var(--key-bg);
|
|
126
155
|
padding: 2px 6px;
|
|
127
156
|
border-radius: 3px;
|
|
128
157
|
font-family: monospace;
|
|
129
158
|
}
|
|
130
159
|
</style>
|
|
131
160
|
</head>
|
|
161
|
+
|
|
132
162
|
<body>
|
|
133
163
|
<div class="container">
|
|
134
164
|
<div class="search-box">
|
|
135
165
|
<div class="input-container">
|
|
136
166
|
<div class="icon">⚡</div>
|
|
137
|
-
<input
|
|
138
|
-
|
|
139
|
-
id="search-input"
|
|
140
|
-
placeholder="Type calculation or command..."
|
|
141
|
-
autocomplete="off"
|
|
142
|
-
spellcheck="false"
|
|
143
|
-
>
|
|
167
|
+
<input type="text" id="search-input" placeholder="Type calculation or command..." autocomplete="off"
|
|
168
|
+
spellcheck="false">
|
|
144
169
|
</div>
|
|
145
|
-
|
|
170
|
+
|
|
146
171
|
<div class="result-container" id="result-container">
|
|
147
172
|
<div class="result-text" id="result-text"></div>
|
|
148
173
|
<div class="hint" id="result-hint"></div>
|
|
@@ -158,7 +183,7 @@
|
|
|
158
183
|
|
|
159
184
|
<script>
|
|
160
185
|
const { ipcRenderer } = require('electron');
|
|
161
|
-
|
|
186
|
+
|
|
162
187
|
const input = document.getElementById('search-input');
|
|
163
188
|
const resultContainer = document.getElementById('result-container');
|
|
164
189
|
const resultText = document.getElementById('result-text');
|
|
@@ -184,7 +209,7 @@
|
|
|
184
209
|
// Handle input
|
|
185
210
|
input.addEventListener('input', (e) => {
|
|
186
211
|
const query = e.target.value.trim();
|
|
187
|
-
|
|
212
|
+
|
|
188
213
|
if (!query) {
|
|
189
214
|
resultContainer.classList.remove('show');
|
|
190
215
|
return;
|
|
@@ -226,6 +251,11 @@
|
|
|
226
251
|
}
|
|
227
252
|
}
|
|
228
253
|
|
|
254
|
+
// Handle theme toggle
|
|
255
|
+
ipcRenderer.on('toggle-theme', () => {
|
|
256
|
+
document.body.classList.toggle('dark');
|
|
257
|
+
});
|
|
258
|
+
|
|
229
259
|
// Handle result from main process
|
|
230
260
|
ipcRenderer.on('query-result', (event, result) => {
|
|
231
261
|
if (result.error) {
|
|
@@ -251,4 +281,5 @@
|
|
|
251
281
|
}, 100);
|
|
252
282
|
</script>
|
|
253
283
|
</body>
|
|
254
|
-
|
|
284
|
+
|
|
285
|
+
</html>
|