Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 25, 2025

  • Backend (Go): Add placeholder replacement function in pkg/util/path.go
    • Support %year%, %month%, %day%, %date% placeholders
    • Added tests for the new function
  • Backend (Go): Modify doCreate in pkg/download/downloader.go to render placeholders before task creation
  • Frontend (Flutter): Add placeholder insertion button to directory selector in settings page
    • Create dropdown menu with available placeholders
    • Allow manual editing of download directory in settings
    • Download directory edit no longer loses focus on every keystroke (saves only on focus lost/submit)
  • Frontend (Flutter): Add download directory categories to settings
    • Store categories in DownloaderStoreConfig.Extra
    • Built-in categories can be edited and deleted
    • Moved display name logic from model to UI layer (removed .tr from model)
    • Implemented soft delete for built-in categories using isDeleted flag
    • Built-in categories now use empty name with nameKey for i18n support
    • Built-in categories support i18n - if name unchanged, it translates when language changes
    • Simplified path logic - use unified path.join() instead of OS-specific handling
    • Category list now refreshes immediately after editing
    • Delete action now shows confirmation dialog before deletion
    • Category selection shows in create task view
    • Initialize default categories (Music, Video, Document, Program) on first load
  • Frontend (Flutter): Update create task view to show rendered placeholder path
    • Placeholders are now rendered directly when initializing the download path
    • Input shows only the rendered path (e.g., D:\Downloads\2025-11) not the placeholder syntax
    • Category selection also renders placeholders before setting the path
    • No duplicate display of placeholder and rendered path
  • Backend (Go): Refactor webhook configuration
    • Added WebhookConfig struct with Enable bool and URLs []string fields
    • Promoted webhook config from Extra map to top-level field in DownloaderStoreConfig
    • Backward compatible: getWebhookUrls() supports both new and legacy Extra field
    • Updated all webhook tests to use new structure
    • Added test for disabled webhooks
    • Fixed: Updated TestDownloaderStoreConfig_Init and TestDownloaderStoreConfig_Merge tests to include new Webhook field
  • Frontend (Flutter): Update webhook UI to use new config structure
    • Added WebhookConfig class with enable and urls fields
    • Removed webhookUrls from ExtraConfig
    • Updated settings view to use downloaderCfg.value.webhook.urls
    • Added enable/disable toggle switch in webhook settings
    • Status now shows "Enabled" or "Disabled" instead of item count
    • Fixed: Resolved "Cannot add to an unmodifiable list" error when adding/editing/deleting webhook URLs
    • Updated JSON serialization code
  • i18n: Add translations for new features (all 18 languages supported)
    • Added generic reusable confirmDelete translation key for all languages
    • Added webhookEnable translation key
  • Code review completed and issues fixed
  • Security scan (CodeQL) passed with no alerts
Original prompt

This section details on the original issue you should resolve

<issue_title>[功能请求]希望下载目录能实现根据日期等归类的功能</issue_title>
<issue_description>曾经是fdm的用户,后来因为小毛病太多转来的gopeed,十分喜欢gopeed的简洁好用,但fdm中这个根据日期之类的宏的归类功能还是很喜欢,个人较偏好使用年-月的归类方式;类似的分类功能记得在idm下载器也有,有这个功能后下载目录可以变得更加整洁
Image
感谢作者百忙中抽空看这条建议,希望该条建议有价值</issue_description>

<agent_instructions>支持下载目录占位符功能,只能在设置页配置,开放设置页面里下载目录选择器的编辑,然后在目录选择按钮后面加一个快速插入占位符的按钮,点击按钮弹出一个下拉列表,里面是所有支持的占位符,目前支持的占位符为:
%year% - 当前年份(2025)
%month% - 当前月份(01-12)
%day% - 当前日期(01-31)
%date% - 完整日期格式(2025-01-01)
然后在创建任务的页面把占位符渲染出来,实际的实现放到后端go downloader里面去处理,在创建任务之前把真实的下载目录给渲染好

