Skip to content

supermem613/ComingUpNext

Repository files navigation

ComingUpNext Tray

A lightweight Windows 11 tray application that displays your next upcoming meeting from a public calendar ICS (.ics) feed.

It shows a dynamic tooltip with the next meeting title and time, and notifies you when the meeting is about to start. Optionally, it shows a hover/preview window with more details.

Screenshots

System tray + tooltip

System tray showing the dynamic tooltip for the next meeting

Context menu (right‑click)

Context menu with Open Meeting, Refresh, Set Calendar URL, Exit

Hover/preview window

Hover window showing upcoming meeting details and quick actions

Features

  • Tray icon with dynamic tooltip showing: Next: <Title> (In X min|In Y h|Mon HH:mm)
  • Auto balloon notification when a meeting is within 15 minutes (once per meeting)
  • Context menu: Open Meeting, Refresh, Set Calendar URL, Exit
  • Stores configuration in %APPDATA%/ComingUpNext/config.json
  • Lightweight ICS parsing (skips malformed events)
  • Configurable refresh interval (default 5 minutes) via RefreshMinutes in config.json or "Set Refresh Minutes" context menu option
  • Sound Intro: Optional MP3 announcement that plays before a meeting, timed to end exactly when the meeting starts. Configure via Settings or SoundIntroPath in config.json. Use "Test Sound Intro" from the context menu to verify playback. Playback is automatically suppressed when a microphone is actively in use (e.g. during a Teams or Zoom call) so it won't interrupt ongoing conversations.

ICS Format Expectations

Provide a publicly accessible .ics URL (can be from Outlook, Google Calendar, etc.). The app reads VEVENT blocks and uses:

  • SUMMARY → Meeting title
  • DTSTART → Start time (all-day events treated as midnight local)
  • DTEND → End time (if missing/invalid defaults to +1 hour)
  • URL → Meeting link (if present)
  • DESCRIPTION → Fallback scan for first http/https link if URL absent (helpful for Teams links embedded in description)

Example snippet:

BEGIN:VEVENT
SUMMARY:Daily Standup
DTSTART:20251030T090000Z
DTEND:20251030T091500Z
URL:https://teams.microsoft.com/l/meetup-join/...
END:VEVENT

Timezone & recurrence handling:

  • TZID= parameters on DTSTART/DTEND are respected (converted from that zone to local).
  • UTC times (Z suffix) converted to local.
  • Floating times (no TZ) treated as local.
  • Date-only values (YYYYMMDD) treated as all-day starting at local midnight.
  • Simple weekly RRULE patterns (e.g. FREQ=WEEKLY;BYDAY=MO,WE;INTERVAL=1;UNTIL=20261102T160000Z) are expanded for upcoming occurrences (up to 3 months lookahead or UNTIL limit) including exclusions via matching EXDATE.
  • EXDATE entries remove specific occurrences from recurrence expansion.

Limitations: Advanced recurrence (monthly rules, BYSETPOS, COUNT, exceptions with time shifts) is not yet supported.

Build & Run

Requires .NET 9 SDK.

# Build
dotnet build

# Run (from project directory)
cd src/ComingUpNextTray
dotnet run

On first run, use the tray icon context menu "Set Calendar URL" to paste the ICS URL. Optionally adjust the refresh interval with "Set Refresh Minutes" (1-1440). The default is 5 minutes. You can force an immediate reload at any time with the "Refresh" context menu item (it disables while fetching to avoid overlapping requests).

Packaging

Produce a single-file self-contained executable:

dotnet publish src/ComingUpNextTray/ComingUpNextTray.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeAllContentForSelfExtract=true -o publish

The output folder publish will contain the EXE. Version metadata (AssemblyVersion/FileVersion/Product Version) is taken from the <Version> property inside ComingUpNextTray.csproj.

MSI Installer (WiX v5)

An example WiX v5 setup is provided under installer/.

