copyhub-cli 1.0.6 → 1.0.8
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/.env.example +2 -1
- package/README.md +188 -136
- package/package.json +1 -1
- package/src/oauth.js +14 -12
- package/ui/main.mjs +7 -6
package/.env.example
CHANGED
|
@@ -16,7 +16,8 @@ COPYHUB_GOOGLE_CLIENT_ID=
|
|
|
16
16
|
COPYHUB_GOOGLE_CLIENT_SECRET=
|
|
17
17
|
COPYHUB_OAUTH_REDIRECT_PORT=19999
|
|
18
18
|
|
|
19
|
-
# Overlay accelerator (optional):
|
|
19
|
+
# Overlay accelerator (optional): overrides config. Default app-wide is Control+Shift+H (⌃/Ctrl + Shift + H).
|
|
20
|
+
# Example Mac ⌘ shortcut: COPYHUB_OVERLAY_ACCELERATOR=CommandOrControl+Shift+H
|
|
20
21
|
COPYHUB_OVERLAY_ACCELERATOR=
|
|
21
22
|
|
|
22
23
|
# Set to 1 to NOT show the window when overlay starts (open via shortcut / tray only).
|
package/README.md
CHANGED
|
@@ -1,230 +1,282 @@
|
|
|
1
1
|
# CopyHub
|
|
2
2
|
|
|
3
|
-
CopyHub
|
|
3
|
+
CopyHub theo dõi **clipboard**, lưu **lịch sử cục bộ** (`~/.copyhub/history.jsonl`), tùy chọn đồng bộ lên **Google Sheets** (một tab mỗi ngày), và mở **overlay Electron** để xem và chọn bản copy gần đây.
|
|
4
|
+
English summary: watches clipboard, local JSONL history, optional daily Google Sheets tabs, floating history overlay.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Chạy trên **Windows**, **macOS**, và **Linux**.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
---
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
- A **Google Cloud** project with:
|
|
11
|
-
- **Google Sheets API** enabled for the *same* project as your OAuth client
|
|
12
|
-
- **OAuth 2.0 Client** (Desktop app type works well for localhost redirect)
|
|
10
|
+
## Mục lục / Table of contents
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
Các mục `##` bên dưới theo thứ tự: **Tính năng** · **Yêu cầu** · **Cài đặt** · **File `.env`** · **Google Cloud & OAuth** · **OAuth config vs env** · **Chạy lần đầu** · **Lệnh CLI** · **Biến môi trường** · **Thư mục dữ liệu** · **Google Sheets** · **Overlay** · **Clipboard & lịch sử** · **Nâng cấp** · **Xử lý sự cố** · **Bảo mật** · **Giấy phép**.
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
---
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
## Tính năng / Features
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
- Theo dõi clipboard theo chu kỳ (có thể chỉnh `COPYHUB_POLL_MS`).
|
|
19
|
+
- Không lưu hai lần liên tiếp **cùng một nội dung** vào `history.jsonl` / Sheet.
|
|
20
|
+
- Ghi Sheet theo tab **`COPYHUB-YYYY-MM-DD`** (timezone máy).
|
|
21
|
+
- Overlay: phân trang lịch sử, đồng bộ Sheet theo từng bước (không tải hết một lúc), gợi ý khi đang load Sheet.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Yêu cầu / Requirements
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
- **Node.js** ≥ 18
|
|
28
|
+
- Một **Google Cloud project** có:
|
|
29
|
+
- **Google Sheets API** bật **trên cùng project** với OAuth client
|
|
30
|
+
- OAuth client kiểu **Web application** và redirect URI đúng (xem dưới)
|
|
25
31
|
|
|
26
|
-
|
|
32
|
+
---
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
## Cài đặt / Installation
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
### Cài global (npm)
|
|
31
37
|
|
|
32
38
|
```bash
|
|
33
|
-
npm install
|
|
39
|
+
npm install -g copyhub-cli
|
|
34
40
|
```
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
Đảm bảo `node` và `copyhub` có trong `PATH`. Linux/macOS có thể cần cấu hình prefix npm cho user — xem [npm global installation](https://docs.npmjs.com/cli/v10/commands/npm-install#global-installation).
|
|
43
|
+
|
|
44
|
+
### Từ mã nguồn (repo)
|
|
37
45
|
|
|
38
46
|
```bash
|
|
47
|
+
npm install
|
|
39
48
|
npm link
|
|
40
49
|
```
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
Hoặc không link:
|
|
43
52
|
|
|
44
53
|
```bash
|
|
45
54
|
node src/cli.js <command>
|
|
46
55
|
```
|
|
47
56
|
|
|
48
|
-
|
|
57
|
+
---
|
|
49
58
|
|
|
50
|
-
|
|
59
|
+
## File `.env` và thứ tự đọc / Environment files
|
|
51
60
|
|
|
52
|
-
**
|
|
61
|
+
CLI và Electron overlay gọi `loadCopyhubEnv()`: đọc lần lượt các file `.env`, parse rồi **gộp một object** — **file sau ghi đè key trùng** với file trước. Sau đó mỗi key chỉ được đưa vào `process.env` nếu biến đó **chưa tồn tại** trong môi trường tiến trình (shell đã `export` trước khi chạy Node thì luôn thắng).
|
|
53
62
|
|
|
54
|
-
|
|
55
|
-
copyhub stop
|
|
56
|
-
```
|
|
63
|
+
Thứ tự file:
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
1. `<package>/.env` (thư mục cài package / repo khi dev)
|
|
66
|
+
2. `~/.copyhub/.env`
|
|
67
|
+
3. `./.env` của **thư mục làm việc hiện tại** (`cwd`)
|
|
59
68
|
|
|
60
|
-
|
|
69
|
+
Nhờ đó `npm install -g` vẫn đọc được biến khi bạn đặt `~/.copyhub/.env`, không phụ thuộc cwd.
|
|
61
70
|
|
|
62
|
-
|
|
71
|
+
Tham khảo mẫu: `.env.example`.
|
|
63
72
|
|
|
64
|
-
|
|
65
|
-
npm view copyhub-cli version
|
|
66
|
-
```
|
|
73
|
+
---
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
## Google Cloud & OAuth
|
|
69
76
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
1. Bật **[Google Sheets API](https://console.cloud.google.com/apis/library/sheets.googleapis.com)** cho project.
|
|
78
|
+
2. **Credentials** → **Create credentials** → **OAuth client ID** → kiểu **Web application**.
|
|
79
|
+
3. **Authorized redirect URIs** — thêm **chính xác** (CopyHub dùng `127.0.0.1`, không dùng `localhost` trong redirect mặc định):
|
|
73
80
|
|
|
74
|
-
|
|
81
|
+
```text
|
|
82
|
+
http://127.0.0.1:19999/oauth2callback
|
|
83
|
+
```
|
|
75
84
|
|
|
76
|
-
|
|
77
|
-
npm update -g copyhub-cli
|
|
78
|
-
```
|
|
85
|
+
Nếu đổi port (`COPYHUB_OAUTH_REDIRECT_PORT` hoặc `redirectPort` trong config), URI trong Console phải khớp port đó.
|
|
79
86
|
|
|
80
|
-
|
|
87
|
+
4. **Không** trộn Client ID trong env với Secret trong file (CopyHub đã chặn trộn nửa cặp). Ưu tiên credentials — xem mục sau.
|
|
81
88
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
### Cách đưa Client ID / Secret vào CopyHub
|
|
90
|
+
|
|
91
|
+
| Cách | Ghi chú |
|
|
92
|
+
|------|---------|
|
|
93
|
+
| **`copyhub login`** | Khuyến nghị lần đầu: wizard localhost nhập ID/Secret → lưu `config.json` → Google đăng nhập → trang nhập Spreadsheet ID / phím tắt. |
|
|
94
|
+
| **`copyhub config --client-id … --client-secret …`** | Ghi thẳng `config.json`. |
|
|
95
|
+
| **`.env`** hoặc shell | Chỉ dùng khi **chưa** có đủ cặp trong `config.json`, hoặc bạn cố ý chỉ dùng env (không ghi OAuth vào config). |
|
|
85
96
|
|
|
86
|
-
|
|
97
|
+
Trên wizard (Mac/Safari): nên **Download JSON** từ Console và paste `client_id` / `client_secret`; xóa sạch ô trước khi dán để tránh Keychain điền nhầm secret cũ.
|
|
87
98
|
|
|
88
|
-
|
|
99
|
+
---
|
|
89
100
|
|
|
90
|
-
|
|
101
|
+
## OAuth: config vs env (quan trọng)
|
|
102
|
+
|
|
103
|
+
- Nếu **`~/.copyhub/config.json` có đủ** `clientId` **và** `clientSecret` → CopyHub **luôn dùng cặp trong file** cho OAuth; **`COPYHUB_GOOGLE_*` trong env/.env bị bỏ qua** cho hai field đó.
|
|
104
|
+
- Nếu file **không** có đủ cặp → dùng **`COPYHUB_GOOGLE_CLIENT_ID`** + **`COPYHUB_GOOGLE_CLIENT_SECRET`** từ env (đã merge từ `.env`).
|
|
105
|
+
- Không bao giờ ghép ID env với Secret file (hoặc ngược lại).
|
|
106
|
+
|
|
107
|
+
Giá trị ID/Secret được **sanitize** khi đọc/ghi (BOM, CRLF, NBSP, ký tự zero-width, ngoặc dư thừa quanh chuỗi).
|
|
108
|
+
|
|
109
|
+
Kiểm tra nguồn đang dùng:
|
|
91
110
|
|
|
92
111
|
```bash
|
|
93
|
-
copyhub
|
|
94
|
-
git pull
|
|
95
|
-
npm install
|
|
112
|
+
copyhub status
|
|
96
113
|
```
|
|
97
114
|
|
|
98
|
-
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Chạy lần đầu / First run
|
|
99
118
|
|
|
100
119
|
```bash
|
|
101
|
-
|
|
120
|
+
copyhub login
|
|
102
121
|
```
|
|
103
122
|
|
|
104
|
-
|
|
123
|
+
1. Nếu chưa có OAuth trong config/env đủ cặp → trình duyệt mở **`http://127.0.0.1:<port>/credentials`** để nhập Client ID / Secret.
|
|
124
|
+
2. Sau đó đăng nhập Google; callback **`/oauth2callback`**.
|
|
125
|
+
3. Trang setup: **Spreadsheet ID** (từ URL `…/d/<ID>/edit`), **platform**, **phím tắt overlay** (tuỳ chọn).
|
|
126
|
+
|
|
127
|
+
Chạy daemon (clipboard + Sheet + overlay mặc định):
|
|
105
128
|
|
|
106
129
|
```bash
|
|
107
130
|
copyhub start
|
|
108
131
|
```
|
|
109
132
|
|
|
110
|
-
|
|
133
|
+
Terminal có thể đóng; tiến trình chạy nền. Xem `copyhub list`, dừng `copyhub stop`.
|
|
111
134
|
|
|
112
|
-
|
|
113
|
-
2. Create **OAuth 2.0 credentials** and add this **Authorized redirect URI** (adjust the port if you change it):
|
|
135
|
+
Chạy gắn terminal (Ctrl+C tắt hết):
|
|
114
136
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
137
|
+
```bash
|
|
138
|
+
copyhub start --foreground
|
|
139
|
+
```
|
|
118
140
|
|
|
119
|
-
|
|
141
|
+
---
|
|
120
142
|
|
|
121
|
-
|
|
143
|
+
## Lệnh CLI / CLI commands
|
|
122
144
|
|
|
123
|
-
|
|
145
|
+
| Lệnh | Mô tả |
|
|
146
|
+
|------|--------|
|
|
147
|
+
| `copyhub config --client-id ID --client-secret SEC [--redirect-port P] [--sheet-id ID]` | Ghi OAuth (và tuỳ chọn Sheet ID, port) vào `config.json`. |
|
|
148
|
+
| `copyhub login` | Luồng OAuth + setup trình duyệt. |
|
|
149
|
+
| `copyhub logout` | Xóa `tokens.json` (chưa xóa config). |
|
|
150
|
+
| `copyhub status` | OAuth, Sheet, token, overlay, daemon. |
|
|
151
|
+
| `copyhub start [--no-sheet] [--no-overlay] [--foreground]` | Mặc định **nền**; một instance. |
|
|
152
|
+
| `copyhub list` / `copyhub ls` | PID daemon (nếu có). |
|
|
153
|
+
| `copyhub stop` | Dừng daemon và overlay con. |
|
|
154
|
+
| `copyhub overlay` | Chỉ cửa sổ Electron (không clipboard daemon). |
|
|
155
|
+
| `copyhub reset --yes` | **Xóa toàn bộ** `~/.copyhub` (config, token, history, run state). Dữ liệu `.env` ngoài thư mục không đụng. |
|
|
156
|
+
| `copyhub commands` / `copyhub cmds` | Liệt kê lệnh nhanh. |
|
|
157
|
+
| `copyhub --help` | Trợ giúp Commander. |
|
|
124
158
|
|
|
125
|
-
|
|
159
|
+
---
|
|
126
160
|
|
|
127
|
-
|
|
128
|
-
copyhub config --client-id "<ID>" --client-secret "<SECRET>" [--sheet-id "<SPREADSHEET_ID>"] [--redirect-port 19999]
|
|
129
|
-
```
|
|
161
|
+
## Biến môi trường / Environment variables
|
|
130
162
|
|
|
131
|
-
|
|
163
|
+
| Biến | Ý nghĩa |
|
|
164
|
+
|------|---------|
|
|
165
|
+
| `COPYHUB_GOOGLE_CLIENT_ID` | OAuth Client ID (chỉ hiệu lực khi config **không** có đủ cặp ID+Secret). |
|
|
166
|
+
| `COPYHUB_GOOGLE_CLIENT_SECRET` | OAuth Client Secret (cùng điều kiện trên). |
|
|
167
|
+
| `COPYHUB_OAUTH_REDIRECT_PORT` | Port localhost cho OAuth (mặc định `19999`). Phải khớp redirect URI trong Google Console. |
|
|
168
|
+
| `COPYHUB_OVERLAY_ACCELERATOR` | Phím tắt Electron ([Accelerator](https://www.electronjs.org/docs/latest/api/accelerator)); **ghi đè** giá trị trong config nếu set. |
|
|
169
|
+
| `COPYHUB_START_NO_OVERLAY` | `=1` → `copyhub start` không spawn overlay. |
|
|
170
|
+
| `COPYHUB_OVERLAY_STICKY` | `=1` → overlay không tự ẩn khi blur (chỉ Esc / chọn dòng). |
|
|
171
|
+
| `COPYHUB_OVERLAY_HIDE_ON_START` | `=1` → không show cửa sổ lúc khởi động overlay (mở bằng shortcut/tray). |
|
|
172
|
+
| `COPYHUB_OVERLAY_SKIP_TASKBAR` | `=1` → ẩn khỏi taskbar (Windows/Electron). |
|
|
173
|
+
| `COPYHUB_POLL_MS` | Chu kỳ đọc clipboard (ms). |
|
|
132
174
|
|
|
133
|
-
|
|
175
|
+
Electron được spawn kế thừa `process.env` của daemon/CLI nên các biến trên áp dụng sau khi có trong môi trường tiến trình cha.
|
|
134
176
|
|
|
135
|
-
|
|
136
|
-
copyhub login
|
|
137
|
-
```
|
|
177
|
+
---
|
|
138
178
|
|
|
139
|
-
|
|
140
|
-
- After Google sign-in, another setup page asks for **Spreadsheet ID**, **platform**, and optional **overlay shortcut**.
|
|
179
|
+
## Thư mục dữ liệu / Data directory
|
|
141
180
|
|
|
142
|
-
|
|
181
|
+
Mọi thứ dưới **`~/.copyhub/`** (Windows: **`%USERPROFILE%\.copyhub`**):
|
|
143
182
|
|
|
144
|
-
|
|
183
|
+
| File | Nội dung |
|
|
184
|
+
|------|-----------|
|
|
185
|
+
| `config.json` | OAuth (`clientId`, `clientSecret`, `redirectPort`), `googleSheetId`, `overlayAccelerator`, `overlayPlatform`, … |
|
|
186
|
+
| `tokens.json` | Refresh / access token OAuth |
|
|
187
|
+
| `history.jsonl` | Lịch sử clipboard (JSON Lines) |
|
|
188
|
+
| `run.json` | PID và metadata khi `copyhub start` chạy nền |
|
|
145
189
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Google Sheets
|
|
193
|
+
|
|
194
|
+
- Append dòng khi bật Sheet và đã login token hợp lệ.
|
|
195
|
+
- Tab mới theo **ngày lịch máy**: `COPYHUB-YYYY-MM-DD`.
|
|
196
|
+
- Sheet phải được share cho đúng Google account đã OAuth (hoặc là spreadsheet của chính user đó).
|
|
197
|
+
- Nếu API báo disabled / permission: xem log — README có link Enable API trong một số thông báo lỗi được format sẵn trong code.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Overlay (Electron)
|
|
202
|
+
|
|
203
|
+
- Phím mặc định (**mọi hệ**, kể cả macOS): **`Control+Shift+H`** — phím **⌃ Control** (góc dưới trái trên bàn phím Apple) hoặc **Ctrl** (bàn phím PC), **cùng một vị trí quen thuộc**, không phụ thuộc ⌘ / Win.
|
|
204
|
+
- Muốn dùng **⌘ Command + Shift + H** trên Mac: chỉnh `overlayAccelerator` trong `~/.copyhub/config.json`, đặt `COPYHUB_OVERLAY_ACCELERATOR`, hoặc chọn preset trên trang setup (`CommandOrControl+Shift+H` / `Command+Shift+H`).
|
|
205
|
+
- **macOS**: vẫn có thể cần quyền **Accessibility** (*Privacy & Security*) cho **Terminal** / tiến trình chạy Electron nếu phím global không hoạt động.
|
|
206
|
+
- Overlay có phân trang ~10 mục; Sheet load dần khi cần (không gom hết tab một lần).
|
|
207
|
+
- Click ra ngoài cửa sổ thường đóng overlay (trừ khi `COPYHUB_OVERLAY_STICKY=1`). **Esc** đóng.
|
|
149
208
|
|
|
150
|
-
|
|
209
|
+
---
|
|
151
210
|
|
|
152
|
-
|
|
211
|
+
## Clipboard & lịch sử
|
|
153
212
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
| Run in terminal (Ctrl+C stops everything) | `copyhub start --foreground` |
|
|
157
|
-
| No Google Sheets | `copyhub start --no-sheet` |
|
|
158
|
-
| No Electron overlay | `copyhub start --no-overlay` or `COPYHUB_START_NO_OVERLAY=1` |
|
|
159
|
-
| Override shortcut | `COPYHUB_OVERLAY_ACCELERATOR` in `.env` (overrides saved config) |
|
|
160
|
-
| Overlay stays open when clicking outside | `COPYHUB_OVERLAY_STICKY=1` |
|
|
213
|
+
- Watcher bỏ qua clipboard trùng hash liên tiếp.
|
|
214
|
+
- Trước khi ghi file/Sheet, nếu nội dung **trùng hệt bản mới nhất** trong `history.jsonl` thì **bỏ qua** (tránh copy lại cùng chuỗi sau khi đổi clipboard khác rồi copy lại).
|
|
161
215
|
|
|
162
|
-
|
|
216
|
+
---
|
|
163
217
|
|
|
164
|
-
##
|
|
218
|
+
## Nâng cấp / Updating
|
|
165
219
|
|
|
166
|
-
|
|
220
|
+
Dữ liệu `~/.copyhub` được giữ khi nâng cấp package.
|
|
167
221
|
|
|
168
222
|
```bash
|
|
169
|
-
copyhub config --client-id "<ID>" --client-secret "<SECRET>" [--redirect-port 19999] [--sheet-id "<SPREADSHEET_ID>"]
|
|
170
|
-
copyhub login
|
|
171
|
-
copyhub logout
|
|
172
|
-
copyhub status
|
|
173
|
-
copyhub start [--no-sheet] [--no-overlay] [--foreground]
|
|
174
|
-
copyhub list # alias: copyhub ls
|
|
175
223
|
copyhub stop
|
|
176
|
-
copyhub
|
|
177
|
-
copyhub
|
|
178
|
-
copyhub --help
|
|
224
|
+
npm install -g copyhub-cli@latest
|
|
225
|
+
copyhub start
|
|
179
226
|
```
|
|
180
227
|
|
|
181
|
-
|
|
182
|
-
|---------|----------------|
|
|
183
|
-
| `copyhub config` | Writes OAuth client ID/secret (and optional Sheet ID, redirect port) to `~/.copyhub/config.json`. `--client-id` and `--client-secret` are required. |
|
|
184
|
-
| `copyhub login` | Opens browser: localhost wizard for Client ID/secret if missing, then Google OAuth, then spreadsheet/platform setup. |
|
|
185
|
-
| `copyhub logout` | Deletes saved OAuth tokens (`~/.copyhub/tokens.json`). |
|
|
186
|
-
| `copyhub status` | Prints OAuth config source, sheet target, tokens, overlay settings, and whether the background daemon is running. |
|
|
187
|
-
| `copyhub start` | Starts clipboard watcher + optional Sheets sync + Electron overlay in the **background** (closing the terminal does not stop it). Only one instance at a time. |
|
|
188
|
-
| `copyhub start --foreground` | Same as above but attached to the terminal; **Ctrl+C** stops everything. |
|
|
189
|
-
| `copyhub start --no-sheet` | Local history only; no Google Sheets writes. |
|
|
190
|
-
| `copyhub start --no-overlay` | No Electron window; use env `COPYHUB_START_NO_OVERLAY=1` for the same effect. |
|
|
191
|
-
| `copyhub list` / `copyhub ls` | Shows PID and start time if the daemon from `copyhub start` is running. |
|
|
192
|
-
| `copyhub stop` | Stops the background daemon and its overlay child process. |
|
|
193
|
-
| `copyhub overlay` | Runs **only** the Electron overlay (no clipboard daemon). Useful if you run the daemon separately or for debugging. |
|
|
228
|
+
Từ source: `git pull`, `npm install`, rồi `copyhub start` (hoặc `npm link` nếu dev).
|
|
194
229
|
|
|
195
|
-
|
|
230
|
+
---
|
|
196
231
|
|
|
197
|
-
|
|
232
|
+
## Xử lý sự cố / Troubleshooting
|
|
198
233
|
|
|
199
|
-
|
|
200
|
-
|------|----------|
|
|
201
|
-
| `config.json` | OAuth credentials (if not only in `.env`), `googleSheetId`, `overlayAccelerator`, `overlayPlatform` |
|
|
202
|
-
| `tokens.json` | OAuth refresh/access tokens |
|
|
203
|
-
| `history.jsonl` | Local clipboard history (JSON Lines) |
|
|
204
|
-
| `run.json` | Daemon PID and metadata (when using `copyhub start` without `--foreground`) |
|
|
234
|
+
### `invalid_client` hoặc “client secret is invalid” sau khi đăng nhập Google
|
|
205
235
|
|
|
206
|
-
|
|
236
|
+
- Dùng OAuth client **Web application**, redirect đúng `http://127.0.0.1:<port>/oauth2callback`.
|
|
237
|
+
- Reset secret hoặc **Download JSON** client mới; nhập lại qua wizard; trên Mac **xóa ô** trước khi dán.
|
|
238
|
+
- `copyhub status` — xem nguồn Client ID/Secret.
|
|
239
|
+
- Chi tiết thêm: CopyHub có trang lỗi HTML khi đổi `code` token thất bại.
|
|
207
240
|
|
|
208
|
-
|
|
209
|
-
- New tabs are created per **local calendar day**, named: **`COPYHUB-YYYY-MM-DD`**.
|
|
241
|
+
### Port OAuth đã được dùng (`EADDRINUSE`)
|
|
210
242
|
|
|
211
|
-
|
|
243
|
+
Đổi port: `COPYHUB_OAUTH_REDIRECT_PORT` hoặc `copyhub config … --redirect-port P`, và cập nhật redirect URI trong Google Console.
|
|
244
|
+
|
|
245
|
+
### `copyhub start` báo đã chạy
|
|
246
|
+
|
|
247
|
+
Một instance nền: `copyhub list` / `copyhub stop` rồi start lại.
|
|
248
|
+
|
|
249
|
+
### Sheet không ghi / lỗi API
|
|
250
|
+
|
|
251
|
+
- Bật Google Sheets API đúng project.
|
|
252
|
+
- Kiểm tra `copyhub status` (token, Sheet ID).
|
|
253
|
+
- Share spreadsheet cho account đã login.
|
|
254
|
+
|
|
255
|
+
### Overlay không mở / phím không hoạt động
|
|
256
|
+
|
|
257
|
+
- **macOS**: bật **Accessibility** cho Terminal / Node / Electron.
|
|
258
|
+
- Mặc định là **Control+Shift+H** (⌃ hoặc Ctrl + Shift + H), không dùng phím Win.
|
|
259
|
+
- Đảm bảo daemon đang chạy (`copyhub list`) hoặc thử `copyhub overlay`.
|
|
260
|
+
- Tránh trùng phím với app khác (Spotlight, Alfred, …).
|
|
261
|
+
|
|
262
|
+
### Xóa sạch cấu hình và làm lại
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
copyhub stop
|
|
266
|
+
copyhub reset --yes
|
|
267
|
+
```
|
|
212
268
|
|
|
213
|
-
|
|
214
|
-
- **macOS**: you may need to grant **Accessibility** permissions for global shortcuts.
|
|
215
|
-
- Some **`Control+Alt+…`** combinations do not register reliably on Windows; prefer alternatives suggested on the setup page.
|
|
269
|
+
Sau đó xóa hoặc sửa `COPYHUB_GOOGLE_*` trong shell/`~/.copyhub/.env` nếu không muốn dùng env nữa. `.env` **không** bị `reset` xóa.
|
|
216
270
|
|
|
217
|
-
|
|
271
|
+
---
|
|
218
272
|
|
|
219
|
-
|
|
273
|
+
## Bảo mật / Security notes
|
|
220
274
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
3. **Paste cleanly**: Re-open the localhost credential wizard or edit `config.json` so ID and secret have **no extra spaces or line breaks**.
|
|
224
|
-
4. Run **`copyhub status`** and confirm **Client ID/Secret source** matches what you expect.
|
|
275
|
+
- `config.json` và `tokens.json` chứa bí mật OAuth — quyền file thư mục user (`~/.copyhub`).
|
|
276
|
+
- Không commit `.env` hoặc copyhub data vào git công khai.
|
|
225
277
|
|
|
226
|
-
|
|
278
|
+
---
|
|
227
279
|
|
|
228
|
-
## License
|
|
280
|
+
## Giấy phép / License
|
|
229
281
|
|
|
230
|
-
MIT —
|
|
282
|
+
MIT — xem `package.json`.
|
package/package.json
CHANGED
package/src/oauth.js
CHANGED
|
@@ -383,18 +383,20 @@ async function runCredentialBootstrap() {
|
|
|
383
383
|
/** Shortcut presets (Electron Accelerator) per platform — embedded as JSON in the setup page. */
|
|
384
384
|
const PLATFORM_PRESETS = {
|
|
385
385
|
win: [
|
|
386
|
-
{ label: 'Ctrl + Shift + H · recommended', value: '
|
|
387
|
-
{ label: 'Control + Shift + H', value: 'Control+Shift+H' },
|
|
386
|
+
{ label: 'Ctrl + Shift + H · recommended', value: 'Control+Shift+H' },
|
|
388
387
|
{ label: 'Alt + Shift + H', value: 'Alt+Shift+H' },
|
|
389
388
|
],
|
|
390
389
|
mac: [
|
|
391
|
-
{
|
|
392
|
-
|
|
390
|
+
{
|
|
391
|
+
label: '⌃ Control + Shift + H · recommended (Apple & PC keyboards)',
|
|
392
|
+
value: 'Control+Shift+H',
|
|
393
|
+
},
|
|
394
|
+
{ label: '⌘ Command + Shift + H', value: 'CommandOrControl+Shift+H' },
|
|
395
|
+
{ label: 'Command + Shift + H (explicit ⌘)', value: 'Command+Shift+H' },
|
|
393
396
|
{ label: '⌘ + Shift + V', value: 'Command+Shift+V' },
|
|
394
397
|
],
|
|
395
398
|
linux: [
|
|
396
|
-
{ label: 'Ctrl + Shift + H · recommended', value: '
|
|
397
|
-
{ label: 'Control + Shift + H', value: 'Control+Shift+H' },
|
|
399
|
+
{ label: 'Ctrl + Shift + H · recommended', value: 'Control+Shift+H' },
|
|
398
400
|
{ label: 'Alt + Shift + H', value: 'Alt+Shift+H' },
|
|
399
401
|
],
|
|
400
402
|
};
|
|
@@ -632,7 +634,7 @@ function setupPageHtml(setupToken, currentSheetId, currentAccelerator, currentPl
|
|
|
632
634
|
<button type="button" class="platform-btn" data-platform="mac" aria-pressed="false">
|
|
633
635
|
<span class="ico" aria-hidden="true">⌘</span>
|
|
634
636
|
<span class="name">macOS</span>
|
|
635
|
-
<span class="tag"
|
|
637
|
+
<span class="tag">⌃ Control default</span>
|
|
636
638
|
</button>
|
|
637
639
|
<button type="button" class="platform-btn" data-platform="linux" aria-pressed="false">
|
|
638
640
|
<span class="ico" aria-hidden="true">🐧</span>
|
|
@@ -641,10 +643,10 @@ function setupPageHtml(setupToken, currentSheetId, currentAccelerator, currentPl
|
|
|
641
643
|
</button>
|
|
642
644
|
</div>
|
|
643
645
|
|
|
644
|
-
<label class="field-label" for="acc">Accelerator (blank =
|
|
646
|
+
<label class="field-label" for="acc">Accelerator (blank = Control + Shift + H)</label>
|
|
645
647
|
<input id="acc" type="text" name="overlayAccelerator" value="${accVal}" placeholder="Pick a preset below or type your own" autocomplete="off" spellcheck="false" />
|
|
646
648
|
|
|
647
|
-
<p class="hint">On Windows
|
|
649
|
+
<p class="hint">Default everywhere: <code>Control+Shift+H</code> (⌃ or Ctrl + Shift + H — same key on Mac Apple keyboard & PC keyboard). On Windows type <code>Control</code> in config, not <code>Ctrl</code>. Avoid <code>Control+Alt+…</code> (often grabbed by drivers).</p>
|
|
648
650
|
<p class="hint"><code>COPYHUB_OVERLAY_ACCELERATOR</code> in <code>.env</code>, if set, overrides this value.</p>
|
|
649
651
|
|
|
650
652
|
<div id="chipRegion" class="chips" aria-live="polite"></div>
|
|
@@ -670,9 +672,9 @@ function setupPageHtml(setupToken, currentSheetId, currentAccelerator, currentPl
|
|
|
670
672
|
var btns = document.querySelectorAll('.platform-btn');
|
|
671
673
|
|
|
672
674
|
var hints = {
|
|
673
|
-
win: 'Windows:
|
|
674
|
-
mac: 'macOS:
|
|
675
|
-
linux: 'Linux:
|
|
675
|
+
win: 'Windows: default Control+Shift+H.',
|
|
676
|
+
mac: 'macOS: default ⌃ Control+Shift+H (same as Ctrl on a PC keyboard). Use a ⌘ preset only if you prefer Command.',
|
|
677
|
+
linux: 'Linux: default Control+Shift+H; clipboard depends on your desktop.'
|
|
676
678
|
};
|
|
677
679
|
|
|
678
680
|
function setPlatform(p) {
|
package/ui/main.mjs
CHANGED
|
@@ -32,7 +32,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
32
32
|
/** Set to 1 so the window does not hide on blur (only Esc / pick row to copy). */
|
|
33
33
|
const STICKY_NO_BLUR = process.env.COPYHUB_OVERLAY_STICKY === '1';
|
|
34
34
|
|
|
35
|
-
/** Electron Accelerator: use `Control`, not `Ctrl`; `
|
|
35
|
+
/** Electron Accelerator: use `Control`, not `Ctrl`; avoid bare `Ctrl` in strings — Electron expects `Control`. */
|
|
36
36
|
function normalizeAccelerator(raw) {
|
|
37
37
|
if (!raw || typeof raw !== 'string') return '';
|
|
38
38
|
let s = raw.trim();
|
|
@@ -42,7 +42,8 @@ function normalizeAccelerator(raw) {
|
|
|
42
42
|
return s;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
/** Same physical ⌃ / Ctrl key on Mac (Apple & Windows-layout keyboards) and on Win/Linux — one default everywhere. */
|
|
46
|
+
const DEFAULT_ACCEL = 'Control+Shift+H';
|
|
46
47
|
const HIDE_ON_START = process.env.COPYHUB_OVERLAY_HIDE_ON_START === '1';
|
|
47
48
|
|
|
48
49
|
/** Overlay size (slightly larger than earlier ~70% width). */
|
|
@@ -213,7 +214,7 @@ function toggleOverlay() {
|
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
/**
|
|
216
|
-
* Register global shortcut: try .env (normalized) then default
|
|
217
|
+
* Register global shortcut: try .env / saved config (normalized) then default Control+Shift+H.
|
|
217
218
|
* @returns {{ accelerator: string, usedFallback: boolean }}
|
|
218
219
|
*/
|
|
219
220
|
function registerHotkeys() {
|
|
@@ -546,12 +547,12 @@ if (gotLock) {
|
|
|
546
547
|
};
|
|
547
548
|
if (accelerator) {
|
|
548
549
|
console.log('CopyHub overlay — shortcut in use:', accelerator);
|
|
549
|
-
console.log('
|
|
550
|
+
console.log('Default shortcut: Control+Shift+H (⌃ or Ctrl + Shift + H).');
|
|
550
551
|
if (usedFallback) {
|
|
551
552
|
console.warn(
|
|
552
|
-
'COPYHUB_OVERLAY_ACCELERATOR could not be registered. Using default
|
|
553
|
+
'COPYHUB_OVERLAY_ACCELERATOR could not be registered. Using default Control+Shift+H.',
|
|
553
554
|
);
|
|
554
|
-
console.warn('Leave COPYHUB_OVERLAY_ACCELERATOR unset
|
|
555
|
+
console.warn('Leave COPYHUB_OVERLAY_ACCELERATOR unset to use the default Control+Shift+H.');
|
|
555
556
|
}
|
|
556
557
|
} else {
|
|
557
558
|
console.error(
|