Skip to content

Feature: Add recent filters drop-down to the message browser#279

Open
mgaffigan wants to merge 5 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:feature/mru-filters
Open

Feature: Add recent filters drop-down to the message browser#279
mgaffigan wants to merge 5 commits into
OpenIntegrationEngine:mainfrom
mgaffigan:feature/mru-filters

Conversation

@mgaffigan

@mgaffigan mgaffigan commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Adds a recent button to the message browser pane. Allows restoration of the last 10 searches on the channel.

image image

Closes #273

@github-actions

github-actions Bot commented Mar 29, 2026

Copy link
Copy Markdown

Test Results

  112 files    216 suites   7m 2s ⏱️
  654 tests   654 ✅ 0 💤 0 ❌
1 308 runs  1 308 ✅ 0 💤 0 ❌

Results for commit d3ebbde.

♻️ This comment has been updated with latest results.

@mgaffigan mgaffigan changed the title Feature/mru filters Feature: Add recent filters drop-down to the message browser Mar 29, 2026
@mgaffigan mgaffigan force-pushed the feature/mru-filters branch from 83970d3 to 2cb78d3 Compare March 29, 2026 21:12
@mgaffigan mgaffigan requested a review from Copilot March 29, 2026 21:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a “Recent…” drop-down to the Message Browser so users can quickly re-apply the last ~10 searches per channel, backed by persisted client preferences. To support MRU de-duplication and display text, the shared MessageFilter model gains equality logic and a new criteria-oriented string formatter.

Changes:

  • Add client-side storage for per-channel recent message filters (persisted in user preferences) and a “Recent…” UI button to restore them.
  • Add applyFilter(...) plumbing to push a saved MessageFilter back into the advanced filter UI.
  • Enhance shared filter model objects with equals/hashCode and add new test coverage around equality / criteria formatting.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
server/test/com/mirth/connect/model/MessageFilterModelTest.java Adds unit tests covering MessageFilter equality, emptiness semantics, and criteria-string output.
server/src/com/mirth/connect/model/filters/elements/MetaDataSearchElement.java Implements equals/hashCode for metadata search elements (enables deep equality in filters).
server/src/com/mirth/connect/model/filters/elements/ContentSearchElement.java Implements equals/hashCode for content search elements (enables deep equality in filters).
server/src/com/mirth/connect/model/filters/MessageFilter.java Adds deep equality + isEmpty(), and introduces a criteria-style toString(Map, padding, includeEmptyCriteria) used by the client.
client/src/com/mirth/connect/client/ui/browsers/message/MessageBrowserRecentFilterStore.java New preference-backed store for MRU MessageFilter lists per channel.
client/src/com/mirth/connect/client/ui/browsers/message/MessageBrowserAdvancedFilter.java Adds applyFilter(...) to restore advanced selections from a saved MessageFilter.
client/src/com/mirth/connect/client/ui/browsers/message/MessageBrowser.java Adds “Recent…” button/menu, saves filters on search, and reuses MessageFilter.toString(...) for the criteria pane.

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