Prerequisites:

  • .NET 10 SDK
  • WiX Toolset v5 (installed automatically by the build script if missing)

Build the MSI (auto-reads <Version> from the csproj):

cd installer
./build.ps1 -Configuration Release -Runtime win-x64

Result: installer/ComingUpNextTray-X.Y.Z.msi where X.Y.Z is the version from the project file.

To override the version just for a build (without editing the csproj), pass -Version:

./build.ps1 -Configuration Release -Runtime win-x64 -Version 1.2.3

This stamps the EXE (assembly/file/product) and the MSI Package version consistently.

Adjustments:

  • Update GUID placeholders in installer/Product.wxs (generate new GUIDs via New-Guid).
  • Change Manufacturer, Version, or add more components (e.g., config file defaults).
  • To auto-start for current user you can add a shortcut component pointing to Startup folder or set Run key (advanced customization).

Silent install example:

msiexec /i ComingUpNextTray-1.0.0.msi /qn

Uninstall:

msiexec /x ComingUpNextTray-1.0.0.msi /qn

If you modify published output location or add resources, re-run the build script to regenerate harvested components.

Tools

This repository includes two small CLI tools under the tools/ folder useful for debugging and reproducing the app's behavior against .ics feeds.

  • CalendarInspector (tools/CalendarInspector)

    • Purpose: Download or read an ICS payload and print diagnostic information including raw VEVENT blocks, parsed entries and a recurrence expansion log. Useful to inspect what the parser actually sees and how recurrences expand.
    • Usage (download a URL or read a file):
       # URL (will attempt to GET the feed)
       dotnet run --project "tools\CalendarInspector\CalendarInspector.csproj" "https://example.com/calendar.ics"
      
       # Local file
       dotnet run --project "tools\CalendarInspector\CalendarInspector.csproj" "C:\path\to\calendar.ics"
    • Notes: The inspector prints raw VEVENT blocks and a summary of parsed entries; it does not apply the app's next-meeting selection rules (it's focused on parsing diagnostics).
  • NextMeetingInspector (tools/NextMeetingInspector)

    • Purpose: Mimics the tray application's selection logic and prints the single next meeting chosen by the app. It reuses CalendarService and NextMeetingSelector so behavior should match the running tray app closely.
    • Usage (URL-only):
       dotnet run --project "tools\NextMeetingInspector\NextMeetingInspector.csproj" "https://example.com/calendar.ics" [ignoreFreeOrFollowing:true|false]
      • The ignoreFreeOrFollowing flag is optional and defaults to true (matches the app's default behavior).
    • Notes and troubleshooting:
      • The tool expects an absolute http or https URL. It uses the same HTTP fetch logic as the tray app (conditional requests, ETag/Last-Modified handling) where applicable.
      • Some calendar providers (Exchange/Office365) may require a public/share link or authentication; if you get HTTP 401/403 or HTTP 400, verify the URL is a public ICS export link or supply an appropriate authenticated feed.
      • The tool injects a browser-like User-Agent header to improve compatibility with servers that reject non-browser clients.

Auto Start (Optional)

Create a shortcut to the published EXE in:

%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup

Configuration

Settings are stored in %APPDATA%/ComingUpNext/config.json:

Key Type Default Description
CalendarUrl string "" ICS feed URL
RefreshMinutes int 5 Refresh interval (1–1440)
ShowHoverWindow bool true Show the floating hover window
IgnoreFreeOrFollowing bool true Skip meetings marked as Free or Following
SoundIntroPath string null Path to an MP3 file played before each meeting. The app detects the MP3 duration and starts playback so it ends at the meeting start time. Leave empty to disable.
HoverWindowLeft int null Saved hover window X position
HoverWindowTop int null Saved hover window Y position

Future Improvements

  • Add Windows Toast notifications using Windows App SDK for richer UX
  • Optional filtering (e.g. ignore all-day events or past events spanning multiple days)

License

See LICENSE.

About

Windows tray app to show next meeting coming up

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors