Skip to content

Commit 59fce4b

Browse files
committed
docs: update documentation and bump version to 2.3.0
- Updated README.md with v2.3 features: - Named Calendars with friendly names - Per-button calendar selection via dropdown - Configurable warning thresholds (orange/red) - Graceful calendar deletion migration - Improved Settings UI documentation - Updated Features section with new capabilities - Updated Configuration section with Global/Per-Button settings - Updated Changelog with detailed v2.3.0 changes - Updated copilot-instructions.md with new patterns - Bumped version to 2.3.0 in package.json, manifest.json, src/manifest.json
1 parent cb996bb commit 59fce4b

File tree

5 files changed

+83
-32
lines changed

5 files changed

+83
-32
lines changed

.github/copilot-instructions.md

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,31 +73,55 @@ PI uses WebSocket, not direct imports. Settings flow:
7373

7474
### Per-Action Settings (v2.3.0)
7575

76-
Each button can have its own calendar via `ActionSettings`:
76+
Each button can select a calendar via `ActionSettings`:
7777

7878
```typescript
7979
interface ActionSettings {
80-
useCustomCalendar?: boolean; // false = use global
80+
calendarId?: string; // ID of named calendar to use (new in v2.3)
81+
// Legacy fields (kept for backwards compatibility)
82+
useCustomCalendar?: boolean;
8183
customUrl?: string;
82-
customLabel?: string; // For PI organization only
84+
customLabel?: string;
8385
customTimeWindow?: 1 | 3 | 5 | 7;
8486
customExcludeAllDay?: boolean;
8587
}
8688
```
8789

90+
**Named Calendars** in GlobalSettings:
91+
```typescript
92+
interface NamedCalendar {
93+
id: string; // Unique ID (e.g., "cal_abc123")
94+
name: string; // User-friendly name (e.g., "Work")
95+
url: string; // iCal URL
96+
timeWindow?: number; // Optional override (1, 3, 5, or 7 days)
97+
excludeAllDay?: boolean;
98+
}
99+
100+
interface GlobalSettings {
101+
calendars?: NamedCalendar[];
102+
defaultCalendarId?: string;
103+
orangeThreshold?: number; // Seconds for orange warning (default: 300 = 5 min)
104+
redThreshold?: number; // Seconds for red warning (default: 30)
105+
// ... other settings
106+
}
107+
```
108+
88109
**CalendarManager** handles multi-calendar support:
89110
- Calendars are deduplicated by URL (same URL = shared cache)
90111
- Reference counting for automatic cleanup
91112
- Each action registers via `calendarManager.registerAction(actionId, url, ...)`
92113

93114
**BaseAction** provides:
94115
- `buttonStates: Map<string, ButtonState>` - Per-button state storage
116+
- `buttonSettings: Map<string, ActionSettings>` - Per-button settings for migration
95117
- `getEventsForButton(actionId)` - Returns events from the button's registered calendar
96118
- `getCacheStatusForButton(actionId)` - Returns status of the button's calendar
97119
- `startTimerForButton(actionId, action)` - Starts update timer for a specific button
98120
- `stopTimerForButton(actionId)` - Stops timer for a specific button
99121
- `setImage(actionId, action, imageName)` - Sets image for a specific button
100122
- `onDidReceiveSettings()` - Handles settings changes, re-registers calendar
123+
- `migrateButtonsWithDeletedCalendar(validIds)` - Migrates buttons when calendar deleted
124+
- `getRedZone()` / `getOrangeZone()` - Get configurable warning thresholds
101125

102126
## Build System
103127

@@ -234,15 +258,16 @@ const flashEnabled = settings.flashOnMeetingStart === true;
234258
| Outlook times wrong | Windows timezone not mapped | Check `timezone-service.ts` mapping |
235259
| Buttons stuck on "Loading" | Startup race condition | `waitForCacheAndStart` uses 500ms polling with `actionRef` fallback |
236260
| Title shows for too long | Duration multiplied twice | `getTitleDisplayDuration()` returns seconds, caller multiplies by 1000 |
237-
| Custom calendar not loading | Missing action ID | Ensure `onWillAppear` sets `this.actionId = ev.action.id` |
261+
| Calendar not loading | Named calendars not set up | Ensure at least one calendar is configured in Settings |
262+
| Button using deleted calendar | Calendar was removed | Buttons auto-migrate to default via `migrateDeletedCalendars()` |
238263
| Settings not persisting | Using wrong settings event | Global = `setGlobalSettings`, Per-action = `setSettings` |
239264

240265
## File Locations
241266

