floq 0.2.2 → 0.2.3

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/README.ja.md CHANGED
@@ -64,6 +64,15 @@ floq
64
64
  | `?` | ヘルプ |
65
65
  | `q` | 終了 |
66
66
 
67
+ #### 検索
68
+
69
+ | キー | アクション |
70
+ |------|-----------|
71
+ | `/` | 検索モード開始 |
72
+ | `↑/↓` または `Ctrl+j/k` | 検索結果をナビゲート |
73
+ | `Enter` | 選択したタスクのタブに移動して選択 |
74
+ | `Esc` | キャンセル |
75
+
67
76
  #### プロジェクト詳細画面
68
77
 
69
78
  | キー | アクション |
package/README.md CHANGED
@@ -64,6 +64,15 @@ floq
64
64
  | `?` | Help |
65
65
  | `q` | Quit |
66
66
 
67
+ #### Search
68
+
69
+ | Key | Action |
70
+ |-----|--------|
71
+ | `/` | Start search mode |
72
+ | `↑/↓` or `Ctrl+j/k` | Navigate search results |
73
+ | `Enter` | Jump to selected task's tab and select it |
74
+ | `Esc` | Cancel search |
75
+
67
76
  #### Project Detail View
68
77
 
69
78
  | Key | Action |
package/dist/i18n/en.js CHANGED
@@ -198,7 +198,7 @@ export const en = {
198
198
  search: {
199
199
  prefix: '/',
200
200
  placeholder: 'Search tasks...',
201
- help: '(Enter to select, Ctrl+j/k to navigate, Esc to cancel)',
201
+ help: '(Enter to select, ↑/↓ or Ctrl+j/k to navigate, Esc to cancel)',
202
202
  noResults: 'No matching tasks',
203
203
  resultsTitle: 'Search Results',
204
204
  searchTasks: 'Search tasks',
package/dist/i18n/ja.js CHANGED
@@ -198,7 +198,7 @@ export const ja = {
198
198
  search: {
199
199
  prefix: '/',
200
200
  placeholder: 'タスクを検索...',
201
- help: '(Enterで選択, Ctrl+j/kで移動, Escでキャンセル)',
201
+ help: '(Enterで選択, ↑/↓またはCtrl+j/kで移動, Escでキャンセル)',
202
202
  noResults: '該当するタスクがありません',
203
203
  resultsTitle: '検索結果',
204
204
  searchTasks: 'タスク検索',
package/dist/ui/App.js CHANGED
@@ -174,6 +174,18 @@ function AppContent({ onOpenSettings }) {
174
174
  setSearchResults(results);
175
175
  setSearchResultIndex(0);
176
176
  }, [searchTasks]);
177
+ // Navigate to a task from search results
178
+ const navigateToTask = useCallback((task) => {
179
+ const targetTab = task.isProject ? 'projects' : task.status;
180
+ const tabIndex = TABS.indexOf(targetTab);
181
+ const tabTasks = tasks[targetTab];
182
+ const taskIndex = tabTasks.findIndex(t => t.id === task.id);
183
+ if (tabIndex >= 0 && taskIndex >= 0) {
184
+ setCurrentListIndex(tabIndex);
185
+ setSelectedTaskIndex(taskIndex);
186
+ setMode('normal');
187
+ }
188
+ }, [tasks]);
177
189
  const addTask = useCallback(async (title, parentId) => {
178
190
  if (!title.trim())
179
191
  return;
@@ -224,9 +236,7 @@ function AppContent({ onOpenSettings }) {
224
236
  if (mode === 'search') {
225
237
  if (searchResults.length > 0) {
226
238
  const task = searchResults[searchResultIndex];
227
- setSelectedTask(task);
228
- loadTaskComments(task.id);
229
- setMode('task-detail');
239
+ navigateToTask(task);
230
240
  }
231
241
  else {
232
242
  setMode('normal');
@@ -345,12 +355,12 @@ function AppContent({ onOpenSettings }) {
345
355
  setMode('normal');
346
356
  return;
347
357
  }
348
- // Navigate search results with Ctrl+j/k or Ctrl+n/p
349
- if (key.ctrl && (input === 'j' || input === 'n')) {
358
+ // Navigate search results with arrow keys, Ctrl+j/k, or Ctrl+n/p
359
+ if (key.downArrow || (key.ctrl && (input === 'j' || input === 'n'))) {
350
360
  setSearchResultIndex((prev) => prev < searchResults.length - 1 ? prev + 1 : 0);
351
361
  return;
352
362
  }
353
- if (key.ctrl && (input === 'k' || input === 'p')) {
363
+ if (key.upArrow || (key.ctrl && (input === 'k' || input === 'p'))) {
354
364
  setSearchResultIndex((prev) => prev > 0 ? prev - 1 : Math.max(0, searchResults.length - 1));
355
365
  return;
356
366
  }
@@ -140,6 +140,30 @@ export function KanbanBoard({ onSwitchToGtd, onOpenSettings }) {
140
140
  setSearchResults(results);
141
141
  setSearchResultIndex(0);
142
142
  }, [searchTasks]);
143
+ // Navigate to a task from search results
144
+ const navigateToTask = useCallback((task) => {
145
+ // Determine which column the task belongs to based on status
146
+ let targetColumn;
147
+ if (task.status === 'inbox' || task.status === 'someday') {
148
+ targetColumn = 'todo';
149
+ }
150
+ else if (task.status === 'next' || task.status === 'waiting') {
151
+ targetColumn = 'doing';
152
+ }
153
+ else {
154
+ targetColumn = 'done';
155
+ }
156
+ const columnIndex = COLUMNS.indexOf(targetColumn);
157
+ const taskIndex = tasks[targetColumn].findIndex(t => t.id === task.id);
158
+ if (columnIndex >= 0 && taskIndex >= 0) {
159
+ setCurrentColumnIndex(columnIndex);
160
+ setSelectedTaskIndices(prev => ({
161
+ ...prev,
162
+ [targetColumn]: taskIndex,
163
+ }));
164
+ setMode('normal');
165
+ }
166
+ }, [tasks]);
143
167
  const addTask = useCallback(async (title) => {
144
168
  if (!title.trim())
145
169
  return;
@@ -169,9 +193,7 @@ export function KanbanBoard({ onSwitchToGtd, onOpenSettings }) {
169
193
  if (mode === 'search') {
170
194
  if (searchResults.length > 0) {
171
195
  const task = searchResults[searchResultIndex];
172
- setSelectedTask(task);
173
- loadTaskComments(task.id);
174
- setMode('task-detail');
196
+ navigateToTask(task);
175
197
  }
176
198
  else {
177
199
  setMode('normal');
@@ -257,12 +279,12 @@ export function KanbanBoard({ onSwitchToGtd, onOpenSettings }) {
257
279
  setMode('normal');
258
280
  return;
259
281
  }
260
- // Navigate search results with Ctrl+j/k or Ctrl+n/p
261
- if (key.ctrl && (input === 'j' || input === 'n')) {
282
+ // Navigate search results with arrow keys, Ctrl+j/k, or Ctrl+n/p
283
+ if (key.downArrow || (key.ctrl && (input === 'j' || input === 'n'))) {
262
284
  setSearchResultIndex((prev) => prev < searchResults.length - 1 ? prev + 1 : 0);
263
285
  return;
264
286
  }
265
- if (key.ctrl && (input === 'k' || input === 'p')) {
287
+ if (key.upArrow || (key.ctrl && (input === 'k' || input === 'p'))) {
266
288
  setSearchResultIndex((prev) => prev > 0 ? prev - 1 : Math.max(0, searchResults.length - 1));
267
289
  return;
268
290
  }
@@ -12,7 +12,7 @@ export function SearchResults({ results, selectedIndex, query }) {
12
12
  return (_jsxs(Box, { flexDirection: "column", borderStyle: theme.borders.list, borderColor: theme.colors.borderActive, paddingX: 1, paddingY: 1, minHeight: 5, children: [_jsx(Box, { marginBottom: 1, children: _jsxs(Text, { color: theme.colors.secondary, bold: true, children: ["[", search.resultsTitle, "] (", results.length, ")"] }) }), results.length === 0 ? (_jsx(Text, { color: theme.colors.textMuted, italic: true, children: search.noResults })) : (results.slice(0, 10).map((task, index) => {
13
13
  const isSelected = index === selectedIndex;
14
14
  const shortId = task.id.slice(0, 8);
15
- const statusLabel = i18n.status[task.status];
16
- return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.text, bold: isSelected, children: [isSelected ? theme.style.selectedPrefix : theme.style.unselectedPrefix, "[", shortId, "] ", task.title, _jsxs(Text, { color: theme.colors.textMuted, children: [" (", statusLabel, ")"] }), task.waitingFor && (_jsxs(Text, { color: theme.colors.statusWaiting, children: [" - ", task.waitingFor] }))] }) }, task.id));
15
+ const displayLabel = task.isProject ? i18n.tui.keyBar.project : i18n.status[task.status];
16
+ return (_jsx(Box, { children: _jsxs(Text, { color: isSelected ? theme.colors.textSelected : theme.colors.text, bold: isSelected, children: [isSelected ? theme.style.selectedPrefix : theme.style.unselectedPrefix, "[", shortId, "] ", task.title, _jsxs(Text, { color: theme.colors.textMuted, children: [" (", displayLabel, ")"] }), task.waitingFor && (_jsxs(Text, { color: theme.colors.statusWaiting, children: [" - ", task.waitingFor] }))] }) }, task.id));
17
17
  })), results.length > 10 && (_jsxs(Text, { color: theme.colors.textMuted, italic: true, children: ["... and ", results.length - 10, " more"] }))] }));
18
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floq",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Floq - Getting Things Done Task Manager with MS-DOS style themes",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",