Skip to content

Add favorites and history tracking with Settings UI#1032

Merged
tisfeng merged 28 commits intodevfrom
copilot/add-favorites-and-history-tabs
Jan 26, 2026
Merged

Add favorites and history tracking with Settings UI#1032
tisfeng merged 28 commits intodevfrom
copilot/add-favorites-and-history-tabs

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Nov 19, 2025

Implements vocabulary notebook functionality: user-initiated favorites and automatic query history, both accessible via Settings tabs.

Architecture

Data Layer

  • QueryRecord: Codable model storing query text, language pair, and timestamp
  • FavoritesManager / HistoryManager: Singleton managers with UserDefaults persistence via Defaults library
  • History capped at 1,000 entries, deduplicated on insert

UI Components

  • FavoritesTab / HistoryTab: SwiftUI list views with swipe-to-delete and bulk clear
  • Click-to-requery: triggers EZWindowManager.showMainWindowIfNeeded()startQueryText()
  • Favorite button in titlebar: star icon (filled/outline) next to pin button

Integration Points

  • History tracking: injected into EZBaseQueryViewController.queryAllSerives: after query execution
  • Favorite toggle: EZTitlebar observes NSNotification.serviceHasUpdated to refresh button state
  • Exposed queryModel as readonly property on EZBaseQueryViewController for titlebar access

Example Usage

// Auto-tracking in query flow
- (void)queryAllSerives:(EZQueryModel *)queryModel {
    // ... existing query logic ...
    [HistoryManager.shared addHistoryWithQueryText:queryModel.queryText
                                      fromLanguage:queryModel.queryFromLanguage
                                        toLanguage:queryModel.queryTargetLanguage];
}

// Toggle favorite from titlebar
- (void)toggleFavorite {
    BOOL isFavorited = [FavoritesManager.shared isFavoritedWithQueryText:queryText];
    if (isFavorited) {
        [FavoritesManager.shared removeFavoriteWithId:record.id];
    } else {
        [FavoritesManager.shared addFavoriteWithQueryText:queryText ...];
    }
}

Localized for en, zh-Hans, zh-Hant. All new files added to Xcode project configuration.

Original prompt

This section details on the original issue you should resolve

<issue_title>🚀 功能建议:建议新增类似生词本的功能</issue_title>
<issue_description>### 请先确认以下事项

  • 已仔细阅读了 README
  • issues 页面搜索过,未发现类似功能建议
  • Easydict 已升级到最新版本

功能描述

在查词界面上加一个收藏按钮,类似有道词典;可以在统一的地方查看生词详情列表;

使用场景(可选)

No response

实现方案(可选)

No response</issue_description>

<agent_instructions>请根据 issue 内容,使用 swift 实现查询文本的收藏夹和历史记录功能。
在设置页面添加收藏夹和历史记录 tab

每次执行查询词操作时,我们都会记录该词,即历史记录列表。
如果用户点击右上角的“新建收藏”按钮,我们会将该词添加到收藏列表中。</agent_instructions>

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

@tisfeng 可以,感谢反馈,稍后会添加这个功能的。 @tisfeng 收到,记下了。 @tisfeng 暂时没有,要等设置页重构 https://github.com//issues/227#issuecomment-1849027631 完成后,再来看这个。 @tisfeng Currently, the new settings page is almost completed, and some related features can be done.

We can add a favorites button in the top right corner, and add a favorites and history Tab to the settings.

If you are interested in this feature, you can try to push this issue, PR is always welcome 🤗</comment_new>
<comment_new>@tisfeng
For now, we can start by only supporting the Favorite/History feature, and Eudic can be put into another issue.

Favorite and History are very similar, we can use a simple way to do it, only record the information of the query word, such as word, queryFromLanguage, timestamp, etc., and don't record the result of the query for the time being.