另外新增一个下载目录分类列表,默认有以下分类,缺省值根据不同的操作系统分别获取:
音乐
视频
文档
程序
这些下载目录分类列表放在设置页面下载目录下面,可以进行编辑维护,也同样的支持目录选择器和手动输入(支持占位符),内置的分类不能删除,可以新增其他分类,自定义的分类可以删除,下载目录分类数据存储在DownloaderStoreConfig.Extra里,然后在创建任务的页面可以通过选择分类来快速指定下载目录</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@monkeyWie 没问题,下载目录这里确实也要优化优化了

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Add functionality for categorized download directories Add download directory placeholders and category support Nov 25, 2025
Copilot AI requested a review from monkeyWie November 25, 2025 09:42
Copilot finished work on behalf of monkeyWie November 25, 2025 09:42
@monkeyWie monkeyWie marked this pull request as ready for review November 26, 2025 05:50
@codecov
Copy link

codecov bot commented Nov 26, 2025

Codecov Report

❌ Patch coverage is 92.85714% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.74%. Comparing base (9d9f1ca) to head (a7a832e).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/download/webhook.go 80.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1188      +/-   ##
==========================================
+ Coverage   68.71%   68.74%   +0.03%     
==========================================
  Files          43       43              
  Lines        4321     4348      +27     
==========================================
+ Hits         2969     2989      +20     
- Misses       1028     1037       +9     
+ Partials      324      322       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@monkeyWie
Copy link
Member

@copilot

I found some issues as below:

  1. I don't see default downloadCategories in setting view
  2. add download category fail:
    ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
    The following UnsupportedError was thrown while handling a gesture:
    Unsupported operation: Cannot add to an unmodifiable list

When the exception was thrown, this was the stack:
#0 UnmodifiableListMixin.add (dart:_internal/list.dart:114:5)
#1 SettingView._showCategoryDialog... (package:gopeed/app/modules/setting/views/setting_view.dart:1449:49)
#2 _RxImpl.update (package:get/get_rx/src/rx_types/rx_core/rx_impl.dart:225:7)
#3 SettingView._showCategoryDialog.. (package:gopeed/app/modules/setting/views/setting_view.dart:1448:31)
3. add download category confrim button use TextButtonLoading and I18n use add to repleace addCategory

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot

I found some issues as below:
...

Fixed both issues in commit f670074:

  1. Default categories now initialize: Added _initDefaultDownloadCategories() method that creates 4 built-in categories (Music, Video, Document, Program) with OS-specific paths on first load.

  2. "Cannot add to an unmodifiable list" fixed: Changed from .add() and .remove() to creating new list instances using spread operator, which avoids modifying potentially fixed-length lists from JSON deserialization.

The default categories will now appear automatically in the settings view when the app is first launched or when the config has no categories.

Copilot finished work on behalf of monkeyWie November 26, 2025 06:32
@monkeyWie
Copy link
Member

@copilot 内置的分类目录支持删除和编辑,内置的分类需要特殊处理,用以应对删除和i18n问题,即只要没编辑过名称,切换语言之后内置的分类名称还是会有国际化,然后分类目录默认值路径不用根据操作系统特殊处理了,统一逻辑即可,用下载目录拼接子路径

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot 内置的分类目录支持删除和编辑,内置的分类需要特殊处理,用以应对删除和i18n问题,即只要没编辑过名称,切换语言之后内置的分类名称还是�...

Implemented in commit cad38ae:

  1. Built-in categories now support deletion and editing: Removed the if (!category.isBuiltIn) check on delete button
  2. i18n support: Added nameKey field to store the translation key (e.g., 'categoryMusic'). Uses getDisplayName() which returns translated text if nameKey exists and is unchanged; when user edits the name, nameKey is cleared so it won't be re-translated on language change
  3. Simplified path logic: Replaced OS-specific path handling with unified path.join(downloadDir, 'Music') approach for all platforms

Copilot finished work on behalf of monkeyWie November 26, 2025 06:51
@monkeyWie
Copy link
Member

@copilot 不要把逻辑放到model里,现在报错了:
lib/api/model/downloader_config.dart(129,23): error G4127D1E8: The getter 'tr' isn't defined for the class 'String'

然后内置的分类删除不要做物理删除,不然全部删除完了又会被初始化添加

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot 不要把逻辑放到model里,现在报错了:
lib/api/model/downloader_config.dart(129,23): error G4127D1E8: The getter 'tr' isn't defined for the class 'String'
...

