floq 0.1.0 → 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 (42) hide show
  1. package/README.ja.md +89 -9
  2. package/README.md +89 -9
  3. package/dist/changelog.d.ts +13 -0
  4. package/dist/changelog.js +95 -0
  5. package/dist/cli.js +44 -1
  6. package/dist/commands/comment.d.ts +2 -0
  7. package/dist/commands/comment.js +67 -0
  8. package/dist/commands/config.d.ts +4 -0
  9. package/dist/commands/config.js +123 -1
  10. package/dist/commands/setup.d.ts +1 -0
  11. package/dist/commands/setup.js +13 -0
  12. package/dist/config.d.ts +5 -0
  13. package/dist/config.js +40 -3
  14. package/dist/db/index.js +20 -0
  15. package/dist/db/schema.d.ts +83 -0
  16. package/dist/db/schema.js +6 -0
  17. package/dist/i18n/en.d.ts +237 -0
  18. package/dist/i18n/en.js +127 -3
  19. package/dist/i18n/ja.js +127 -3
  20. package/dist/index.js +14 -4
  21. package/dist/paths.d.ts +4 -0
  22. package/dist/paths.js +63 -5
  23. package/dist/ui/App.js +280 -25
  24. package/dist/ui/ModeSelector.d.ts +7 -0
  25. package/dist/ui/ModeSelector.js +37 -0
  26. package/dist/ui/SetupWizard.d.ts +6 -0
  27. package/dist/ui/SetupWizard.js +321 -0
  28. package/dist/ui/components/HelpModal.d.ts +2 -1
  29. package/dist/ui/components/HelpModal.js +118 -4
  30. package/dist/ui/components/KanbanBoard.d.ts +6 -0
  31. package/dist/ui/components/KanbanBoard.js +508 -0
  32. package/dist/ui/components/KanbanColumn.d.ts +12 -0
  33. package/dist/ui/components/KanbanColumn.js +11 -0
  34. package/dist/ui/components/ProgressBar.d.ts +7 -0
  35. package/dist/ui/components/ProgressBar.js +13 -0
  36. package/dist/ui/components/SearchBar.d.ts +8 -0
  37. package/dist/ui/components/SearchBar.js +11 -0
  38. package/dist/ui/components/SearchResults.d.ts +9 -0
  39. package/dist/ui/components/SearchResults.js +18 -0
  40. package/dist/ui/components/TaskItem.d.ts +6 -1
  41. package/dist/ui/components/TaskItem.js +3 -2
  42. package/package.json +1 -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,6 +89,7 @@ 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}に紐づけました',
@@ -86,16 +102,23 @@ export const ja = {
86
102
  done: '完了',
87
103
  next: '次へ',
88
104
  someday: 'いつか',
105
+ waiting: '待ち',
89
106
  inbox: 'Inbox',
90
107
  project: 'プロジェクト',
91
108
  help: 'ヘルプ',
92
109
  quit: '終了',
110
+ comment: 'コメント',
111
+ back: '戻る',
112
+ delete: '削除',
93
113
  },
94
114
  // Help modal
95
115
  help: {
96
116
  title: 'キーボードショートカット',
117
+ whatsNewTab: '更新履歴',
118
+ keybindingsTab: 'キー操作',
119
+ tabHint: 'Tab: 表示切替',
97
120
  navigation: 'ナビゲーション',
98
- tabSwitch: 'タブ切替 (5=プロジェクト)',
121
+ tabSwitch: 'タブ切替 (5=プロジェクト, 6=完了)',
99
122
  prevNextTab: '前後のタブ',
100
123
  taskSelect: 'タスク選択',
101
124
  actions: 'アクション',
@@ -103,6 +126,7 @@ export const ja = {
103
126
  completeTask: '選択タスクを完了',
104
127
  moveToNext: '次のアクションへ移動',
105
128
  moveToSomeday: 'いつかやるへ移動',
129
+ moveToWaiting: '連絡待ちへ移動',
106
130
  moveToInbox: 'Inboxへ移動',
107
131
  refresh: 'リスト更新',
108
132
  projects: 'プロジェクト',
@@ -110,10 +134,110 @@ export const ja = {
110
134
  linkToProject: 'タスクをプロジェクトに紐づけ',
111
135
  openProject: 'プロジェクトを開く (Projectsタブ)',
112
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: 'タスク検索',
113
169
  other: 'その他',
114
170
  showHelp: 'このヘルプを表示',
115
171
  quit: '終了',
116
- 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を開始...',
117
241
  },
118
242
  },
119
243
  };
package/dist/index.js CHANGED
@@ -1,23 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import { program } from './cli.js';
3
3
  import { initDb } from './db/index.js';
4
- import { isTursoEnabled, getTursoConfig } from './config.js';
4
+ import { isTursoEnabled, getTursoConfig, isFirstRun } from './config.js';
5
+ import { runSetupWizard } from './commands/setup.js';
5
6
  async function main() {
6
7
  // 起動時にモードを表示(TUI以外のコマンド時)
7
8
  const args = process.argv.slice(2);
8
9
  const isTuiMode = args.length === 0;
9
10
  const isConfigCommand = args[0] === 'config';
10
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
+ }
11
21
  // config/syncコマンド以外でTursoモードの場合は接続先を表示
12
- if (!isTuiMode && !isConfigCommand && !isSyncCommand && isTursoEnabled()) {
22
+ if (!isTuiMode && !isConfigCommand && !isSyncCommand && !isSetupCommand && isTursoEnabled()) {
13
23
  const turso = getTursoConfig();
14
24
  if (turso) {
15
25
  const host = new URL(turso.url).host;
16
26
  console.log(`🔄 Turso sync: ${host}`);
17
27
  }
18
28
  }
19
- // configコマンドはDB不要なのでスキップ
20
- if (!isConfigCommand) {
29
+ // config/setupコマンドはDB不要なのでスキップ
30
+ if (!isConfigCommand && !isSetupCommand) {
21
31
  await initDb();
22
32
  }
23
33
  program.parse();
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');