Each time we perform a query word action, we record the word, which is the History list.
If the user clicks on the New Favorite button in the upper right corner, we add the word to the Favorite list.</comment_new>
<comment_new>@tisfeng
I previously added Realm package, you can use it to store favorite words.

Of course, if you have other better solutions, that's fine too.</comment_new>
<comment_new>@tisfeng
单词本:手动添加才会记录。
历史记录:每个查询都会被记录。

@yam-liu 你好,请问有在做这个功能吗</comment_new>
<comment_new>@tisfeng
我也在使用 eudic,对于支持 eudic,将收藏的单词同步到 eudic 这部分没问题。

但考虑到不是所有用户都使用欧路词典,所以 Easydict 本身还是应该实现一个自己的单词记录模块(单词本和历史记录),将单词本同步到 eudic 可以是一个额外功能。</comment_new>
<comment_new>@tisfeng
最近计划使用 SwiftUI 重写查询窗口 #551 ,考虑到 SwiftUI 可能会改动许多数据存储结构,因此单词本功能需要等重写完成后。</comment_new>
<comment_new>@tisfeng

单词本什么时候上呢,需不需要帮忙

需要的,非常需要,如果会一些 Swift,可以来帮忙。

最近我在尝试重写 AppleService 服务 #921 ,其他开发者在冬眠,顾不上这里。

我之前曾想用 Swift 重写 EZQueryService 和 EZQueryModel,但后面发现牵扯太多了。

如果想要做这个功能,可以单独写一个有关单词记录的数据存储模块,不用太顾及当前的代码,这样会更方便快捷。</comment_new>
<comment_new>@tisfeng
我最近工作比较忙,其他开发者也没有活跃,没有空来处理 🥺</comment_new>


✨ 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 and others added 4 commits November 19, 2025 16:26
Co-authored-by: tisfeng <25194972+tisfeng@users.noreply.github.com>
Co-authored-by: tisfeng <25194972+tisfeng@users.noreply.github.com>
Co-authored-by: tisfeng <25194972+tisfeng@users.noreply.github.com>
Co-authored-by: tisfeng <25194972+tisfeng@users.noreply.github.com>
Copilot AI changed the title [WIP] Add favorites and history functionality to query interface Add favorites and history tracking with Settings UI Nov 19, 2025
Copilot AI requested a review from tisfeng November 19, 2025 16:36
This commit applies formatting and code organization improvements across multiple files:
- QueryRecord.swift: Reorder methods (equality operator before hash)
- HistoryManager.swift: Move maxHistoryCount declaration to the end
- FavoritesTab.swift: Add MARK comments for Internal and Private sections

These changes improve code readability and follow Swift style conventions without altering functionality.
This commit fixes build configuration errors by adding the missing TTSServiceType.swift file references to the Xcode project file (project.pbxproj). The file was created but not properly registered in the build phases, causing compilation issues.

Changes include:
- Add TTSServiceType.swift to Sources build phase
- Add corresponding file reference definitions

This resolves the file reference error and allows the project to build successfully.
This commit fixes compilation errors across multiple files and adds localization support:
- Fix type mismatches and property errors in FavoritesManager, HistoryManager, and FavoritesTab
- Add comprehensive localization strings for favorites/history features (English, Simplified Chinese, Traditional Chinese)
- Add language extension utilities to handle string formatting
- Update Objective-C code in EZTitlebar for compatibility
- Clean up unnecessary build configuration entries

These changes resolve build failures and enable proper localization for the new favorites and history features.
Replace the standalone favorite button in the titlebar with a menu item
in the quick action menu. This improves UI organization by consolidating
related actions into a single menu, reducing visual clutter while
maintaining the same functionality.

Changes:
- Remove favoriteButton property and UI element from titlebar
- Remove updateFavoriteButton method and related constraints
- Remove favorite button initialization and notification observer
- Update localization strings for menu item context
Consolidate the separate history tab into the favorites tab to simplify
the settings UI. This reduces the number of tabs while keeping both
favorites and history management in a single, unified interface.

