|
| 1 | +# Changelog — GarminWO |
| 2 | + |
| 3 | +All notable changes to this project will be documented in this file. |
| 4 | + |
| 5 | +--- |
| 6 | + |
| 7 | +## [1.4.20] — 2026-04-22 |
| 8 | +### Fixed |
| 9 | +- Duplicate workout names now handled correctly — cache stores a list of IDs per name instead of a single ID, so selecting multiple workouts with the same name no longer causes incorrect count in the delete bar |
| 10 | + |
| 11 | +## [1.4.19] — 2026-04-22 |
| 12 | +### Fixed |
| 13 | +- Guard against `undefined` values being added to the selection Set when checking a row with no cached ID |
| 14 | +- Cleanup of `undefined/null` entries in the Set before counting selected workouts |
| 15 | + |
| 16 | +## [1.4.18] — 2026-04-22 |
| 17 | +### Fixed |
| 18 | +- Post-import redirect now uses `?workoutType=running` parameter required by Garmin Connect v5.24 |
| 19 | +- Cache is reloaded after import to retrieve the freshly created workout ID |
| 20 | + |
| 21 | +## [1.4.17] — 2026-04-22 |
| 22 | +### Fixed |
| 23 | +- Replaced `MutationObserver` on `document.body` with a simple `setInterval` polling (every 2s) to detect new rows — eliminates infinite loop that froze Garmin Connect when checking a checkbox |
| 24 | + |
| 25 | +## [1.4.16] — 2026-04-22 |
| 26 | +### Fixed |
| 27 | +- `MutationObserver` now disconnects before and reconnects after `renderCheckboxes()` to prevent re-entrancy loops |
| 28 | + |
| 29 | +## [1.4.15] — 2026-04-22 |
| 30 | +### Fixed |
| 31 | +- `renderCheckboxes()` made synchronous again — `loadWorkoutIds()` called only once before the observer starts |
| 32 | + |
| 33 | +## [1.4.14] — 2026-04-22 |
| 34 | +### Fixed |
| 35 | +- `loadWorkoutIds()` loading flag prevents multiple simultaneous calls |
| 36 | +- Post-import redirect reloads cache before navigating to the new workout page |
| 37 | + |
| 38 | +## [1.4.13] — 2026-04-22 |
| 39 | +### Fixed |
| 40 | +- CSRF token now read from `<meta name="csrf-token">` tag instead of cookies (changed in Garmin Connect v5.24) |
| 41 | +- Applied to `loadWorkoutIds`, `importWorkout` and `confirmAndDelete` |
| 42 | + |
| 43 | +## [1.4.12] — 2026-04-22 |
| 44 | +### Fixed |
| 45 | +- `loadWorkoutIds()` uses relative URL `/gc-api/...` to avoid CORS restrictions in content script |
| 46 | + |
| 47 | +## [1.4.11] — 2026-04-22 |
| 48 | +### Fixed |
| 49 | +- Workout IDs now fetched via `GWO_FETCH_WORKOUT_IDS` message to background service worker to bypass content script CORS restrictions |
| 50 | + |
| 51 | +## [1.4.10] — 2026-04-22 |
| 52 | +### Fixed |
| 53 | +- Compatibility with Garmin Connect v5.24 update: |
| 54 | + - All URLs updated from `/modern/workouts` to `/app/workouts` |
| 55 | + - Checkbox selectors updated to use `className.includes()` instead of CSS attribute selectors (incompatible with special characters in class names) |
| 56 | + - Link selector updated from `a[href*="/workout/"]` to `[class*="workoutName"] button/a` (Garmin replaced `<a>` tags with `<button>` elements) |
| 57 | + - Post-import redirect updated to `/app/workout/{id}?workoutType=running` |
| 58 | + |
| 59 | +--- |
| 60 | + |
| 61 | +## [1.4.9] — 2026-04-20 |
| 62 | +### Fixed |
| 63 | +- Retry button now correctly re-sends selected text to AI (was falling back to image analysis) |
| 64 | +- Added `currentPendingText` global variable to preserve text across retry attempts |
| 65 | + |
| 66 | +## [1.4.8] — 2026-04-20 |
| 67 | +### Fixed |
| 68 | +- Workout ID fetch via intercepted fetch — replaced by background API call approach |
| 69 | + |
| 70 | +## [1.4.7] — 2026-04-20 |
| 71 | +### Fixed |
| 72 | +- Redirect after import falls back to `/app/workouts` list if no workout ID available |
| 73 | +- Link selector made more robust for varying Garmin DOM structures |
| 74 | + |
| 75 | +## [1.4.6] — 2026-04-20 |
| 76 | +### Fixed |
| 77 | +- Checkbox row selector uses `Array.from().filter()` instead of `querySelectorAll('[class*=...]')` to handle special characters (`+`) in Garmin CSS class names |
| 78 | + |
| 79 | +## [1.4.5] — 2026-04-19 |
| 80 | +### Fixed |
| 81 | +- Post-import redirect polling: checks URL availability every 500ms instead of fixed delay (max 15s fallback) |
| 82 | + |
| 83 | +## [1.4.4] — 2026-04-19 |
| 84 | +### Fixed |
| 85 | +- Post-import redirect URL updated to `/app/workout/{id}` (Garmin Connect URL structure change) |
| 86 | +- Redirect delay increased from 2s to 6s to allow Garmin server to make the workout available |
| 87 | + |
| 88 | +## [1.4.3] — 2026-04-18 |
| 89 | +### Changed |
| 90 | +- Chrome Web Store submission: added justifications for `contextMenus`, `tabs` and `*://*/*` host permissions |
| 91 | +- Host permissions limited to specific domains as alternative (reverted to `*://*/*` for flexibility) |
| 92 | + |
| 93 | +## [1.4.2] — 2026-04-17 |
| 94 | +### Fixed |
| 95 | +- `t()` i18n helper now uses a local cache and built-in EN fallback dictionary — prevents raw key display when service worker is asleep after extended navigation |
| 96 | + |
| 97 | +## [1.4.1] — 2026-04-16 |
| 98 | +### Fixed |
| 99 | +- Checkbox observer reset on page change — checkboxes now re-inject correctly when navigating between workout list pages |
| 100 | + |
| 101 | +## [1.4.0] — 2026-04-15 |
| 102 | +### Fixed |
| 103 | +- `try/catch` added around `chrome.runtime.sendMessage()` calls in `checkPendingImage()` and `checkPendingText()` — prevents uncaught errors when service worker is inactive |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## [1.3.9] — 2026-04-14 |
| 108 | +### Fixed |
| 109 | +- `injectCheckboxes()` waits for table rows to be present in DOM before injecting (retry every 300ms, max 20 attempts) |
| 110 | + |
| 111 | +## [1.3.8] — 2026-04-14 |
| 112 | +### Fixed |
| 113 | +- Checkbox row selector changed to `[class*="tableRow"]` to handle special characters in Garmin CSS class names |
| 114 | + |
| 115 | +## [1.3.7] — 2026-04-14 |
| 116 | +### Added |
| 117 | +- **Bulk delete** — checkboxes injected into the native Garmin Connect workout list |
| 118 | +- "Select all" checkbox in table header |
| 119 | +- Floating delete bar with count, Cancel and Delete buttons |
| 120 | +- Confirmation dialog before deletion |
| 121 | +- Rows removed from DOM immediately after successful deletion |
| 122 | + |
| 123 | +## [1.3.6] — 2026-04-13 |
| 124 | +### Fixed |
| 125 | +- Added missing `tabs` permission in `manifest.json` — was causing silent failure of `chrome.tabs.query()` and `chrome.tabs.update()` in background service worker |
| 126 | + |
| 127 | +## [1.3.5] — 2026-04-13 |
| 128 | +### Changed |
| 129 | +- After successful import, redirects directly to the created workout page instead of reloading the list |
| 130 | + |
| 131 | +## [1.3.4] — 2026-04-13 |
| 132 | +### Fixed |
| 133 | +- Retry button correctly re-sends text to AI after a failed text analysis |
| 134 | +- `currentPendingText` preserved for retry |
| 135 | + |
| 136 | +## [1.3.3] — 2026-04-12 |
| 137 | +### Changed |
| 138 | +- Version alignment |
| 139 | + |
| 140 | +## [1.3.2] — 2026-04-12 |
| 141 | +### Added |
| 142 | +- **Retry button** — appears in the error block for temporary API errors (overload, timeout) |
| 143 | +- Retry is context-aware: re-runs image analysis, text analysis, or import depending on current state |
| 144 | + |
| 145 | +## [1.3.1] — 2026-04-12 |
| 146 | +### Added |
| 147 | +- **Right-click on selected text** — select any workout plan text on any web page → right-click → "Send to GarminWO" → AI analyses and imports directly |
| 148 | +- Text analysis via Gemini (`analyzeTextWithGemini`) and Claude (`analyzeTextWithClaude`) |
| 149 | +- `ANALYZE_TEXT` message handler in background service worker |
| 150 | + |
| 151 | +## [1.3.0] — 2026-04-11 |
| 152 | +### Added |
| 153 | +- **Right-click on image** — right-click any image on any web page → "Send to GarminWO" |
| 154 | +- Image fetched and stored in `chrome.storage.local` as pending |
| 155 | +- If a Garmin Connect Workouts tab is already open: activates it and opens the modal automatically |
| 156 | +- Otherwise: opens a new Garmin Connect tab (content.js detects the pending image on load) |
| 157 | +- `contextMenus` and `tabs` permissions added to manifest |
| 158 | + |
| 159 | +--- |
| 160 | + |
| 161 | +## [1.2.x] — 2026-03-xx |
| 162 | +### Added |
| 163 | +- Google Gemini engine support (free, 1500 req/day) |
| 164 | +- Engine selector tabs in popup (Gemini / Claude) |
| 165 | +- JSON file import (no AI call required) |
| 166 | +- Help button (?) in modal — opens language-specific PDF guide |
| 167 | +- 6 language support: FR, EN, ES, DE, IT, RU |
| 168 | +- Full i18n audit and corrections across all locales |
| 169 | +- PDF help guides for all 6 languages |
| 170 | + |
| 171 | +--- |
| 172 | + |
| 173 | +## [1.1.0] — 2026-02-xx |
| 174 | +### Added |
| 175 | +- Initial release |
| 176 | +- Import running workouts into Garmin Connect from a photo or screenshot |
| 177 | +- AI analysis via Anthropic Claude |
| 178 | +- Popup configuration for API key |
| 179 | +- Automatic injection of import button on Garmin Connect Workouts page |
| 180 | +- Support for all native Garmin step types: warmup, interval, recovery, cooldown, repeat |
| 181 | +- End conditions: distance, time, lap button |
0 commit comments