Comment thread server/src/com/mirth/connect/model/filters/MessageFilter.java
Comment thread server/src/com/mirth/connect/model/filters/MessageFilter.java Outdated
Comment thread client/src/com/mirth/connect/client/ui/browsers/message/MessageBrowser.java Outdated
Comment on lines +32 to +41
public List<MessageFilter> getRecentFilters() {
try {
String serialized = Preferences.userNodeForPackage(Mirth.class).get(prefKey, "");
if (StringUtils.isBlank(serialized)) return List.of();

return (List<MessageFilter>) ObjectXMLSerializer.getInstance().deserialize(serialized, List.class);
} catch (Exception e) {
// Fail quietly if the stored filters cannot be deserialized for any reason.
e.printStackTrace();
return List.of();

Copilot AI Mar 29, 2026

Copy link

Choose a reason for hiding this comment

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

getRecentFilters() deserializes into a raw List.class and then unchecked-casts to List<MessageFilter>. If the stored preference value is corrupted or from a different version, elements may not actually be MessageFilter instances, leading to runtime failures later (e.g., when iterating in restoreRecentFilter()). Consider validating the deserialized value/type (ensure it’s a List and that each element is a MessageFilter) before returning it, otherwise return an empty list / clear the preference key.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the first version. That's future me's problem.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

new ArrayList<>()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@kpalang, not sure what you are referring to by that.

@mgaffigan mgaffigan force-pushed the feature/mru-filters branch from 2cb78d3 to b1cefe0 Compare March 29, 2026 22:25
@mgaffigan mgaffigan marked this pull request as ready for review March 29, 2026 22:30
@mgaffigan mgaffigan requested review from a team, NicoPiel, gibson9583, jonbartels, kayyagari, kpalang, ssrowe and tonygermano and removed request for a team March 29, 2026 22:31
@NicoPiel

Copy link
Copy Markdown
Collaborator

Great feature. Will look at the code as soon as I am able to.

@jonbartels jonbartels left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pretty nice! Left two comments for improvements to property handling and maybe a simpler data structure

@pacmano1 pacmano1 self-requested a review May 26, 2026 16:02
@pacmano1

Copy link
Copy Markdown
Contributor

This feature may leave PII and PHI locally on a workstaiton. So in its current storage format, it's a no for me.

@pacmano1 pacmano1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can leave PII/PHI on local workstation. Storage format needs to be changed.

@gibson9583

Copy link
Copy Markdown
Contributor

This feature may leave PII and PHI locally on a workstaiton. So in its current storage format, it's a no for me.

agree that PII/PHI is a risk. Perhaps we should rethink how this works? While it may negate how useful this is, perhaps this is cleared on user logout? If thats the case, maybe we then dont cache by channelId but rather global so user doesnt have to build the cache on every channel.

@pacmano1

Copy link
Copy Markdown
Contributor

This feature may leave PII and PHI locally on a workstaiton. So in its current storage format, it's a no for me.

agree that PII/PHI is a risk. Perhaps we should rethink how this works? While it may negate how useful this is, perhaps this is cleared on user logout? If thats the case, maybe we then dont cache by channelId but rather global so user doesnt have to build the cache on every channel.

admin session can be terminated without logout.

@mgaffigan

Copy link
Copy Markdown
Contributor Author

@pacmano1 / @gibson9583

This feature may leave PII and PHI locally on a workstaiton. So in its current storage format, it's a no for me.

agree that PII/PHI is a risk. Perhaps we should rethink how this works? While it may negate how useful this is, perhaps this is cleared on user logout? If thats the case, maybe we then dont cache by channelId but rather global so user doesnt have to build the cache on every channel.

I agree with the concern, but think storing any text search only in memory or in preferences is likely sufficient. I'll update the PR to address the unencrypted-local-storage of text searches.

@gibson9583

Copy link
Copy Markdown
Contributor

@pacmano1 / @gibson9583

This feature may leave PII and PHI locally on a workstaiton. So in its current storage format, it's a no for me.

agree that PII/PHI is a risk. Perhaps we should rethink how this works? While it may negate how useful this is, perhaps this is cleared on user logout? If thats the case, maybe we then dont cache by channelId but rather global so user doesnt have to build the cache on every channel.

I agree with the concern, but think storing any text search only in memory or in preferences is likely sufficient. I'll update the PR to address the unencrypted-local-storage of text searches.

in-memory is good with me. It doesnt need to survive client restart. Preferences is the only issue I can see because that is stored unencrypted and available to any process on server.

@mgaffigan mgaffigan requested a review from pacmano1 May 26, 2026 17:18
@mgaffigan

Copy link
Copy Markdown
Contributor Author

@pacmano1 / @gibson9583, updated to use in-memory storage only. That's tantamount to the rest of the PHI which already resides in memory.

@kpalang kpalang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Some suggestions and nitpicks, but overall a nice implementation.

Comments formatted as conventional comments.

Comment on lines +32 to +41
public List<MessageFilter> getRecentFilters() {
try {
String serialized = Preferences.userNodeForPackage(Mirth.class).get(prefKey, "");
if (StringUtils.isBlank(serialized)) return List.of();

return (List<MessageFilter>) ObjectXMLSerializer.getInstance().deserialize(serialized, List.class);
} catch (Exception e) {
// Fail quietly if the stored filters cannot be deserialized for any reason.
e.printStackTrace();
return List.of();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

new ArrayList<>()

Comment thread server/src/com/mirth/connect/model/filters/MessageFilter.java Outdated
Comment thread server/src/com/mirth/connect/model/filters/MessageFilter.java Outdated
Comment thread server/src/com/mirth/connect/model/filters/MessageFilter.java Outdated
Comment thread server/src/com/mirth/connect/model/filters/MessageFilter.java Outdated
Comment thread server/src/com/mirth/connect/model/filters/MessageFilter.java Outdated
@mgaffigan mgaffigan requested a review from kpalang May 26, 2026 21:16
}

if (value instanceof Calendar calendar) {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

thought (non-blocking): I found this cool site with modern approaches to things in Java, and one of them is to use DateTimeFormatter instead of SimpleDateFormat.

@kpalang kpalang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved.

I found one small improvement after the previous review, but it is small and I'm not gonna request a change for this.

Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
Signed-off-by: Mitch Gaffigan <mitch.gaffigan@comcast.net>
@mgaffigan mgaffigan force-pushed the feature/mru-filters branch from c360924 to d3ebbde Compare June 30, 2026 10:17
@mgaffigan mgaffigan requested a review from a team June 30, 2026 10:17
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.

[IDEA] Recent filters drop down

7 participants