Skip to main content

TrackerProvider

Trait TrackerProvider 

Source
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<(), TrackerError>> + 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 calls detect_ticket_id + fetch_ticket without 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§

Source

fn name(&self) -> &'static str

Human-readable name of the tracker (e.g. “Redmine”, “Jira”). Used for logging and UI labels.

Source

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.

Source

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.

Source

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§

Source

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.

Source

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).

Source

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).

Source

fn log_time<'life0, 'life1, 'async_trait>( &'life0 self, _ticket_id: &'life1 str, _entry: TimeEntryRequest, ) -> Pin<Box<dyn Future<Output = Result<(), TrackerError>> + 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 a TrackerError describing the failure. Default returns TrackerError::Unsupported — opt-in capability.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§