floq 0.0.1 → 0.2.0

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.
Files changed (55) hide show
  1. package/README.ja.md +157 -29
  2. package/README.md +157 -29
  3. package/dist/changelog.d.ts +13 -0
  4. package/dist/changelog.js +95 -0
  5. package/dist/cli.js +70 -1
  6. package/dist/commands/add.js +5 -6
  7. package/dist/commands/comment.d.ts +2 -0
  8. package/dist/commands/comment.js +67 -0
  9. package/dist/commands/config.d.ts +7 -0
  10. package/dist/commands/config.js +163 -14
  11. package/dist/commands/done.js +4 -6
  12. package/dist/commands/list.js +9 -13
  13. package/dist/commands/move.js +4 -6
  14. package/dist/commands/project.js +18 -26
  15. package/dist/commands/setup.d.ts +1 -0
  16. package/dist/commands/setup.js +13 -0
  17. package/dist/config.d.ts +15 -1
  18. package/dist/config.js +53 -2
  19. package/dist/db/index.d.ts +5 -4
  20. package/dist/db/index.js +127 -32
  21. package/dist/db/schema.d.ts +83 -0
  22. package/dist/db/schema.js +6 -0
  23. package/dist/i18n/en.d.ts +258 -0
  24. package/dist/i18n/en.js +138 -3
  25. package/dist/i18n/ja.js +138 -3
  26. package/dist/index.js +33 -1
  27. package/dist/paths.d.ts +4 -0
  28. package/dist/paths.js +63 -5
  29. package/dist/ui/App.js +384 -136
  30. package/dist/ui/ModeSelector.d.ts +7 -0
  31. package/dist/ui/ModeSelector.js +37 -0
  32. package/dist/ui/SetupWizard.d.ts +6 -0
  33. package/dist/ui/SetupWizard.js +321 -0
  34. package/dist/ui/ThemeSelector.d.ts +1 -1
  35. package/dist/ui/ThemeSelector.js +23 -10
  36. package/dist/ui/components/FunctionKeyBar.d.ts +5 -4
  37. package/dist/ui/components/FunctionKeyBar.js +19 -15
  38. package/dist/ui/components/HelpModal.d.ts +2 -1
  39. package/dist/ui/components/HelpModal.js +118 -4
  40. package/dist/ui/components/KanbanBoard.d.ts +6 -0
  41. package/dist/ui/components/KanbanBoard.js +508 -0
  42. package/dist/ui/components/KanbanColumn.d.ts +12 -0
  43. package/dist/ui/components/KanbanColumn.js +11 -0
  44. package/dist/ui/components/ProgressBar.d.ts +7 -0
  45. package/dist/ui/components/ProgressBar.js +13 -0
  46. package/dist/ui/components/SearchBar.d.ts +8 -0
  47. package/dist/ui/components/SearchBar.js +11 -0
  48. package/dist/ui/components/SearchResults.d.ts +9 -0
  49. package/dist/ui/components/SearchResults.js +18 -0
  50. package/dist/ui/components/TaskItem.d.ts +6 -1
  51. package/dist/ui/components/TaskItem.js +3 -2
  52. package/dist/ui/theme/themes.d.ts +12 -0
  53. package/dist/ui/theme/themes.js +495 -3
  54. package/dist/ui/theme/types.d.ts +1 -1
  55. package/package.json +2 -1
package/dist/i18n/ja.js CHANGED
@@ -7,6 +7,12 @@ export const ja = {
7
7
  someday: 'いつかやる',
8
8
  done: '完了',
9
9
  },
10
+ // Kanban mode labels
11
+ kanban: {
12
+ todo: 'TODO',
13
+ doing: '作業中',
14
+ done: '完了',
15
+ },
10
16
  // Project status
11
17
  projectStatus: {
12
18
  active: 'アクティブなプロジェクト',
@@ -54,6 +60,13 @@ export const ja = {
54
60
  statusLabel: 'ステータス: {status}',
55
61
  tasksCount: 'タスク: {count}件',
56
62
  },
63
+ comment: {
64
+ added: '「{title}」にコメントを追加しました',
65
+ notFound: 'タスクが見つかりません: {id}',
66
+ multipleMatch: '「{id}」に一致するタスクが複数あります。より具体的に指定してください:',
67
+ noComments: 'コメントはありません',
68
+ listHeader: '「{title}」のコメント:',
69
+ },
57
70
  },
58
71
  // TUI
