diff --git a/src/tui.ts b/src/tui.ts index 064ef9e..c925764 100644 --- a/src/tui.ts +++ b/src/tui.ts @@ -437,6 +437,8 @@ export class TuiEngine { this.handleCreateIssueKeypress(str, key); } else if (this.state.screen === 'confirm-cancel-create') { this.handleConfirmCancelCreateKeypress(str, key); + } else if (this.state.screen === 'confirm-cancel-edit') { + this.handleConfirmCancelEditKeypress(str, key); } else if (this.state.screen === 'add-comment') { this.handleAddCommentKeypress(str, key); } else if (this.state.screen === 'edit-issue') { @@ -1100,6 +1102,8 @@ export class TuiEngine { this.renderConfirmStateChangeScreen(cols, rows); } else if (this.state.screen === 'confirm-cancel-create') { this.renderConfirmCancelCreateScreen(cols, rows); + } else if (this.state.screen === 'confirm-cancel-edit') { + this.renderConfirmCancelEditScreen(cols, rows); } else if (this.state.screen === 'animating-close') { this.renderAnimationScreen(cols, rows, GRAVESTONE_FRAMES); } else if (this.state.screen === 'animating-reopen') { @@ -1939,8 +1943,7 @@ export class TuiEngine { } if (key && (key.name === 'up' || key.name === 'down') && activeField === 'body') { - const lines = val.split(' -'); + const lines = val.split('\n'); let lineIdx = 0, col = 0, count = 0; for (let i = 0; i < lines.length; i++) { if (count + lines[i].length >= cursor) { @@ -1983,8 +1986,7 @@ export class TuiEngine { if (key && key.name === 'return') { if (activeField === 'body') { - this.state.createIssueForm.body = val.slice(0, cursor) + ' -' + val.slice(cursor); + this.state.createIssueForm.body = val.slice(0, cursor) + '\n' + val.slice(cursor); this.state.createIssueForm.cursor = cursor + 1; this.render(); } else { @@ -2273,7 +2275,7 @@ export class TuiEngine { private async handleEditIssueKeypress(str: string, key: any) { if (key && key.name === 'escape') { - this.state.screen = 'details'; + this.state.screen = 'confirm-cancel-edit'; this.state.error = null; this.render(); return; @@ -2343,8 +2345,7 @@ export class TuiEngine { } if (key && (key.name === 'up' || key.name === 'down') && activeField === 'body') { - const lines = val.split(' -'); + const lines = val.split('\n'); let lineIdx = 0, col = 0, count = 0; for (let i = 0; i < lines.length; i++) { if (count + lines[i].length >= cursor) { @@ -2387,8 +2388,7 @@ export class TuiEngine { if (key && key.name === 'return') { if (activeField === 'body') { - this.state.editIssueForm.body = val.slice(0, cursor) + ' -' + val.slice(cursor); + this.state.editIssueForm.body = val.slice(0, cursor) + '\n' + val.slice(cursor); this.state.editIssueForm.cursor = cursor + 1; this.render(); } else { @@ -2675,6 +2675,51 @@ export class TuiEngine { return; } } + + private renderConfirmCancelEditScreen(cols: number, rows: number) { + const borderCh = chalk.bold.hex('#4A90E2')('│'); + + const title = ' Confirm Cancel '; + const leftLen = stripAnsi(title).length; + let leftHeader = chalk.bold.hex('#4A90E2')(title); + + console.log(leftHeader + ' '.repeat(Math.max(1, cols - leftLen - 1))); + console.log(chalk.bold.hex('#4A90E2')('┌' + '─'.repeat(cols - 2) + '┐')); + + const question = 'Are you sure you want to cancel editing this issue?'; + const promptPlain = ` ${question} [y/N] `; + + const paddingRows = Math.floor((rows - 8) / 2); + for (let i = 0; i < paddingRows; i++) console.log(borderCh + ' '.repeat(cols - 2) + borderCh); + + const padContentLeft = Math.max(0, Math.floor((cols - 2 - promptPlain.length) / 2)); + const contentLine = (' '.repeat(padContentLeft) + chalk.yellow.bold(question) + ' [y/N] ').padEnd(cols - 2 + (chalk.yellow.bold(question).length - question.length)); + console.log(borderCh + contentLine + borderCh); + + for (let i = 0; i < (rows - 8) - paddingRows; i++) console.log(borderCh + ' '.repeat(cols - 2) + borderCh); + + console.log(chalk.bold.hex('#4A90E2')('└' + '─'.repeat(cols - 2) + '┘')); + + const helpLinePlain = ' [y] Yes [n/Esc] No'; + process.stdout.write(chalk.gray(helpLinePlain)); + } + + private async handleConfirmCancelEditKeypress(str: string, key: any) { + if ((key && (key.name === 'escape' || key.name === 'n')) || str === 'n' || str === 'N') { + this.state.screen = 'edit-issue'; + this.state.error = null; + this.render(); + return; + } + + if (str === 'y' || str === 'Y') { + this.state.screen = 'details'; + this.state.error = null; + this.render(); + return; + } + } + private renderSetAssigneesScreen(cols: number, rows: number) { const borderCh = chalk.bold.hex('#4A90E2')('│'); diff --git a/src/types.ts b/src/types.ts index bf51e81..1668c2d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -83,7 +83,7 @@ export interface LabelForm { activeField: 'name' | 'color' | 'description' | 'exclusive'; } -export type ScreenType = 'launch' | 'setup' | 'repo-picker' | 'list' | 'details' | 'create-issue' | 'add-comment' | 'edit-issue' | 'add-time' | 'confirm-state-change' | 'confirm-cancel-create' | 'animating-close' | 'animating-reopen' | 'set-assignees' | 'labels-list' | 'create-label' | 'edit-label' | 'help'; +export type ScreenType = 'launch' | 'setup' | 'repo-picker' | 'list' | 'details' | 'create-issue' | 'add-comment' | 'edit-issue' | 'add-time' | 'confirm-state-change' | 'confirm-cancel-create' | 'confirm-cancel-edit' | 'animating-close' | 'animating-reopen' | 'set-assignees' | 'labels-list' | 'create-label' | 'edit-label' | 'help'; export interface RepoItem {