pub trait TrackerProvider: Send + Sync {
// Required methods
fn name(&self) -> &'static str;
fn detect_ticket_id(&self, title: &str, description: &str) -> Option<String>;
fn fetch_ticket<'life0, 'life1, 'async_trait>(
&'life0 self,
ticket_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Option<LinkedTicket>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn ticket_url(&self, ticket_id: &str) -> String;
// Provided methods
fn label_colors(&self) -> LabelColorMaps { ... }
fn fetch_activities<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Vec<Activity>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait { ... }
fn fetch_time_entries<'life0, 'life1, 'async_trait>(
&'life0 self,
_ticket_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Vec<TimeEntry>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn log_time<'life0, 'life1, 'async_trait>(
&'life0 self,
_ticket_id: &'life1 str,
_entry: TimeEntryRequest,
) -> Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
}Expand description
Contract that every external tracker integration must implement.
§Design
- The orchestrator holds a
Box<dyn TrackerProvider + Send + Sync>and callsdetect_ticket_id+fetch_ticketwithout knowing the concrete type. - Each implementation lives in its own crate (e.g.
gitlab-tracker-redmine). - Adding a new tracker (Jira, Trello, Linear …) only requires a new crate that implements this trait — no change to the orchestrator logic.
§Thread safety
Send + Sync is required because the provider is shared across async tasks.
Required Methods§
Sourcefn name(&self) -> &'static str
fn name(&self) -> &'static str
Human-readable name of the tracker (e.g. “Redmine”, “Jira”). Used for logging and UI labels.
Sourcefn detect_ticket_id(&self, title: &str, description: &str) -> Option<String>
fn detect_ticket_id(&self, title: &str, description: &str) -> Option<String>
Attempts to extract a ticket identifier from the MR title and/or description.
Returns the raw ticket id string (e.g. “1234”) when found, None otherwise.
Implementations should prefer the title over the description when both match.
Sourcefn fetch_ticket<'life0, 'life1, 'async_trait>(
&'life0 self,
ticket_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Option<LinkedTicket>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_ticket<'life0, 'life1, 'async_trait>(
&'life0 self,
ticket_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Option<LinkedTicket>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetches the full ticket details for the given raw ticket id.
Returns None on network error, authentication failure, or when the
ticket does not exist. The caller is responsible for caching results.
Sourcefn ticket_url(&self, ticket_id: &str) -> String
fn ticket_url(&self, ticket_id: &str) -> String
Builds the direct URL to the ticket from its id.
This is a pure helper that may be called without a network round-trip (e.g. to open the browser immediately on keypress while the fetch is pending).
Provided Methods§
Sourcefn label_colors(&self) -> LabelColorMaps
fn label_colors(&self) -> LabelColorMaps
Returns the badge colour maps for tracker-type and priority labels.
The returned strings are colour names or hex codes understood by the
orchestrator’s parse_color function ("red", "#ff6600", …).
Default implementation returns empty maps — the renderer then falls back to its hard-coded default (dark_gray background, white text). Override this in your provider to expose your config file’s colour settings.
Sourcefn fetch_activities<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Vec<Activity>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn fetch_activities<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Vec<Activity>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Fetches the list of time-tracking activity categories available in the tracker.
Called once at startup (or on first popup open) and cached in App.
Default implementation returns an empty list (opt-in capability).
Sourcefn fetch_time_entries<'life0, 'life1, 'async_trait>(
&'life0 self,
_ticket_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Vec<TimeEntry>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_time_entries<'life0, 'life1, 'async_trait>(
&'life0 self,
_ticket_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Vec<TimeEntry>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetches all time entries recorded on the given ticket.
Displayed in the Inspector’s TimeLog view. Default returns empty (opt-in).
Sourcefn log_time<'life0, 'life1, 'async_trait>(
&'life0 self,
_ticket_id: &'life1 str,
_entry: TimeEntryRequest,
) -> Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn log_time<'life0, 'life1, 'async_trait>(
&'life0 self,
_ticket_id: &'life1 str,
_entry: TimeEntryRequest,
) -> Pin<Box<dyn Future<Output = Result<(), String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Submits a new time entry on the given ticket.
Returns Ok(()) on success, or an error message string suitable for
displaying inline in the TUI. Default returns an unsupported error.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".