2026-06-01 00:59:22 +00:00
|
|
|
export interface Config {
|
|
|
|
|
url: string;
|
|
|
|
|
token: string | null;
|
2026-06-01 02:02:23 +00:00
|
|
|
userid: string;
|
2026-06-01 00:59:22 +00:00
|
|
|
owner: string;
|
|
|
|
|
repo: string;
|
2026-06-03 18:38:41 +00:00
|
|
|
autoRefreshInterval?: number;
|
2026-06-01 00:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface User {
|
|
|
|
|
id: number;
|
|
|
|
|
login: string;
|
|
|
|
|
full_name: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Label {
|
|
|
|
|
id: number;
|
|
|
|
|
name: string;
|
|
|
|
|
color: string;
|
2026-06-02 23:42:07 +00:00
|
|
|
description?: string;
|
|
|
|
|
exclusive?: boolean;
|
2026-06-01 00:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Issue {
|
|
|
|
|
id: number;
|
|
|
|
|
number: number;
|
|
|
|
|
title: string;
|
|
|
|
|
state: 'open' | 'closed';
|
|
|
|
|
body: string;
|
|
|
|
|
user: User;
|
|
|
|
|
created_at: string;
|
|
|
|
|
updated_at: string;
|
|
|
|
|
comments: number;
|
|
|
|
|
labels: Label[];
|
|
|
|
|
pull_request?: any | null;
|
2026-06-01 23:34:20 +00:00
|
|
|
total_tracked_time?: number; // Total time in seconds
|
2026-06-02 18:41:33 +00:00
|
|
|
assignees?: User[];
|
2026-06-01 00:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface Comment {
|
|
|
|
|
id: number;
|
|
|
|
|
user: User;
|
|
|
|
|
body: string;
|
|
|
|
|
created_at: string;
|
|
|
|
|
updated_at: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SetupForm {
|
|
|
|
|
url: string;
|
2026-06-01 02:02:23 +00:00
|
|
|
userid: string;
|
2026-06-01 00:59:22 +00:00
|
|
|
token: string;
|
2026-06-01 02:27:57 +00:00
|
|
|
saveConfig: boolean;
|
|
|
|
|
activeField: 'url' | 'userid' | 'token' | 'saveConfig';
|
2026-06-01 00:59:22 +00:00
|
|
|
}
|
|
|
|
|
|
2026-06-01 03:06:53 +00:00
|
|
|
export interface CreateIssueForm {
|
|
|
|
|
title: string;
|
|
|
|
|
body: string;
|
|
|
|
|
activeField: 'title' | 'body';
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-01 03:18:12 +00:00
|
|
|
export interface AddCommentForm {
|
|
|
|
|
body: string;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-01 23:15:01 +00:00
|
|
|
export interface EditIssueForm {
|
|
|
|
|
title: string;
|
|
|
|
|
body: string;
|
|
|
|
|
activeField: 'title' | 'body';
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-01 23:34:20 +00:00
|
|
|
export interface AddTimeForm {
|
|
|
|
|
timeInput: string;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-02 23:42:07 +00:00
|
|
|
export interface LabelForm {
|
|
|
|
|
name: string;
|
|
|
|
|
color: string;
|
|
|
|
|
description: string;
|
|
|
|
|
exclusive: boolean;
|
|
|
|
|
activeField: 'name' | 'color' | 'description' | 'exclusive';
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-03 13:34:31 +00:00
|
|
|
export type ScreenType = 'launch' | 'setup' | 'repo-picker' | 'list' | 'details' | 'create-issue' | 'add-comment' | 'edit-issue' | 'add-time' | 'confirm-state-change' | 'animating-close' | 'animating-reopen' | 'set-assignees' | 'labels-list' | 'create-label' | 'edit-label' | 'help';
|
2026-06-01 03:18:12 +00:00
|
|
|
|
2026-06-01 02:02:23 +00:00
|
|
|
|
|
|
|
|
export interface RepoItem {
|
|
|
|
|
id: number;
|
|
|
|
|
name: string;
|
|
|
|
|
full_name: string;
|
|
|
|
|
private: boolean;
|
|
|
|
|
description: string;
|
|
|
|
|
}
|
2026-06-01 00:59:22 +00:00
|
|
|
|
|
|
|
|
export interface AppState {
|
|
|
|
|
screen: ScreenType;
|
2026-06-03 13:34:31 +00:00
|
|
|
previousScreen?: ScreenType;
|
2026-06-01 00:59:22 +00:00
|
|
|
config: Config;
|
2026-06-03 18:38:41 +00:00
|
|
|
autoRefreshInterval: number;
|
2026-06-01 00:59:22 +00:00
|
|
|
|
2026-06-03 13:34:31 +00:00
|
|
|
focusedPane: 'list' | 'settings';
|
|
|
|
|
selectedSettingIndex: number;
|
|
|
|
|
|
2026-06-01 00:59:22 +00:00
|
|
|
// List Screen State
|
|
|
|
|
issues: Issue[];
|
|
|
|
|
currentPage: number;
|
|
|
|
|
issuesPerPage: number;
|
|
|
|
|
totalIssuesCount: number; // calculated or fetched
|
|
|
|
|
loading: boolean;
|
|
|
|
|
error: string | null;
|
|
|
|
|
selectedIssueIndex: number; // cursor in list
|
|
|
|
|
searchQuery: string;
|
|
|
|
|
stateFilter: 'open' | 'closed' | 'all';
|
|
|
|
|
typeFilter: 'issues' | 'pulls' | 'all';
|
2026-06-02 18:41:33 +00:00
|
|
|
sortField: 'created' | 'updated' | 'comments' | 'assignees';
|
2026-06-01 00:59:22 +00:00
|
|
|
sortOrder: 'asc' | 'desc';
|
|
|
|
|
|
|
|
|
|
// Detail Screen State
|
|
|
|
|
selectedIssue: Issue | null;
|
|
|
|
|
selectedIssueComments: Comment[];
|
|
|
|
|
commentsLoading: boolean;
|
|
|
|
|
detailScrollOffset: number;
|
2026-06-02 18:41:33 +00:00
|
|
|
assigneesInput: string;
|
2026-06-01 00:59:22 +00:00
|
|
|
|
2026-06-01 02:02:23 +00:00
|
|
|
// Repo Picker State
|
|
|
|
|
repos: RepoItem[];
|
|
|
|
|
selectedRepoIndex: number;
|
|
|
|
|
repoSearchQuery: string;
|
|
|
|
|
repoPickerActiveSearch: boolean;
|
|
|
|
|
|
2026-06-01 00:59:22 +00:00
|
|
|
// Setup Form State
|
|
|
|
|
setupForm: SetupForm;
|
2026-06-01 03:06:53 +00:00
|
|
|
|
|
|
|
|
// Create Issue Form State
|
|
|
|
|
createIssueForm: CreateIssueForm;
|
2026-06-01 03:18:12 +00:00
|
|
|
|
|
|
|
|
// Add Comment Form State
|
|
|
|
|
addCommentForm: AddCommentForm;
|
2026-06-01 23:15:01 +00:00
|
|
|
|
|
|
|
|
// Edit Issue Form State
|
|
|
|
|
editIssueForm: EditIssueForm;
|
2026-06-01 23:34:20 +00:00
|
|
|
|
|
|
|
|
// Add Time Form State
|
|
|
|
|
addTimeForm: AddTimeForm;
|
2026-06-02 23:42:07 +00:00
|
|
|
|
|
|
|
|
// Labels List State
|
|
|
|
|
labels: Label[];
|
|
|
|
|
selectedLabelIndex: number;
|
|
|
|
|
labelsLoading: boolean;
|
|
|
|
|
|
|
|
|
|
// Label Form State
|
|
|
|
|
labelForm: LabelForm;
|
2026-06-01 00:59:22 +00:00
|
|
|
}
|
2026-06-01 02:02:23 +00:00
|
|
|
|