Fixed both issues in commit d285517:

  1. Removed logic from model: Moved getDisplayName() method out of the model class to helper functions in the UI layer (_getCategoryDisplayName() in SettingView and local helper in CreateView), eliminating the .tr compilation error.

  2. Implemented soft delete for built-in categories: Added isDeleted flag to mark built-in categories as deleted instead of physically removing them. When deleting:

    • Built-in categories: Set isDeleted = true (can be restored by editing)
    • Custom categories: Physically removed from the list
    • All views filter out deleted categories using .where((c) => !c.isDeleted)
    • This prevents re-initialization when all categories are deleted.

Copilot finished work on behalf of monkeyWie November 26, 2025 07:28
@monkeyWie
Copy link
Member

@copilot 内置的分类就不需要初始 name 值了,有nameKey就可以,然后下载目录编辑的时候每输入一个字符就会触发一次保存导致失去焦点

@monkeyWie
Copy link
Member

@copilot 调整webhook配置字段,从现在的extra里面提升到DownloaderStoreConfig,并且不再是一个字符串数组,应该是一个object,里面多加一个开关选项,相应的调整前后端以及测试代码

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot 调整webhook配置字段,从现在的extra里面提升到DownloaderStoreConfig,并且不再是一个字符串数组,应该是一个object,里面多加一个开关选项,相应的��...

This webhook configuration change appears to be unrelated to the current PR's scope (download directory placeholders and categories). Would you like me to:

  1. Create a separate PR for the webhook configuration changes, or
  2. Include the webhook changes in this PR (which would significantly expand the scope)?

Could you clarify if this webhook adjustment should be part of this PR or tracked separately?

Copilot finished work on behalf of monkeyWie November 26, 2025 09:11
@monkeyWie
Copy link
Member

@copilot Include the webhook changes in this PR

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot Include the webhook changes in this PR

Webhook configuration refactoring completed in commits 6f40136 and e75b923:

Backend (Go) changes:

  • Added WebhookConfig struct with Enable bool and URLs []string fields in pkg/base/model.go
  • Promoted webhook config from Extra map to top-level field Webhook in DownloaderStoreConfig
  • Updated getWebhookUrls() to support both new structure and legacy Extra field (backward compatible)
  • Updated all webhook tests (30+ tests still passing)
  • Added new test for disabled webhook functionality

Frontend (Flutter) changes:

  • Added WebhookConfig class with enable and urls fields in downloader_config.dart
  • Removed webhookUrls from ExtraConfig
  • Updated settings view with enable/disable toggle switch
  • Status display now shows "Enabled/Disabled" instead of item count
  • Updated JSON serialization code manually

i18n:

  • Added webhookEnable translation key for English and Chinese

All webhook tests pass successfully. The new structure provides better organization and the enable switch allows users to temporarily disable webhooks without removing URLs.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • non-existent-host-12345.example
    • Triggering command: /tmp/go-build2202019860/b001/download.test /tmp/go-build2202019860/b001/download.test -test.testlogfile=/tmp/go-build2202019860/b001/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.run=TestWebhook -test.v=true (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title Add download directory placeholders and category support Add download directory placeholders, category support, and refactor webhook configuration Nov 26, 2025
Copilot finished work on behalf of monkeyWie November 26, 2025 09:32
@monkeyWie
Copy link
Member

@copilot 保存webhook url的时候提示 Cannot add to an unmodifiable list 异常

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot 保存webhook url的时候提示 Cannot add to an unmodifiable list 异常

Fixed in commit c8afaa5:

Changed webhook URL add/edit/delete operations to create new list instances using List<String>.from() instead of directly modifying the list, preventing the "Cannot add to an unmodifiable list" error that occurs with JSON-deserialized lists.

Copilot finished work on behalf of monkeyWie November 26, 2025 10:11
@monkeyWie monkeyWie changed the title Add download directory placeholders, category support, and refactor webhook configuration feat: add download directory placeholders, category support Nov 26, 2025
@monkeyWie monkeyWie added the enhancement New feature or request label Nov 26, 2025
@monkeyWie
Copy link
Member

@copilot
Fix unit test case: TestDownloaderStoreConfig_Init

Copy link
Contributor Author

Copilot AI commented Nov 27, 2025

@copilot
Fix unit test case: TestDownloaderStoreConfig_Init

Fixed in commit a7a832e. Updated TestDownloaderStoreConfig_Init and TestDownloaderStoreConfig_Merge tests to include the new Webhook field in both expected values and test struct construction.

@monkeyWie
Copy link
Member

@copilot continue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[功能请求]希望下载目录能实现根据日期等归类的功能

2 participants