59
72
  tui: {
@@ -65,8 +78,10 @@ export const ja = {
65
78
  added: '追加しました: 「{title}」',
66
79
  completed: '完了しました: 「{title}」',
67
80
  movedTo: '「{title}」を{status}に移動しました',
81
+ movedToWaiting: '「{title}」を連絡待ち({person})に移動しました',
82
+ waitingFor: '待機相手: ',
68
83
  refreshed: '更新しました',
69
- footer: 'a=追加 d=完了 n=次 s=いつか i=Inbox p=プロジェクト化 P=紐づけ',
84
+ footer: 'a=追加 d=完了 n=次 s=いつか w=待ち i=Inbox p=プロジェクト化 P=紐づけ',
70
85
  noTasks: 'タスクなし',
71
86
  // Tab labels
72
87
  tabInbox: 'Inbox',
@@ -74,17 +89,36 @@ export const ja = {
74
89
  tabWaiting: '待ち',
75
90
  tabSomeday: 'いつか',
76
91
  tabProjects: 'プロジェクト',
92
+ tabDone: '完了',
77
93
  // Project actions
78
94
  madeProject: 'プロジェクト化しました: 「{title}」',
79
95
  linkedToProject: '「{title}」を{project}に紐づけました',
80
96
  selectProject: 'プロジェクトを選択',
81
97
  selectProjectHelp: 'j/k: 選択, Enter: 確定, Esc: キャンセル',
82
98
  back: '戻る',
99
+ // Action key bar labels
100
+ keyBar: {
101
+ add: '追加',
102
+ done: '完了',
103
+ next: '次へ',
104
+ someday: 'いつか',
105
+ waiting: '待ち',
106
+ inbox: 'Inbox',
107
+ project: 'プロジェクト',
108
+ help: 'ヘルプ',
109
+ quit: '終了',
110
+ comment: 'コメント',
111
+ back: '戻る',
112
+ delete: '削除',
113
+ },
83
114
  // Help modal
84
115
  help: {
85
116
  title: 'キーボードショートカット',
117
+ whatsNewTab: '更新履歴',
118
+ keybindingsTab: 'キー操作',
119
+ tabHint: 'Tab: 表示切替',
86
120
  navigation: 'ナビゲーション',
87
- tabSwitch: 'タブ切替 (5=プロジェクト)',
121
+ tabSwitch: 'タブ切替 (5=プロジェクト, 6=完了)',
88
122
  prevNextTab: '前後のタブ',
89
123
  taskSelect: 'タスク選択',
90
124
  actions: 'アクション',
@@ -92,6 +126,7 @@ export const ja = {
92
126
  completeTask: '選択タスクを完了',
93
127
  moveToNext: '次のアクションへ移動',
94
128
  moveToSomeday: 'いつかやるへ移動',
129
+ moveToWaiting: '連絡待ちへ移動',
95
130
  moveToInbox: 'Inboxへ移動',
96
131
  refresh: 'リスト更新',
97
132
  projects: 'プロジェクト',
@@ -99,10 +134,110 @@ export const ja = {
99
134
  linkToProject: 'タスクをプロジェクトに紐づけ',
100
135
  openProject: 'プロジェクトを開く (Projectsタブ)',
101
136
  backFromProject: 'プロジェクト詳細から戻る',
137
+ taskDetail: 'タスク詳細を表示',
138
+ addComment: 'コメント追加',
139
+ searchTasks: 'タスク検索',
140
+ other: 'その他',
141
+ showHelp: 'このヘルプを表示',
142
+ quit: '終了',
143
+ closeHint: 'Esc/q: 閉じる',
144
+ },
145
+ // What's New / Changelog
146
+ whatsNew: {
147
+ title: '更新履歴',
148
+ noChanges: '更新履歴はありません',
149
+ added: '追加',
150
+ changed: '変更',
151
+ deprecated: '非推奨',
152
+ removed: '削除',
153
+ fixed: '修正',
154
+ security: 'セキュリティ',
155
+ },
156
+ // Kanban mode help
157
+ kanbanHelp: {
158
+ title: 'Kanbanショートカット',
159
+ navigation: 'ナビゲーション',
160
+ columnSwitch: 'カラム切替',
161
+ columnDirect: 'カラムに直接ジャンプ',
162
+ taskSelect: 'タスク選択',
163
+ actions: 'アクション',
164
+ addTask: '新規タスク追加 (TODOへ)',
165
+ completeTask: '完了へ移動',
166
+ moveRight: '次のカラムへ移動',
167
+ moveLeft: '前のカラムへ戻す',
168
+ searchTasks: 'タスク検索',
102
169
  other: 'その他',
103
170
  showHelp: 'このヘルプを表示',
104
171
  quit: '終了',
105
- closeHint: '任意のキーで閉じる',
172
+ closeHint: 'Esc/q: 閉じる',
173
+ },
174
+ addComment: '新規コメント: ',
175
+ noComments: 'コメントはまだありません',
176
+ commentHint: 'i: コメント追加',
177
+ linkHint: 'P: プロジェクト紐づけ',
178
+ commentAdded: 'コメントを追加しました',
179
+ commentDeleted: 'コメントを削除しました',
180
+ taskDetailTitle: 'タスク詳細',
181
+ taskDetailFooter: 'j/k=選択 i=コメント d=削除 P=紐づけ b/Esc=戻る',
182
+ comments: 'コメント',
183
+ projectTasks: 'タスク一覧',
184
+ // Search
185
+ search: {
186
+ prefix: '/',
187
+ placeholder: 'タスクを検索...',
188
+ help: '(Enterで選択, Ctrl+j/kで移動, Escでキャンセル)',
189
+ noResults: '該当するタスクがありません',
190
+ resultsTitle: '検索結果',
191
+ searchTasks: 'タスク検索',
192
+ },
193
+ },
194
+ // Setup wizard
195
+ setup: {
196
+ welcome: {
197
+ title: 'Floqへようこそ!',
198
+ subtitle: 'タスクマネージャーを設定しましょう',
199
+ instruction: '任意のキーを押して設定を開始...',
200
+ },
201
+ language: {
202
+ title: '言語を選択',
203
+ hint: 'j/k: 選択, Enter: 確定, Esc: 戻る',
204
+ },
205
+ theme: {
206
+ title: 'テーマを選択',
207
+ hint: 'j/k: 選択, Enter: 確定, Esc: 戻る',
208
+ },
209
+ viewMode: {
210
+ title: '表示モードを選択',
211
+ hint: 'j/k: 選択, Enter: 確定, Esc: 戻る',
212
+ gtd: 'GTD (Getting Things Done)',
213
+ gtdDesc: 'Inbox、次のアクション、連絡待ち、いつかやるリストによるクラシックGTDワークフロー',
214
+ kanban: 'Kanbanボード',
215
+ kanbanDesc: '3カラムのKanbanボード表示',
216
+ },
217
+ database: {
218
+ title: 'データベースモードを選択',
219
+ local: 'ローカル',
220
+ localDesc: 'このデバイスにデータをローカル保存',
221
+ turso: 'Turso Cloud',
222
+ tursoDesc: 'Turso経由でデバイス間でデータを同期',
223
+ hint: 'j/k: 選択, Enter: 確定, Esc: 戻る',
224
+ },
225
+ turso: {
226
+ urlPrompt: 'TursoデータベースURL',
227
+ urlPlaceholder: 'libsql://your-db.turso.io',
228
+ urlError: 'URLはlibsql://で始まる必要があります',
229
+ tokenPrompt: 'Turso認証トークン',
230
+ tokenError: 'トークンは空にできません',
231
+ inputHint: 'Enter: 確定, Esc: 戻る',
232
+ },
233
+ complete: {
234
+ title: '設定完了!',
235
+ summary: '設定内容:',
236
+ language: '言語',
237
+ theme: 'テーマ',
238
+ viewMode: '表示モード',
239
+ database: 'データベース',
240
+ confirm: 'Enterを押してFloqを開始...',
106
241
  },
107
242
  },
108
243
  };
package/dist/index.js CHANGED
@@ -1,3 +1,35 @@
1
1
  #!/usr/bin/env node
2
2
  import { program } from './cli.js';
3
- program.parse();
3
+ import { initDb } from './db/index.js';
4
+ import { isTursoEnabled, getTursoConfig, isFirstRun } from './config.js';
5
+ import { runSetupWizard } from './commands/setup.js';
6
+ async function main() {
7
+ // 起動時にモードを表示(TUI以外のコマンド時)
8
+ const args = process.argv.slice(2);
9
+ const isTuiMode = args.length === 0;
10
+ const isConfigCommand = args[0] === 'config';
11
+ const isSyncCommand = args[0] === 'sync';
12
+ const isSetupCommand = args[0] === 'setup';
13
+ // 初回起動時(引数なし + config未作成)はウィザードを起動
14
+ if (isTuiMode && isFirstRun()) {
15
+ await runSetupWizard();
16
+ // ウィザード完了後、DBを初期化してTUIを起動
17
+ await initDb();
18
+ program.parse();
19
+ return;
20
+ }
21
+ // config/syncコマンド以外でTursoモードの場合は接続先を表示
22
+ if (!isTuiMode && !isConfigCommand && !isSyncCommand && !isSetupCommand && isTursoEnabled()) {
23
+ const turso = getTursoConfig();
24
+ if (turso) {
25
+ const host = new URL(turso.url).host;
26
+ console.log(`🔄 Turso sync: ${host}`);
27
+ }
28
+ }
29
+ // config/setupコマンドはDB不要なのでスキップ
30
+ if (!isConfigCommand && !isSetupCommand) {
31
+ await initDb();
32
+ }
33
+ program.parse();
34
+ }
35
+ main().catch(console.error);
package/dist/paths.d.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  export declare function getConfigDir(): string;
2
2
  export declare function getDataDir(): string;
3
+ /**
4
+ * Run migration from legacy paths if needed
5
+ */
6
+ export declare function runMigration(): void;
3
7
  export declare const CONFIG_DIR: string;
4
8
  export declare const DATA_DIR: string;
5
9
  export declare const CONFIG_FILE: string;
package/dist/paths.js CHANGED
@@ -1,22 +1,80 @@
1
1
  import { homedir } from 'os';
2
2
  import { join } from 'path';
3
+ import { existsSync, renameSync, mkdirSync, readdirSync } from 'fs';
3
4
  // XDG Base Directory Specification
4
5
  // https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
6
+ const APP_NAME = 'floq';
7
+ const LEGACY_APP_NAME = 'gtd-cli';
8
+ function getLegacyConfigDir() {
9
+ const xdgConfigHome = process.env.XDG_CONFIG_HOME;
10
+ if (xdgConfigHome) {
11
+ return join(xdgConfigHome, LEGACY_APP_NAME);
12
+ }
13
+ return join(homedir(), '.config', LEGACY_APP_NAME);
14
+ }
15
+ function getLegacyDataDir() {
16
+ const xdgDataHome = process.env.XDG_DATA_HOME;
17
+ if (xdgDataHome) {
18
+ return join(xdgDataHome, LEGACY_APP_NAME);
19
+ }
20
+ return join(homedir(), '.local', 'share', LEGACY_APP_NAME);
21
+ }
5
22
  export function getConfigDir() {
6
23
  const xdgConfigHome = process.env.XDG_CONFIG_HOME;
7
24
  if (xdgConfigHome) {
8
- return join(xdgConfigHome, 'gtd-cli');
25
+ return join(xdgConfigHome, APP_NAME);
9
26
  }
10
- return join(homedir(), '.config', 'gtd-cli');
27
+ return join(homedir(), '.config', APP_NAME);
11
28
  }
12
29
  export function getDataDir() {
13
30
  const xdgDataHome = process.env.XDG_DATA_HOME;
14
31
  if (xdgDataHome) {
15
- return join(xdgDataHome, 'gtd-cli');
32
+ return join(xdgDataHome, APP_NAME);
16
33
  }
17
- return join(homedir(), '.local', 'share', 'gtd-cli');
34
+ return join(homedir(), '.local', 'share', APP_NAME);
35
+ }
36
+ /**
37
+ * Migrate from legacy gtd-cli directories to floq directories
38
+ */
39
+ function migrateDirectory(legacyDir, newDir) {
40
+ // Only migrate if legacy exists and new doesn't
41
+ if (existsSync(legacyDir) && !existsSync(newDir)) {
42
+ try {
43
+ // Create parent directory if needed
44
+ const parentDir = join(newDir, '..');
45
+ if (!existsSync(parentDir)) {
46
+ mkdirSync(parentDir, { recursive: true });
47
+ }
48
+ // Rename (move) the directory
49
+ renameSync(legacyDir, newDir);
50
+ }
51
+ catch {
52
+ // If rename fails (cross-device), copy files manually
53
+ try {
54
+ mkdirSync(newDir, { recursive: true });
55
+ const files = readdirSync(legacyDir);
56
+ for (const file of files) {
57
+ const legacyPath = join(legacyDir, file);
58
+ const newPath = join(newDir, file);
59
+ renameSync(legacyPath, newPath);
60
+ }
61
+ }
62
+ catch {
63
+ // Ignore migration errors, user can migrate manually
64
+ }
65
+ }
66
+ }
67
+ }
68
+ /**
69
+ * Run migration from legacy paths if needed
70
+ */
71
+ export function runMigration() {
72
+ migrateDirectory(getLegacyConfigDir(), getConfigDir());
73
+ migrateDirectory(getLegacyDataDir(), getDataDir());
18
74
  }
75
+ // Run migration on module load
76
+ runMigration();
19
77
  export const CONFIG_DIR = getConfigDir();
20
78
  export const DATA_DIR = getDataDir();
21
79
  export const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
22
- export const DB_PATH = join(DATA_DIR, 'gtd.db');
80
+ export const DB_PATH = join(DATA_DIR, 'floq.db');