App Triggers — per-app event-driven display interrupts#39
Open
csader wants to merge 14 commits into
Open
Conversation
a6d64bc to
be10680
Compare
Full trigger developer guide including: - manifest.json trigger_conditions schema - trigger(settings, conditions) function contract - State persistence pattern between calls - BirdNET rare species example end-to-end - Triggers without conditions (ISS-style) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Backend: trigger() function loading alongside fetch() in plugin system - _plugin_triggers dict, _trigger_cooldowns, _trigger_last_check tracking - _trigger_loop() daemon thread checks every 10s, respects quiet hours - GET/POST /triggers routes; /installed_apps now includes has_trigger + trigger_conditions - Triggers page in hamburger menu with enable/disable master switch - Bell icon on app cards for trigger-capable apps (links to add trigger) - Add/edit trigger modal: name, app picker, dynamic condition fields from manifest, display duration, cooldown - Trigger list shows last fired time, enable toggle, edit/delete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sports: fires on game_start, score_change, close_game (within 5), or final. BirdNET: fires on any detection, new species today, or specific species. Stocks: fires when any ticker moves beyond a % threshold (up/down/either). Weather: fires on severe weather or temp crossing a threshold (Open-Meteo). ISS: fires when ISS ground track is within 500km of user's zip code. All manifests updated with trigger schema. Bell icon moved to left side of app tiles for visual separation from settings/remove buttons. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…38) Crypto: fires when any followed coin moves beyond a % threshold (up/down/either). YouTube: fires when a new video is posted to the followed channel. Seeds last_video_id on first run to avoid false fire on install. Countdown: fires at configurable milestones — 30d, 7d, 1d, 1h, or arrival. Uses state to fire once per milestone per target date. Moon Phase: fires on full moon or new moon (configurable). Resets state between phases so each occurrence fires once. World Clock: fires when business hours open (9am) or close (5pm) in any followed timezone. Fires once per event per day. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Metro: fires when the next train on the followed route/stop is arriving within a configurable number of minutes. Supports direction filter. Planes Overhead: fires when a new aircraft appears in the search radius. Reuses fetch() cached flight data to avoid extra API calls. Supports callsign keyword filter (e.g. UAL, N12). News Headlines: fires when a new headline containing configured keywords appears in the RSS feed. Empty keywords = any new headline. Tracks seen titles to avoid re-firing on the same story. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BTC Fear & Greed: fires when the index enters extreme fear or extreme greed territory. Configurable zone and threshold. Fires once per zone entry, resets when index leaves the zone. YT Comments: fires when a new comment appears on the followed video. Supports optional keyword filter. Seeds seen IDs on first run. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fires when elapsed time hits a round milestone: 100 days, 1 year, 2 years, 5 years, or 10 years. Fires once per milestone per event date. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sports: add overtime/extra time and playoff/postseason event types. Stocks: add price target condition (fires when ticker crosses a specific price, resets when price moves away). Condition type toggle selects between % move and price target. BirdNET: add watchlist (comma-separated species list) and high_confidence (configurable % threshold) filter options. Weather: add rain_starting (dry→rain transition), rapid_temp_change (configurable °F delta), uv_high, and wind_high conditions. Now fetches UV index and wind speed from Open-Meteo alongside temp/code. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sports: add comeback alert (was down by N, now within 3). Stocks: add 52-week high/low condition. Condition type toggle now includes pct_change, price_target, and 52w_extreme. Crypto: add price target condition (mirrors stocks pattern). Condition type toggle selects between % move and price target. YouTube: add view milestone condition (requires API key). Condition type toggle selects between new_video and view_milestone. Metro: add service alert condition (fires on DELAY, SUSPENSION, SHUTTLE, STOP_CLOSURE, DETOUR). Condition type toggle selects between arriving and alert. Planes Overhead: add military aircraft filter using common US military callsign prefixes (RCH, SPAR, SAM, VENUS, etc.). BirdNET: add busy feeder condition (N detections within M minutes). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- overhead: existing behavior (within ~500km ground track) - visible_pass: overhead + nighttime (8pm–5am local) + cloud cover ≤30% Uses Open-Meteo for cloud cover (keyless) - crew_change: fires when ISS crew roster changes (arrival or departure) Seeds on first run to avoid false fire on install Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… first_today (#38) Sports: rival matchup (fire when followed team plays a configured rival) and shutout in progress (one team has 0 after scoring begins). Stocks: market open/close condition (9:30am and 4:00pm ET on weekdays, no API needed). Condition type toggle now has 4 options. Planes Overhead: altitude threshold filter (fire only for aircraft above a configurable altitude in feet). OpenSky poll now captures altitude_m from state vector. BirdNET: first detection of the day (fires once per day on the first qualifying detection regardless of species). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- openAddTrigger() now lazily fetches installed_apps if _triggerApps
is empty (happens when called from app card before Triggers page loads)
- _saveTriggerModal() now receives button reference and uses
btn.closest('.modal-overlay') instead of querySelector which could
grab a stale/wrong overlay
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- flex-wrap:wrap so buttons flow to next row when there are many options - min-width:0 and white-space:normal so buttons shrink and wrap text - Slightly smaller font (.75rem) for dense option sets like BirdNET Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Modal now uses width:max-content with min 320px and max 600px (or 90vw), so it expands to fit wide toggle sets like BirdNET without overflow. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
13 trigger-capable apps
Test plan
🤖 Generated with Claude Code