Skip to content

Add URL matcher functionality for domain-based application selection#184

Open
lwille wants to merge 6 commits intosonnyp:mainfrom
lwille:feature/domain-matching
Open

Add URL matcher functionality for domain-based application selection#184
lwille wants to merge 6 commits intosonnyp:mainfrom
lwille:feature/domain-matching

Conversation

@lwille
Copy link

@lwille lwille commented Jul 18, 2025

Summary

This PR implements URL matcher functionality to automatically route URLs to specific applications based on user-defined regex patterns, addressing #75.

Also related to #5.

image

Key Features

  • URL Pattern Matching: Users can define regex patterns to match URLs
  • Automatic Application Selection: Matching URLs automatically open in the configured application
  • Preferences Integration: New Preferences button in welcome screen for managing URL matchers
  • GSettings Storage: URL matchers are persisted using GSettings with proper serialization
  • Libadwaita UI: Modern dialog components following GNOME design guidelines

Implementation Details

  • Added url-matchers GSettings key for storing JSON-serialized patterns
  • Implemented getUrlMatchers(), addUrlMatcher(), removeUrlMatcher() functions in util.js
  • Added findMatchingApp() for automatic URL-to-application matching
  • Enhanced window.js to check for URL matches before displaying application chooser
  • Refactored preferences action to use application-level Gio.SimpleAction

Use Cases

  • Open GitHub URLs in GitHub Desktop: https://github\.com/.*
  • Route YouTube to media player: https://youtube\.com/.*
  • Direct documentation to specific browser: https://docs\..*
  • Route work tools to work browser: .*\.company\.com/.*

Test Coverage

  • Comprehensive URL pattern matching tests
  • JSON serialization/deserialization validation
  • Edge case handling for invalid patterns

Test Plan

  • Verify Preferences button appears in welcome screen
  • Test URL matcher creation and deletion via preferences
  • Confirm automatic URL routing works for HTTP/HTTPS schemes
  • Validate pattern validation and error handling
  • Test GSettings persistence across app restarts

Fixes #75

🤖 Generated with Claude Code

@lwille lwille force-pushed the feature/domain-matching branch 4 times, most recently from 1e1d384 to e7ccb13 Compare July 18, 2025 11:33
@lwille lwille marked this pull request as ready for review July 18, 2025 11:34
@lwille lwille force-pushed the feature/domain-matching branch 2 times, most recently from 41c5de2 to 494de34 Compare July 19, 2025 11:39
- Implement regex-based URL pattern matching for automatic application selection
- Add Preferences dialog with URL matcher management interface
- Store URL matchers in GSettings with JSON serialization
- Add automatic URL routing for HTTP/HTTPS schemes in window.js
- Replace deprecated GtkShortcutsWindow with modern Adw.Dialog components
- Refactor preferences action to application-level Gio.SimpleAction
- Add comprehensive URL matcher test coverage

Fixes sonnyp#75
@sonnyp
Copy link
Owner

sonnyp commented Oct 30, 2025

Thanks, I will review this for Junction 2.0

Copy link
Owner

@sonnyp sonnyp left a comment

Choose a reason for hiding this comment

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

Merged main and fixed a couple of issues.

The matcher logic needs to be fixed, we don't use Gio.AppInfo anymore


Label {
label: _("URL Pattern (Regular Expression):");
xalign: 0;
Copy link
Owner

Choose a reason for hiding this comment

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

please remove all xalign

replace with halign

Comment on lines 22 to 25
// Add dialog responses
add_matcher_dialog.add_response("cancel", "Cancel");
add_matcher_dialog.add_response("add", "Add");
add_matcher_dialog.set_response_appearance("add", Adw.ResponseAppearance.SUGGESTED);
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
// Add dialog responses
add_matcher_dialog.add_response("cancel", "Cancel");
add_matcher_dialog.add_response("add", "Add");
add_matcher_dialog.set_response_appearance("add", Adw.ResponseAppearance.SUGGESTED);
add_matcher_dialog.add_response("cancel", "Cancel");
add_matcher_dialog.add_response("add", "Add");
add_matcher_dialog.set_response_appearance("add", Adw.ResponseAppearance.SUGGESTED);

comments shouldn't repeat what the code says

Comment on lines 23 to 24
add_matcher_dialog.add_response("cancel", "Cancel");
add_matcher_dialog.add_response("add", "Add");
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
add_matcher_dialog.add_response("cancel", "Cancel");
add_matcher_dialog.add_response("add", "Add");
add_matcher_dialog.add_response("cancel", _("Cancel"));
add_matcher_dialog.add_response("add", _("Add"));

Comment on lines 27 to 31
// Populate browser applications
populateAppDropdown();

// Load existing matchers
loadMatchers();
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
// Populate browser applications
populateAppDropdown();
// Load existing matchers
loadMatchers();
populateAppDropdown();
loadMatchers();

// Load existing matchers
loadMatchers();

// Add button handler
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
// Add button handler


if (pattern && selectedIndex !== Gtk.INVALID_LIST_POSITION) {
const appString = app_list_model.get_string(selectedIndex);
const [appId] = appString.split(" - ");
Copy link
Owner

Choose a reason for hiding this comment

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

too big of a hack

Comment on lines +101 to +107
section {
item {
label: _("Preferences");
action: "app.preferences";
}
}

Copy link
Owner

Choose a reason for hiding this comment

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

preferences should have the ctrl+, shortcut

https://developer.gnome.org/hig/reference/keyboard.html

Comment on lines +41 to +47
Button {
label: _("Preferences");
valign: center;
halign: center;
clicked => $onPreferences();
}

Copy link
Owner

Choose a reason for hiding this comment

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

This doesn't need to be so prominent in the welcome window

Please replace the top right about button with a menu that has Preferences + About

using Gtk 4.0;
using Adw 1;

Adw.PreferencesDialog preferences_window {
Copy link
Owner

Choose a reason for hiding this comment

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

please move the "Show App Names" menu entry to this Preferences dialog


const deleteButton = new Gtk.Button({
icon_name: "user-trash-symbolic",
tooltip_text: "Remove URL matcher",
Copy link
Owner

Choose a reason for hiding this comment

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

all user visible strings should be marked as translatable

Suggested change
tooltip_text: "Remove URL matcher",
tooltip_text: _("Remove URL matcher"),


Adw.AlertDialog add_matcher_dialog {
heading: _("Add URL Matcher");
body: _("Enter a regular expression pattern to match URLs and select the application to open them with.");
Copy link
Owner

Choose a reason for hiding this comment

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

UI should be self explanatory

Suggested change
body: _("Enter a regular expression pattern to match URLs and select the application to open them with.");

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.

Domain Specific Applications Possible?

2 participants