Changes:
- Delete HistoryTab.swift component
- Expand FavoritesTab to include history display and management
- Update SettingView tab configuration to remove history tab
- Remove HistoryTab project references from pbxproj
…splay

Simplify the favorites tab by removing the clear/delete all button and
enhancing the timestamp display styling. This reduces unnecessary UI
complexity while improving the visual presentation of item timestamps.

Changes:
- Remove clear button and associated localization strings
- Enhance timestamp display formatting and styling
- Refactor FavoritesTab layout for improved clarity
- Update SettingView configuration
Fix the favorites tab to use the word selection window (rather than
opening a new query window) when clicking on favorite items. This provides
a consistent and efficient lookup experience aligned with the app's
primary interaction pattern.

Changes:
- Update favorites item tap action to use word selection window
- Simplify FavoritesTab query logic
- Refactor SettingView integration
… padding

This commit improves the visual consistency and layout of the FavoritesTab view by replacing manual frame sizing with the reusable `borderedCard()` modifier and adding consistent padding.

Changes:
- FavoritesTab.swift: Replace .frame(maxWidth, maxHeight) with .borderedCard() and .padding(20)
- project.pbxproj: Reorder file reference in build project (cleanup)

This change ensures the Favorites tab follows the same styling pattern as other tabs in the settings view, improving code consistency and maintainability.
…o unified QueryRecordManager

This commit consolidates the separate `FavoritesManager` and `HistoryManager` classes into a unified `QueryRecordManager` class that manages both favorites and history operations. This reduces code duplication and improves maintainability.

Changes:
- Delete FavoritesManager.swift and HistoryManager.swift
- Create QueryRecordManager.swift with combined functionality for favorites and history management
- Update FavoritesTab.swift to use QueryRecordManager
- Update EZTitlebar.m and EZBaseQueryViewController.m to use QueryRecordManager
- Update project.pbxproj with new file references and build settings

The unified manager provides a cleaner API while maintaining backward compatibility through @objc annotations for Objective-C interoperability.
…perations

This commit refactors QueryRecordManager to introduce a unified API for managing both favorites and history records. The changes introduce a `RecordType` enum and deduplication policies to eliminate code duplication and improve flexibility.

Changes:
- Add RecordType enum with storageKey, maxCount, and deduplicationPolicy properties
- Add DeduplicationPolicy enum to handle different duplicate handling strategies
- Consolidate favorites/history methods into generic addRecord, removeRecord, getAllRecords, and clearAllRecords methods
- Replace type-specific logic with dynamic record type handling
- Update FavoritesTab.swift to use new generic API
- Update EZTitlebar.m to use containsRecord and addRecord methods
- Update EZBaseQueryViewController.m to use generic addRecord method

The refactoring maintains backward compatibility while providing a cleaner, more maintainable codebase.
This commit updates the Xcode project configuration to reflect compatibility with Xcode 16.2 (build version 16.2). The LastUpgradeCheck version is bumped from 2610 to 2620 to maintain project metadata consistency.

Changes:
- Update project.pbxproj LastUpgradeCheck from 2610 to 2620
- Update Easydict.xcscheme LastUpgradeVersion from 2610 to 2620

This ensures the project configuration is properly aligned with the latest Xcode version requirements.
@tisfeng
Copy link
Copy Markdown
Owner

tisfeng commented Jan 11, 2026

image

@tisfeng tisfeng marked this pull request as ready for review January 11, 2026 16:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a favorites and query history feature for Easydict, allowing users to bookmark translations and automatically track query history.

