free-coding-models 0.2.13 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ---
4
4
 
5
+ ## 0.2.14
6
+
7
+ ### Fixed
8
+ - **Changelog scrolling viewport**: Scrolling in changelog details (N key) now respects viewport boundaries — content no longer scrolls beyond visible area. Down/PageDown/End keys now properly clamp to max scroll offset so you can view all content without it disappearing off screen.
9
+
10
+ ---
11
+
5
12
  ## 0.2.13
6
13
 
7
14
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-coding-models",
3
- "version": "0.2.13",
3
+ "version": "0.2.14",
4
4
  "description": "Find the fastest coding LLM models in seconds — ping free models from multiple providers, pick the best one for OpenCode, Cursor, or any AI coding assistant.",
5
5
  "keywords": [
6
6
  "nvidia",
@@ -820,12 +820,44 @@ export function createKeyHandler(ctx) {
820
820
  state.changelogScrollOffset = 0
821
821
  return
822
822
  }
823
+
824
+ // 📖 Calculate total content lines for proper scroll boundary clamping
825
+ const calcChangelogLines = () => {
826
+ const lines = []
827
+ lines.push(` 🚀 free-coding-models`)
828
+ lines.push(` 📋 v${state.changelogSelectedVersion}`)
829
+ lines.push(` — ↑↓ / PgUp / PgDn scroll • B back • Esc close`)
830
+ lines.push('')
831
+ const changes = versions[state.changelogSelectedVersion]
832
+ if (changes) {
833
+ const sections = { added: '✨ Added', fixed: '🐛 Fixed', changed: '🔄 Changed', updated: '📝 Updated' }
834
+ for (const [key, label] of Object.entries(sections)) {
835
+ if (changes[key] && changes[key].length > 0) {
836
+ lines.push(` ${label}`)
837
+ for (const item of changes[key]) {
838
+ let displayText = item.replace(/\*\*([^*]+)\*\*/g, '$1').replace(/`([^`]+)`/g, '$1')
839
+ const maxWidth = state.terminalCols - 16
840
+ if (displayText.length > maxWidth) {
841
+ displayText = displayText.substring(0, maxWidth - 3) + '…'
842
+ }
843
+ lines.push(` • ${displayText}`)
844
+ }
845
+ lines.push('')
846
+ }
847
+ }
848
+ }
849
+ return lines.length
850
+ }
851
+ const totalChangelogLines = calcChangelogLines()
852
+ const viewportRows = Math.max(1, state.terminalRows || 1)
853
+ const maxScrollOffset = Math.max(0, totalChangelogLines - viewportRows)
854
+
823
855
  if (key.name === 'up') { state.changelogScrollOffset = Math.max(0, state.changelogScrollOffset - 1); return }
824
- if (key.name === 'down') { state.changelogScrollOffset += 1; return }
856
+ if (key.name === 'down') { state.changelogScrollOffset = Math.min(maxScrollOffset, state.changelogScrollOffset + 1); return }
825
857
  if (key.name === 'pageup') { state.changelogScrollOffset = Math.max(0, state.changelogScrollOffset - pageStep); return }
826
- if (key.name === 'pagedown') { state.changelogScrollOffset += pageStep; return }
858
+ if (key.name === 'pagedown') { state.changelogScrollOffset = Math.min(maxScrollOffset, state.changelogScrollOffset + pageStep); return }
827
859
  if (key.name === 'home') { state.changelogScrollOffset = 0; return }
828
- if (key.name === 'end') { state.changelogScrollOffset = Number.MAX_SAFE_INTEGER; return }
860
+ if (key.name === 'end') { state.changelogScrollOffset = maxScrollOffset; return }
829
861
  }
830
862
 
831
863
  if (key.ctrl && key.name === 'c') { exit(0); return }