242267
- **Actions**: `src/actions/` - Extend `BaseAction`
243268
- **Services**: `src/services/` - Business logic (`calendar-manager.ts` for multi-calendar)
244-
- **Types**: `src/types/index.ts` - All interfaces (`ActionSettings`, `CalendarInstance`)
245-
- **PI HTML**: `pi/setup.html` - Settings popup (includes custom calendar section)
269+
- **Types**: `src/types/index.ts` - All interfaces (`ActionSettings`, `NamedCalendar`, `CalendarInstance`)
270+
- **PI HTML**: `pi/setup.html` - Settings popup (Named Calendars management)
246271
- **PI JS**: `pi/setup.js` - Settings logic (not TypeScript)
247272
- **Tests**: `tests/` - Vitest test files
248273

README.md

Lines changed: 49 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ This plugin is available on the Stream Deck store, you can also download [the la
88

99
## ✨ New in v2.3
1010

11-
-**Multiple Calendars Support**: Use different calendars on different buttons! (#5)
12-
- Enable "Use custom calendar" in the button settings
13-
- Configure separate URL, time window, and all-day event options per button
14-
- Label your calendars for easy identification (e.g., "Work", "Personal", "Family")
15-
- Buttons using the same URL share a single cache (efficient!)
11+
-**Named Calendars**: Set up multiple calendars with friendly names in Settings (#5)
12+
- Create a library of calendars (Work, Personal, Family, etc.)
13+
- Each button can select which calendar to use from a dropdown
14+
- Calendars sharing the same URL share a single cache (efficient!)
15+
-**Per-Button Settings**: Each button can have its own time window and all-day event preferences
16+
-**Configurable Warning Thresholds**: Customize when orange/red warnings appear
17+
- Orange warning: Choose from 1, 2, 3, 5, 10, 15, or 30 minutes (default: 5 min)
18+
- Red warning: Choose from 10, 15, 30, 45, or 60 seconds (default: 30 sec)
19+
-**Graceful Calendar Deletion**: Buttons using a deleted calendar automatically fall back to default
20+
-**Improved Settings UI**: Redesigned Property Inspector with collapsible help sections
1621

1722
## ✨ New in v2.2
1823

@@ -37,7 +42,9 @@ This plugin is available on the Stream Deck store, you can also download [the la
3742
-**Provider Compatibility**: Optimized for Google Calendar, Microsoft Outlook/Office 365, and Apple Calendar
3843

3944
## Features ##
40-
***Multiple calendars** - Different buttons can show different calendars
45+
***Named calendars** - Set up multiple calendars with friendly names, assign to buttons via dropdown
46+
***Per-button settings** - Each button can use different calendar, time window, and all-day preferences
47+
***Configurable warning thresholds** - Customize orange/red warning times
4148
***Recurring events** with RRULE expansion and EXDATE handling
4249
***Configurable time window** (1, 3, 5, or 7 days)
4350
***Exclude all-day events** option (enabled by default)
@@ -50,8 +57,8 @@ This plugin is available on the Stream Deck store, you can also download [the la
5057

5158
### Time Left ###
5259
* Shows time left until the meeting ends
53-
* Changes icon color to orange when 5 minutes are left on the meeting
54-
* Changes icon color to red when 30 seconds are left on the meeting and goes up to 5 minutes after the meeting
60+
* Changes icon color to orange when time remaining reaches the orange threshold (default: 5 minutes)
61+
* Changes icon color to red when time remaining reaches the red threshold (default: 30 seconds)
5562
* When the meeting ends the counter will keep going and stay red for 5 minutes, if the user pushes the button it will show the next meeting if one is available
5663
* Supports multiple concurrent meetings, to switch between meeting just push the button
5764
* Shows meeting indicator (e.g., "1/3") when multiple meetings are active
@@ -65,7 +72,7 @@ This plugin is available on the Stream Deck store, you can also download [the la
6572
* Scrolling marquee for meeting titles (tap to show/hide)
6673
* Concurrent meeting support (tap to cycle through active meetings)
6774
* Flash alert when meetings start
68-
* Color-coded countdown (orange at 5 min, red at 30 sec)
75+
* Configurable warning thresholds (orange/red)
6976
* **Perfect for limited Stream Deck space** - one button does it all!
7077

7178
### Next Meeting ###
@@ -75,8 +82,8 @@ This plugin is available on the Stream Deck store, you can also download [the la
7582
* If the button is pushed while the text is showing it will go back to show the time left until the next meeting
7683
* At the end of the title animation, the button will go back to show the time left until the next meeting
7784
* **Optional flash alert** when meetings are about to start (disabled by default)
78-
* Changes icon color to orange when there are 5 minutes left for the next meeting to start
79-
* Changes icon color to red when there are 30 seconds left for the next meeting to start
85+
* Changes icon color to orange when time remaining reaches the orange threshold (default: 5 minutes)
86+
* Changes icon color to red when time remaining reaches the red threshold (default: 30 seconds)
8087

8188
## Calendar Provider Support
8289

@@ -138,15 +145,29 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup instructions.
138145

139146
## Configuration
140147

148+
### Global Settings (Settings Popup)
141149
1. Drag an action to your Stream Deck
142150
2. Click the action to open Property Inspector
143151
3. Click "Settings" button
144-
4. Enter your iCal URL
145-
5. Choose time window (1, 3, 5, or 7 days)
146-
6. Set title display duration (5, 10, 15, or 30 seconds)
147-
7. Optionally enable "Flash when meeting starts" for visual alerts
148-
8. Optionally uncheck "Exclude All-Day Events" to show all-day events
149-
9. Click "Save Settings"
152+
4. **Manage Calendars**: Add named calendars with friendly labels
153+
- Click "Add Calendar" to create a new entry
154+
- Give it a name (e.g., "Work", "Personal")
155+
- Paste your iCal URL
156+
- Set time window and all-day event preferences per calendar
157+
- Click ★ to set as default calendar
158+
5. **Warning Thresholds**: Customize when color warnings appear
159+
- Orange warning: 1-30 minutes (default: 5 min)
160+
- Red warning: 10-60 seconds (default: 30 sec)
161+
6. **Other Options**:
162+
- Title display duration (5, 10, 15, or 30 seconds)
163+
- Flash on meeting start (optional visual alert)
164+
7. Click "Save Settings"
165+
166+
### Per-Button Settings (Property Inspector)
167+
Each button can override the default calendar:
168+
1. Select the button on your Stream Deck
169+
2. In Property Inspector, use the "Calendar" dropdown to select which calendar this button should use
170+
3. The default calendar is indicated with "(Default)" in the dropdown
150171

151172
## Troubleshooting
152173

@@ -195,12 +216,17 @@ We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for:
195216
## Changelog
196217

197218
### v2.3.0 (2026)
198-
-**Multiple Calendars Support**: Each button can use a different calendar (#5)
199-
- ✨ Per-button custom URL, time window, and all-day event settings
200-
- ✨ Calendar labels for easy identification in settings
201-
- ✨ URL-level caching: buttons sharing the same URL share a single cache
202-
- ✅ Added CalendarManager service with 28 tests
203-
- ✅ Added 13 per-action settings tests
219+
-**Named Calendars**: Set up multiple calendars with friendly names in Settings (#5)
220+
-**Per-Button Calendar Selection**: Each button selects calendar from dropdown
221+
-**Configurable Warning Thresholds**: Customize orange (1-30 min) and red (10-60 sec) warnings
222+
-**Graceful Calendar Deletion**: Buttons auto-migrate to default when calendar is deleted
223+
-**Improved Settings UI**: Redesigned Property Inspector with collapsible help
224+
- ✨ Per-button time window and all-day event settings
225+
- ✨ URL-level caching: buttons sharing same URL share a single cache
226+
- 🐛 Fixed button state preservation with SingletonAction pattern
227+
- 🐛 Fixed calendar selection not persisting after Stream Deck restart
228+
- ✅ Added CalendarManager service with 31 tests
229+
- ✅ Added 104 new regression tests (529 total)
204230

205231
### v2.2.0 (2026)
206232
-**Smart Calendar Action**: New combined action that auto-switches between Time Left and Next Meeting (#10)

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"CategoryIcon": "assets/icalIcon",
5858
"URL": "https://github.com/pedrofuentes/stream-deck-ical#readme",
5959
"PropertyInspectorPath": "pi.html",
60-
"Version": "2.2.0.0",
60+
"Version": "2.3.0.0",
6161
"Nodejs": {
6262
"Version": "20",
6363
"Debug": "enabled"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "stream-deck-ical",
3-
"version": "2.2.0",
3+
"version": "2.3.0",
44
"description": "An elgato Stream Deck plugin that displays information from your calendar using an iCal URL. Visual cues and a countdown will help you end meetings on time and be ready for the next one.",
55
"private": true,
66
"type": "module",

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"CategoryIcon": "assets/icalIcon",
5555
"URL": "https://github.com/pedrofuentes/stream-deck-ical#readme",
5656
"PropertyInspectorPath": "pi.html",
57-
"Version": "2.2.0.0",
57+
"Version": "2.3.0.0",
5858
"Nodejs": {
5959
"Version": "20",
6060
"Debug": "enabled"

0 commit comments

Comments
 (0)