Changes:

  • Added data models (QueryRecord, QueryRecordManager) with UserDefaults persistence using the Defaults library
  • Implemented a unified FavoritesTab UI with segmented control for viewing favorites and history
  • Integrated automatic history tracking into the query flow and added manual favorite functionality via quick action menu

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
QueryRecord.swift New Codable model for storing query text, language pair, and timestamp
QueryRecordManager.swift Singleton manager handling CRUD operations with deduplication and history capping at 1,000 entries
Language+Extension.swift Added Codable conformance to Language type for QueryRecord serialization
Defaults.Keys+Extension.swift Added storage keys for favorites and query history arrays
FavoritesTab.swift SwiftUI view with segmented control for favorites/history, swipe-to-delete, and click-to-requery
SettingView.swift Added favorites tab to settings with 640px height configuration
EZBaseQueryViewController.m Integrated automatic history recording after query execution
EZBaseQueryViewController.h Exposed queryModel as readonly property for titlebar access
EZTitlebar.m Added "Add to Favorites" menu item to quick action menu
Localizable.xcstrings Added localized strings for favorites/history UI (en, zh-Hans, zh-Hant)
project.pbxproj Added new Swift files to Xcode project build configuration
Easydict.xcscheme Updated Xcode version to 2620

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@phlpsong
Copy link
Copy Markdown
Collaborator

image

Could we have the delete function for these records? Maybe add a fav icon button in list item will also allow user to change status quickly.

@purifier1990
Copy link
Copy Markdown
Contributor

LGTM

@tisfeng
Copy link
Copy Markdown
Owner

tisfeng commented Jan 23, 2026

image

Could we have the delete function for these records? Maybe add a fav icon button in list item will also allow user to change status quickly.

ok, i will add it

@tisfeng
Copy link
Copy Markdown
Owner

tisfeng commented Jan 25, 2026

Actually, I previously added a swipe action to the List for deletion, but considering this design might not be obvious, I'll add a delete button later.

image

@tisfeng
Copy link
Copy Markdown
Owner

tisfeng commented Jan 25, 2026

new UI
image

This commit redesigns the `QueryRecordRow` in the Favorites tab to improve user interaction.

Key changes:
- Replaced the tap-to-query behavior with explicit "Query" and "Delete" buttons for better usability.
- Updated the layout to a horizontal stack (`HStack`) to accommodate the new actions.
- Added necessary localization keys (`common.query`) in `Localizable.xcstrings`.
This commit introduces the ability to export saved favorites and query history records as CSV files.

Key changes:
- Added an "Export" menu in the Favorites/History tab header.
- Implemented CSV generation logic with proper escaping for special characters.
- Integrated `NSSavePanel` for a native file saving experience on macOS.
- Added necessary localization strings for the new export actions.
@tisfeng
Copy link
Copy Markdown
Owner

tisfeng commented Jan 25, 2026

add export favorites and history to CSV

image

This commit updates the `Localizable.xcstrings` file to synchronize and add new localization keys related to the favorites and history features.

Key changes:
- Added Slovak (sk) translations for multiple core and feature-specific strings.
- Updated and consolidated strings for favorites/history empty states and export actions.
- Cleaned up stale localization keys and synchronized translations across English, Chinese (Simplified/Traditional), and Slovak.
@tisfeng
Copy link
Copy Markdown
Owner

tisfeng commented Jan 25, 2026

Later, we can consider also recording the query results for easy viewing.

@tisfeng
Copy link
Copy Markdown
Owner

tisfeng commented Jan 25, 2026

pls review

@Jerry23011
Copy link
Copy Markdown
Collaborator

Jerry23011 commented Jan 25, 2026

I added localization for add_to_favorites in the quick action menu in e22961e
Screenshot 2026-01-25 at 11 29 07

Copy link
Copy Markdown
Collaborator

@Jerry23011 Jerry23011 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@tisfeng tisfeng merged commit ff59b3d into dev Jan 26, 2026
4 checks passed
@tisfeng tisfeng deleted the copilot/add-favorites-and-history-tabs branch January 26, 2026 01:44
@yusenguo2024
Copy link
Copy Markdown

Looking good! Will this be available in the next release (if so, when)?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚀 功能建议:建议新增类似生词本的功能

7 participants