@muhammedaksam/easiarr 0.8.2 → 0.8.4

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.
@@ -18,6 +18,11 @@ import { FullAutoSetup } from "./FullAutoSetup"
18
18
  import { MonitorDashboard } from "./MonitorDashboard"
19
19
  import { HomepageSetup } from "./HomepageSetup"
20
20
  import { JellyfinSetup } from "./JellyfinSetup"
21
+ import { JellyseerrSetup } from "./JellyseerrSetup"
22
+
23
+ type MenuItem = { name: string; description: string; action: () => void | Promise<void> }
24
+
25
+ type ScreenConstructor = new (renderer: CliRenderer, config: EasiarrConfig, onBack: () => void) => BoxRenderable
21
26
 
22
27
  export class MainMenu {
23
28
  private renderer: RenderContext
@@ -26,6 +31,7 @@ export class MainMenu {
26
31
  private config: EasiarrConfig
27
32
  private menu!: SelectRenderable
28
33
  private page!: BoxRenderable
34
+ private menuItems: MenuItem[] = []
29
35
 
30
36
  constructor(renderer: RenderContext, container: BoxRenderable, app: App, config: EasiarrConfig) {
31
37
  this.renderer = renderer
@@ -36,6 +42,122 @@ export class MainMenu {
36
42
  this.render()
37
43
  }
38
44
 
45
+ private isAppEnabled(id: string): boolean {
46
+ return this.config.apps.some((a) => a.id === id && a.enabled)
47
+ }
48
+
49
+ private buildMenuItems(): MenuItem[] {
50
+ const items: MenuItem[] = []
51
+
52
+ // Core items (always shown)
53
+ items.push({
54
+ name: "📦 Manage Apps",
55
+ description: "Add, remove, or configure apps",
56
+ action: () => this.app.navigateTo("appManager"),
57
+ })
58
+ items.push({
59
+ name: "🐳 Container Control",
60
+ description: "Start, stop, restart containers",
61
+ action: () => this.app.navigateTo("containerControl"),
62
+ })
63
+ items.push({
64
+ name: "⚙️ Advanced Settings",
65
+ description: "Customize ports, volumes, env",
66
+ action: () => this.app.navigateTo("advancedSettings"),
67
+ })
68
+ items.push({
69
+ name: "🔑 Extract API Keys",
70
+ description: "Find API keys from running containers",
71
+ action: () => this.showScreen(ApiKeyViewer),
72
+ })
73
+ items.push({
74
+ name: "⚙️ Configure Apps",
75
+ description: "Set root folders and download clients via API",
76
+ action: () => this.showScreen(AppConfigurator),
77
+ })
78
+ items.push({
79
+ name: "🎯 TRaSH Guide Setup",
80
+ description: "Apply TRaSH quality profiles and custom formats",
81
+ action: () => this.showScreen(TRaSHProfileSetup),
82
+ })
83
+ items.push({
84
+ name: "🔄 Regenerate Compose",
85
+ description: "Rebuild docker-compose.yml",
86
+ action: async () => {
87
+ await saveCompose(this.config)
88
+ },
89
+ })
90
+
91
+ // Conditional items based on enabled apps
92
+ if (this.isAppEnabled("prowlarr")) {
93
+ items.push({
94
+ name: "🔗 Prowlarr Setup",
95
+ description: "Sync indexers to *arr apps, FlareSolverr",
96
+ action: () => this.showScreen(ProwlarrSetup),
97
+ })
98
+ }
99
+ if (this.isAppEnabled("qbittorrent")) {
100
+ items.push({
101
+ name: "⚡ qBittorrent Setup",
102
+ description: "Configure TRaSH-compliant paths and categories",
103
+ action: () => this.showScreen(QBittorrentSetup),
104
+ })
105
+ }
106
+
107
+ // Full Auto Setup (always shown)
108
+ items.push({
109
+ name: "🚀 Full Auto Setup",
110
+ description: "Run all configurations (Auth, Root Folders, Prowlarr, etc.)",
111
+ action: () => this.showScreen(FullAutoSetup),
112
+ })
113
+
114
+ items.push({
115
+ name: "📊 Monitor Dashboard",
116
+ description: "Configure app health monitoring",
117
+ action: () => this.showScreen(MonitorDashboard),
118
+ })
119
+
120
+ if (this.isAppEnabled("homepage")) {
121
+ items.push({
122
+ name: "🏠 Homepage Setup",
123
+ description: "Generate Homepage dashboard config",
124
+ action: () => this.showScreen(HomepageSetup),
125
+ })
126
+ }
127
+ if (this.isAppEnabled("jellyfin")) {
128
+ items.push({
129
+ name: "🎬 Jellyfin Setup",
130
+ description: "Run Jellyfin setup wizard via API",
131
+ action: () => this.showScreen(JellyfinSetup),
132
+ })
133
+ }
134
+ if (this.isAppEnabled("jellyseerr")) {
135
+ items.push({
136
+ name: "🎥 Jellyseerr Setup",
137
+ description: "Configure Jellyseerr with media server",
138
+ action: () => this.showScreen(JellyseerrSetup),
139
+ })
140
+ }
141
+
142
+ items.push({
143
+ name: "❌ Exit",
144
+ description: "Close easiarr",
145
+ action: () => process.exit(0),
146
+ })
147
+
148
+ return items
149
+ }
150
+
151
+ private showScreen(ScreenClass: ScreenConstructor): void {
152
+ this.menu.blur()
153
+ this.page.visible = false
154
+ const screen = new ScreenClass(this.renderer as CliRenderer, this.config, () => {
155
+ this.page.visible = true
156
+ this.menu.focus()
157
+ })
158
+ this.container.add(screen)
159
+ }
160
+
39
161
  private render(): void {
40
162
  const { container: page, content } = createPageLayout(this.renderer as CliRenderer, {
41
163
  title: "Main Menu",
@@ -81,187 +203,21 @@ export class MainMenu {
81
203
 
82
204
  content.add(new TextRenderable(this.renderer, { id: "spacer2", content: " " }))
83
205
 
206
+ // Build menu items dynamically based on enabled apps
207
+ this.menuItems = this.buildMenuItems()
208
+
84
209
  // Menu
85
210
  this.menu = new SelectRenderable(this.renderer, {
86
211
  id: "main-menu-select",
87
212
  width: "100%",
88
213
  flexGrow: 1,
89
- options: [
90
- {
91
- name: "📦 Manage Apps",
92
- description: "Add, remove, or configure apps",
93
- },
94
- {
95
- name: "🐳 Container Control",
96
- description: "Start, stop, restart containers",
97
- },
98
- {
99
- name: "⚙️ Advanced Settings",
100
- description: "Customize ports, volumes, env",
101
- },
102
- {
103
- name: "🔑 Extract API Keys",
104
- description: "Find API keys from running containers",
105
- },
106
- {
107
- name: "⚙️ Configure Apps",
108
- description: "Set root folders and download clients via API",
109
- },
110
- {
111
- name: "🎯 TRaSH Guide Setup",
112
- description: "Apply TRaSH quality profiles and custom formats",
113
- },
114
- {
115
- name: "🔄 Regenerate Compose",
116
- description: "Rebuild docker-compose.yml",
117
- },
118
- {
119
- name: "🔗 Prowlarr Setup",
120
- description: "Sync indexers to *arr apps, FlareSolverr",
121
- },
122
- {
123
- name: "⚡ qBittorrent Setup",
124
- description: "Configure TRaSH-compliant paths and categories",
125
- },
126
- {
127
- name: "🚀 Full Auto Setup",
128
- description: "Run all configurations (Auth, Root Folders, Prowlarr, etc.)",
129
- },
130
- {
131
- name: "📊 Monitor Dashboard",
132
- description: "Configure app health monitoring",
133
- },
134
- {
135
- name: "🏠 Homepage Setup",
136
- description: "Generate Homepage dashboard config",
137
- },
138
- {
139
- name: "🎬 Jellyfin Setup",
140
- description: "Run Jellyfin setup wizard via API",
141
- },
142
- { name: "❌ Exit", description: "Close easiarr" },
143
- ],
214
+ options: this.menuItems.map((item) => ({ name: item.name, description: item.description })),
144
215
  })
145
216
 
146
217
  this.menu.on(SelectRenderableEvents.ITEM_SELECTED, async (index) => {
147
- switch (index) {
148
- case 0:
149
- this.app.navigateTo("appManager")
150
- break
151
- case 1:
152
- this.app.navigateTo("containerControl")
153
- break
154
- case 2:
155
- this.app.navigateTo("advancedSettings")
156
- break
157
- case 3: {
158
- // API Key Extractor
159
- this.menu.blur()
160
- this.page.visible = false
161
- const viewer = new ApiKeyViewer(this.renderer as CliRenderer, this.config, () => {
162
- // On Back
163
- this.page.visible = true
164
- this.menu.focus()
165
- })
166
- this.container.add(viewer)
167
- break
168
- }
169
- case 4: {
170
- // Configure Apps
171
- this.menu.blur()
172
- this.page.visible = false
173
- const configurator = new AppConfigurator(this.renderer as CliRenderer, this.config, () => {
174
- this.page.visible = true
175
- this.menu.focus()
176
- })
177
- this.container.add(configurator)
178
- break
179
- }
180
- case 5: {
181
- // TRaSH Profile Setup
182
- this.menu.blur()
183
- this.page.visible = false
184
- const trashSetup = new TRaSHProfileSetup(this.renderer as CliRenderer, this.config, () => {
185
- this.page.visible = true
186
- this.menu.focus()
187
- })
188
- this.container.add(trashSetup)
189
- break
190
- }
191
- case 6: {
192
- // Regenerate compose
193
- await saveCompose(this.config)
194
- break
195
- }
196
- case 7: {
197
- // Prowlarr Setup
198
- this.menu.blur()
199
- this.page.visible = false
200
- const prowlarrSetup = new ProwlarrSetup(this.renderer as CliRenderer, this.config, () => {
201
- this.page.visible = true
202
- this.menu.focus()
203
- })
204
- this.container.add(prowlarrSetup)
205
- break
206
- }
207
- case 8: {
208
- // qBittorrent Setup
209
- this.menu.blur()
210
- this.page.visible = false
211
- const qbSetup = new QBittorrentSetup(this.renderer as CliRenderer, this.config, () => {
212
- this.page.visible = true
213
- this.menu.focus()
214
- })
215
- this.container.add(qbSetup)
216
- break
217
- }
218
- case 9: {
219
- // Full Auto Setup
220
- this.menu.blur()
221
- this.page.visible = false
222
- const autoSetup = new FullAutoSetup(this.renderer as CliRenderer, this.config, () => {
223
- this.page.visible = true
224
- this.menu.focus()
225
- })
226
- this.container.add(autoSetup)
227
- break
228
- }
229
- case 10: {
230
- // Monitor Dashboard
231
- this.menu.blur()
232
- this.page.visible = false
233
- const monitor = new MonitorDashboard(this.renderer as CliRenderer, this.config, () => {
234
- this.page.visible = true
235
- this.menu.focus()
236
- })
237
- this.container.add(monitor)
238
- break
239
- }
240
- case 11: {
241
- // Homepage Setup
242
- this.menu.blur()
243
- this.page.visible = false
244
- const homepageSetup = new HomepageSetup(this.renderer as CliRenderer, this.config, () => {
245
- this.page.visible = true
246
- this.menu.focus()
247
- })
248
- this.container.add(homepageSetup)
249
- break
250
- }
251
- case 12: {
252
- // Jellyfin Setup
253
- this.menu.blur()
254
- this.page.visible = false
255
- const jellyfinSetup = new JellyfinSetup(this.renderer as CliRenderer, this.config, () => {
256
- this.page.visible = true
257
- this.menu.focus()
258
- })
259
- this.container.add(jellyfinSetup)
260
- break
261
- }
262
- case 13:
263
- process.exit(0)
264
- break
218
+ const item = this.menuItems[index]
219
+ if (item) {
220
+ await item.action()
265
221
  }
266
222
  })
267
223