timely-calendar 1.0.3 → 1.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: afd143174ee0c9300fbce699d4400b3bd2dabb7761571dcbe1196857c81c46cc
4
- data.tar.gz: '0938df470ceedda38b7ce563df8b9ece0c296bc11ba52d4e0a3fef16a19bb0f7'
3
+ metadata.gz: 6c3e56d3da55afb67b478464bca8ebe80dbb0616f5c180f3f40e96969c9ef3d4
4
+ data.tar.gz: 0fbad81b0406bb69b21434c406d60ffdf663c9d94d8e8bec33bd51364eb492df
5
5
  SHA512:
6
- metadata.gz: f7f46d4646e632f9a9770556252eb83d377cd7b4b4b5dbc89f3bf6b0bba6ee3cf2f44bd915ef1562b8daaeb7acef139c9f9dd874bff22e5f84eac5a0f117a2f4
7
- data.tar.gz: 6db50a84acd413e8bda0d6cdbdaff8752d643b43c1bfdeba7d6b233116a759b2f7ca82061e39ec691e09598ca5e0177e89d5cdb6276a1bf7555eca566d9970b6
6
+ metadata.gz: 75eade25f0fdd21608c2b1bcdce7af993bd78a125e5a211df426629a225cf0a1725e8d6376e324529cc8321bca459809cf39ccb67d4bc9e366a871aa2a9fd0f7
7
+ data.tar.gz: 3e613797bf54d9b031818fa9a6bd91ee0412483f2e04bab7c70a380d531a0a9b04ae1c881c49eeafe3bc5e38b2e0adc378461ceae316911c6f59474cd7347fa6
@@ -22,6 +22,7 @@ module Timely
22
22
  @selected_slot = now.hour * 2 + (now.min >= 30 ? 1 : 0)
23
23
  @slot_offset = [@selected_slot - 5, 0].max # Show a few rows above current time
24
24
  @events_by_date = {}
25
+ @_weather_date = Date.today
25
26
  end
26
27
 
27
28
  def run
@@ -60,6 +61,15 @@ module Timely
60
61
  end
61
62
  # Check notifications on idle (runs inexpensively)
62
63
  Notifications.check_and_notify(@db) rescue nil
64
+ # Refresh weather on new day
65
+ today = Date.today
66
+ if @_weather_date != today
67
+ @_weather_date = today
68
+ @weather_forecast = nil
69
+ @_weather_fetched_at = nil
70
+ load_events_for_range
71
+ render_all
72
+ end
63
73
  # Check for Heathrow goto trigger
64
74
  check_heathrow_goto
65
75
  end
@@ -178,10 +188,17 @@ module Timely
178
188
  # @selected_slot: 0-47 = time slots (00:00-23:30)
179
189
  # negative = all-day event rows (-1 = first, -2 = second...)
180
190
  def allday_count
191
+ # Return max all-day event count across the visible week (matches render_mid_pane)
181
192
  @_allday_count_date ||= nil
182
193
  if @_allday_count_date != @selected_date
183
- events = events_on_selected_day
184
- @_allday_count = events.count { |e| e['all_day'].to_i == 1 }
194
+ week_start = @selected_date - (@selected_date.cwday - 1)
195
+ max = 0
196
+ 7.times do |i|
197
+ day = week_start + i
198
+ n = (@events_by_date[day] || []).count { |e| e['all_day'].to_i == 1 }
199
+ max = n if n > max
200
+ end
201
+ @_allday_count = max
185
202
  @_allday_count_date = @selected_date
186
203
  end
187
204
  @_allday_count
@@ -194,13 +211,14 @@ module Timely
194
211
 
195
212
  def adjust_slot_offset
196
213
  return unless @selected_slot >= 0
197
- allday_rows = allday_count > 0 ? allday_count + 1 : 0
198
- available_rows = @panes[:mid].h - 3 - allday_rows
214
+ extra_rows = allday_count > 0 ? allday_count + 1 : 0
215
+ available_rows = @panes[:mid].h - 3 - extra_rows
199
216
  available_rows = [available_rows, 1].max
200
- if @selected_slot - @slot_offset >= available_rows
201
- @slot_offset = @selected_slot - available_rows + 1
202
- elsif @selected_slot < @slot_offset
203
- @slot_offset = @selected_slot
217
+ scrolloff = 2
218
+ if @selected_slot - @slot_offset >= available_rows - scrolloff
219
+ @slot_offset = [@selected_slot - available_rows + scrolloff + 1, [48 - available_rows, 0].max].min
220
+ elsif @selected_slot - @slot_offset < scrolloff
221
+ @slot_offset = [@selected_slot - scrolloff, 0].max
204
222
  end
205
223
  end
206
224
 
@@ -217,8 +235,8 @@ module Timely
217
235
  @selected_slot ||= (@config.get('work_hours.start', 8) rescue 8) * 2
218
236
  @selected_slot = @selected_slot <= min_slot ? 47 : @selected_slot - 1
219
237
  if @selected_slot == 47
220
- allday_rows = allday_count > 0 ? allday_count + 1 : 0
221
- available = [@panes[:mid].h - 3 - allday_rows, 1].max
238
+ extra = allday_count > 0 ? allday_count + 1 : 0
239
+ available = [@panes[:mid].h - 3 - extra, 1].max
222
240
  @slot_offset = [48 - available, 0].max
223
241
  end
224
242
  adjust_slot_offset
@@ -251,8 +269,8 @@ module Timely
251
269
 
252
270
  def go_slot_bottom
253
271
  @selected_slot = 47
254
- allday_rows = allday_count > 0 ? allday_count + 1 : 0
255
- available_rows = @panes[:mid].h - 3 - allday_rows
272
+ extra = allday_count > 0 ? allday_count + 1 : 0
273
+ available_rows = @panes[:mid].h - 3 - extra
256
274
  available_rows = [available_rows, 1].max
257
275
  @slot_offset = [48 - available_rows, 0].max
258
276
  render_mid_pane
@@ -545,7 +563,7 @@ module Timely
545
563
 
546
564
  # Info bar: top row with bg color
547
565
  def render_info_bar
548
- title = " Timely".b
566
+ title = " Timely".bd
549
567
  date_str = @selected_date.strftime(" %A, %B %d, %Y")
550
568
  phase = Astronomy.moon_phase(@selected_date)
551
569
  moon = " #{phase[:symbol]} #{phase[:phase_name]} (#{(phase[:illumination] * 100).round}%)"
@@ -688,11 +706,11 @@ module Timely
688
706
  today_bg = @config.get('colors.today_bg', 246)
689
707
  today_fg = @config.get('colors.today_fg', 232)
690
708
  header = if is_sel && is_today
691
- header.b.u.fg(today_fg).bg(today_bg)
709
+ header.bd.ul.fg(today_fg).bg(today_bg)
692
710
  elsif is_sel
693
- header.b.u.fg(base_color).bg(sel_alt_a)
711
+ header.bd.ul.fg(base_color).bg(sel_alt_a)
694
712
  elsif is_today
695
- header.b.u.fg(today_fg).bg(today_bg)
713
+ header.bd.ul.fg(today_fg).bg(today_bg)
696
714
  else
697
715
  header.fg(base_color)
698
716
  end
@@ -729,7 +747,7 @@ module Timely
729
747
  max_allday.times do |row|
730
748
  allday_slot = -(max_allday - row) # top row = most negative, bottom = -1
731
749
  is_row_selected = (@selected_slot == allday_slot)
732
- parts = [is_row_selected ? " All".fg(255).b + " " : " " * time_col]
750
+ parts = [is_row_selected ? " All".fg(255).bd + " " : " " * time_col]
733
751
  7.times do |col|
734
752
  evt = week_allday[col][row]
735
753
  day = week_start + col
@@ -741,7 +759,7 @@ module Timely
741
759
  color = evt['calendar_color'] || 39
742
760
  marker = is_at ? ">" : " "
743
761
  entry = "#{marker}#{title}"[0, day_col - 1]
744
- cell = cell_bg ? entry.fg(color).b.bg(cell_bg) : entry.fg(color)
762
+ cell = cell_bg ? entry.fg(color).bd.bg(cell_bg) : entry.fg(color)
745
763
  else
746
764
  cell = cell_bg ? " ".bg(cell_bg) : " "
747
765
  end
@@ -777,7 +795,7 @@ module Timely
777
795
 
778
796
  # Time label: highlight if selected
779
797
  time_label = format("%02d:%02d ", hour, minute)
780
- time_label = is_slot_selected ? time_label.fg(255).b : time_label.fg(238)
798
+ time_label = is_slot_selected ? time_label.fg(255).bd : time_label.fg(238)
781
799
 
782
800
  parts = [time_label]
783
801
  7.times do |col|
@@ -809,7 +827,7 @@ module Timely
809
827
  color = evt['calendar_color'] || 39
810
828
  entry = "#{marker}#{title}"
811
829
  entry = entry[0, day_col - 1] + "." if entry.length > day_col
812
- cell = is_at_slot ? entry.fg(color).b.bg(cell_bg) : entry.fg(color).bg(cell_bg)
830
+ cell = is_at_slot ? entry.fg(color).bd.bg(cell_bg) : entry.fg(color).bg(cell_bg)
813
831
  else
814
832
  cell = " ".bg(cell_bg)
815
833
  end
@@ -851,7 +869,7 @@ module Timely
851
869
  time_info = st.strftime('%a %Y-%m-%d %H:%M')
852
870
  time_info += " - #{Time.at(evt['end_time'].to_i).strftime('%H:%M')}" if evt['end_time']
853
871
  end
854
- lines << " #{title}".fg(color).b + " #{time_info}".fg(252)
872
+ lines << " #{title}".fg(color).bd + " #{time_info}".fg(252)
855
873
 
856
874
  # Line 2: Location + Organizer + Calendar on same line
857
875
  details = []
@@ -898,7 +916,7 @@ module Timely
898
916
 
899
917
  else
900
918
  # No events: show day summary
901
- lines << " #{@selected_date.strftime('%A, %B %d, %Y')}".b
919
+ lines << " #{@selected_date.strftime('%A, %B %d, %Y')}".bd
902
920
 
903
921
  # Astronomical events (solstices, meteor showers, etc.)
904
922
  lat = @config.get('location.lat', 59.9139)
@@ -986,7 +1004,7 @@ module Timely
986
1004
  if calendars.size > 1
987
1005
  cal_list = calendars.each_with_index.map { |c, i| "#{i + 1}:#{c['name']}" }.join(" ")
988
1006
  default_idx = calendars.index(cal) || 0
989
- blank_bottom(" New Event".fg(cal_color).b)
1007
+ blank_bottom(" New Event".fg(cal_color).bd)
990
1008
  pick = bottom_ask(" Calendar (#{cal_list}): ", (default_idx + 1).to_s)
991
1009
  return cancel_create if pick.nil?
992
1010
  idx = pick.strip.to_i - 1
@@ -994,11 +1012,11 @@ module Timely
994
1012
  cal_color = cal['color'] || 39
995
1013
  end
996
1014
 
997
- blank_bottom(" New Event on #{@selected_date.strftime('%A, %B %d, %Y')}".fg(cal_color).b)
1015
+ blank_bottom(" New Event on #{@selected_date.strftime('%A, %B %d, %Y')}".fg(cal_color).bd)
998
1016
  title = bottom_ask(" Title: ", "")
999
1017
  return cancel_create if title.nil? || title.strip.empty?
1000
1018
 
1001
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1019
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1002
1020
  time_str = bottom_ask(" Start time (HH:MM or 'all day'): ", default_time)
1003
1021
  return cancel_create if time_str.nil?
1004
1022
 
@@ -1013,7 +1031,7 @@ module Timely
1013
1031
  minute = (parts[1] || 0).to_i
1014
1032
  start_ts = Time.new(@selected_date.year, @selected_date.month, @selected_date.day, hour, minute, 0).to_i
1015
1033
 
1016
- blank_bottom(" #{title.strip} at #{time_str.strip}".fg(cal_color).b)
1034
+ blank_bottom(" #{title.strip} at #{time_str.strip}".fg(cal_color).bd)
1017
1035
  dur_str = bottom_ask(" Duration in minutes: ", "60")
1018
1036
  return cancel_create if dur_str.nil?
1019
1037
  duration = dur_str.strip.to_i
@@ -1022,12 +1040,12 @@ module Timely
1022
1040
  end
1023
1041
 
1024
1042
  # Location
1025
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1043
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1026
1044
  location = bottom_ask(" Location (Enter to skip): ", "")
1027
1045
  location = nil if location.nil? || location.strip.empty?
1028
1046
 
1029
1047
  # Invitees
1030
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1048
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1031
1049
  invitees_str = bottom_ask(" Invite (comma-separated emails, Enter to skip): ", "")
1032
1050
  attendees = nil
1033
1051
  if invitees_str && !invitees_str.strip.empty?
@@ -1035,7 +1053,7 @@ module Timely
1035
1053
  end
1036
1054
 
1037
1055
  # Attachments via rtfm --pick
1038
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1056
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1039
1057
  attach_str = bottom_ask(" Add attachments? (y/N): ", "")
1040
1058
  attachments = nil
1041
1059
  if attach_str&.strip&.downcase == 'y'
@@ -1119,7 +1137,7 @@ module Timely
1119
1137
  evt = event_at_selected_slot
1120
1138
  return show_feedback("No event at this time slot", 245) unless evt
1121
1139
 
1122
- blank_bottom(" Edit Event".b)
1140
+ blank_bottom(" Edit Event".bd)
1123
1141
  new_title = bottom_ask(" Title: ", evt['title'] || "")
1124
1142
  return if new_title.nil?
1125
1143
 
@@ -1153,7 +1171,7 @@ module Timely
1153
1171
  evt = event_at_selected_slot
1154
1172
  return show_feedback("No event at this time slot", 245) unless evt
1155
1173
 
1156
- blank_bottom(" Delete Event".b)
1174
+ blank_bottom(" Delete Event".bd)
1157
1175
  confirm = bottom_ask(" Delete '#{evt['title']}'? (y/n): ", "")
1158
1176
  return unless confirm&.strip&.downcase == 'y'
1159
1177
 
@@ -1214,7 +1232,7 @@ module Timely
1214
1232
  color = evt['calendar_color'] || 39
1215
1233
  lines = []
1216
1234
  lines << ""
1217
- lines << " #{evt['title'] || '(No title)'}".fg(color).b
1235
+ lines << " #{evt['title'] || '(No title)'}".fg(color).bd
1218
1236
  lines << ""
1219
1237
 
1220
1238
  if evt['all_day'].to_i == 1
@@ -1384,7 +1402,7 @@ module Timely
1384
1402
  # --- ICS Import ---
1385
1403
 
1386
1404
  def import_ics_file
1387
- blank_bottom(" Import ICS File".b)
1405
+ blank_bottom(" Import ICS File".bd)
1388
1406
  path = bottom_ask(" File path: ", "")
1389
1407
  return cancel_create if path.nil? || path.strip.empty?
1390
1408
 
@@ -1406,7 +1424,7 @@ module Timely
1406
1424
  # --- Google Calendar ---
1407
1425
 
1408
1426
  def setup_google_calendar
1409
- blank_bottom(" Google Calendar Setup".b.fg(39))
1427
+ blank_bottom(" Google Calendar Setup".bd.fg(39))
1410
1428
  email = bottom_ask(" Google email: ", "")
1411
1429
  return cancel_create if email.nil? || email.strip.empty?
1412
1430
  email = email.strip
@@ -1432,7 +1450,7 @@ module Timely
1432
1450
 
1433
1451
  # Show calendars and let user pick
1434
1452
  cal_list = calendars.each_with_index.map { |c, i| "#{i + 1}:#{c[:summary]}" }.join(" ")
1435
- blank_bottom(" Found #{calendars.size} calendar(s)".fg(39).b)
1453
+ blank_bottom(" Found #{calendars.size} calendar(s)".fg(39).bd)
1436
1454
  pick = bottom_ask(" Add which? (#{cal_list}, 'all', or ESC): ", "all")
1437
1455
  return cancel_create if pick.nil?
1438
1456
 
@@ -1486,7 +1504,7 @@ module Timely
1486
1504
  # --- Outlook Calendar ---
1487
1505
 
1488
1506
  def setup_outlook_calendar
1489
- blank_bottom(" Outlook/365 Calendar Setup".b.fg(33))
1507
+ blank_bottom(" Outlook/365 Calendar Setup".bd.fg(33))
1490
1508
 
1491
1509
  # Get client_id (from Azure app registration)
1492
1510
  default_client_id = @config.get('outlook.client_id', '')
@@ -1522,11 +1540,11 @@ module Timely
1522
1540
  user_code = auth['user_code']
1523
1541
  verify_url = auth['verification_uri'] || 'https://microsoft.com/devicelogin'
1524
1542
 
1525
- blank_bottom(" Outlook Device Login".b.fg(33))
1543
+ blank_bottom(" Outlook Device Login".bd.fg(33))
1526
1544
  lines = [("-" * @w).fg(238)]
1527
1545
  lines << ""
1528
1546
  lines << " Go to: #{verify_url}".fg(51)
1529
- lines << " Enter code: #{user_code}".fg(226).b
1547
+ lines << " Enter code: #{user_code}".fg(226).bd
1530
1548
  lines << ""
1531
1549
  lines << " Waiting for authorization...".fg(245)
1532
1550
  while lines.length < @panes[:bottom].h
@@ -1561,7 +1579,7 @@ module Timely
1561
1579
 
1562
1580
  # Let user pick calendars
1563
1581
  cal_list = calendars.each_with_index.map { |c, i| "#{i + 1}:#{c[:name]}" }.join(" ")
1564
- blank_bottom(" Found #{calendars.size} Outlook calendar(s)".fg(33).b)
1582
+ blank_bottom(" Found #{calendars.size} Outlook calendar(s)".fg(33).bd)
1565
1583
  pick = bottom_ask(" Add which? (#{cal_list}, 'all', or ESC): ", "all")
1566
1584
  return cancel_create if pick.nil?
1567
1585
 
@@ -1733,14 +1751,14 @@ module Timely
1733
1751
  popup.full_refresh
1734
1752
  lines = []
1735
1753
  lines << ""
1736
- lines << " " + "Pick Color".b + " current: " + "\u2588\u2588".fg(sel) + " #{sel}"
1754
+ lines << " " + "Pick Color".bd + " current: " + "\u2588\u2588".fg(sel) + " #{sel}"
1737
1755
  lines << ""
1738
1756
  16.times do |row|
1739
1757
  line = " "
1740
1758
  16.times do |col|
1741
1759
  c = row * 16 + col
1742
1760
  if c == sel
1743
- line += "X ".bg(c).fg(255).b
1761
+ line += "X ".bg(c).fg(255).bd
1744
1762
  else
1745
1763
  line += " ".bg(c)
1746
1764
  end
@@ -1810,7 +1828,7 @@ module Timely
1810
1828
  popup.full_refresh
1811
1829
  lines = []
1812
1830
  lines << ""
1813
- lines << " " + "Calendars".b
1831
+ lines << " " + "Calendars".bd
1814
1832
  lines << " " + ("-" * [pw - 6, 1].max).fg(238)
1815
1833
 
1816
1834
  calendars.each_with_index do |cal, i|
@@ -1821,7 +1839,7 @@ module Timely
1821
1839
  src = cal['source_type'] || 'local'
1822
1840
  name = cal['name'] || '(unnamed)'
1823
1841
  display = " #{swatch} %-22s %s [%s]" % [name[0..21], status, src]
1824
- lines << (i == sel ? display.fg(39).b : display)
1842
+ lines << (i == sel ? display.fg(39).bd : display)
1825
1843
  end
1826
1844
 
1827
1845
  lines << ""
@@ -1915,7 +1933,7 @@ module Timely
1915
1933
  inner_w = pw - 4
1916
1934
  lines = []
1917
1935
  lines << ""
1918
- lines << " " + "Preferences".b
1936
+ lines << " " + "Preferences".bd
1919
1937
  lines << " " + ("\u2500" * [inner_w - 3, 1].max).fg(238)
1920
1938
 
1921
1939
  pref_keys.each_with_index do |(key, label, default), i|
@@ -1932,7 +1950,7 @@ module Timely
1932
1950
  display = " %-18s %s" % [label, val.to_s]
1933
1951
  end
1934
1952
  if i == sel
1935
- lines << display.fg(39).b
1953
+ lines << display.fg(39).bd
1936
1954
  else
1937
1955
  lines << display
1938
1956
  end
@@ -2025,9 +2043,9 @@ module Timely
2025
2043
 
2026
2044
  help = []
2027
2045
  help << ""
2028
- help << " " + "Timely - Terminal Calendar".b.fg(156)
2046
+ help << " " + "Timely - Terminal Calendar".bd.fg(156)
2029
2047
  help << sep
2030
- help << " " + "Navigation".b.fg(156)
2048
+ help << " " + "Navigation".bd.fg(156)
2031
2049
  help << " #{k['d/RIGHT']} #{d['Next day']} #{k['D/LEFT']} #{d['Prev day']}"
2032
2050
  help << " #{k['w']} #{d['Next week']} #{k['W']} #{d['Prev week']}"
2033
2051
  help << " #{k['m']} #{d['Next month']} #{k['M']} #{d['Prev month']}"
@@ -2038,7 +2056,7 @@ module Timely
2038
2056
  help << " #{k['e/E']} #{d['Jump to event (next/prev)']}"
2039
2057
  help << " #{k['t']} #{d['Today']} #{k['g']} #{d['Go to (date, Mon, yyyy)']}"
2040
2058
  help << sep
2041
- help << " " + "Events".b.fg(156)
2059
+ help << " " + "Events".bd.fg(156)
2042
2060
  help << " #{k['n']} #{d['New event']} #{k['ENTER']} #{d['Edit event']}"
2043
2061
  help << " #{k['x/DEL']} #{d['Delete event']} #{k['a']} #{d['Accept invite']}"
2044
2062
  help << " #{k['v']} #{d['View event details (scrollable popup)']}"
@@ -17,7 +17,7 @@ module Timely
17
17
  # Title: centered month and year
18
18
  title = Date.new(year, month, 1).strftime("%B %Y")
19
19
  pad = [(width - title.length) / 2, 1].max
20
- lines << (" " * pad + title).b
20
+ lines << (" " * pad + title).bd
21
21
 
22
22
  # Weekday headers (with space for week number column)
23
23
  header = " " + WEEKDAYS.each_with_index.map { |d, i|
@@ -101,9 +101,9 @@ module Timely
101
101
 
102
102
  d = day.to_s.rjust(2)
103
103
  if is_selected && is_today
104
- base_color ? d.b.u.fg(base_color).bg(today_bg) : d.b.u.bg(today_bg)
104
+ base_color ? d.bd.ul.fg(base_color).bg(today_bg) : d.bd.ul.bg(today_bg)
105
105
  elsif is_selected
106
- base_color ? d.b.u.fg(base_color) : d.b.u
106
+ base_color ? d.bd.ul.fg(base_color) : d.bd.ul
107
107
  elsif is_today
108
108
  base_color ? d.fg(base_color).bg(today_bg) : d.bg(today_bg)
109
109
  elsif base_color
@@ -1,3 +1,3 @@
1
1
  module Timely
2
- VERSION = '1.0.3'
2
+ VERSION = '1.1.0'
3
3
  end
data/timely.gemspec CHANGED
@@ -28,6 +28,6 @@ Gem::Specification.new do |spec|
28
28
  spec.require_paths = ['lib']
29
29
 
30
30
  # Runtime dependencies
31
- spec.add_runtime_dependency 'rcurses', '>= 5.0'
31
+ spec.add_runtime_dependency 'rcurses', '~> 7.0'
32
32
  spec.add_runtime_dependency 'sqlite3', '>= 1.4'
33
33
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timely-calendar
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2026-03-27 00:00:00.000000000 Z
12
+ date: 2026-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rcurses
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '5.0'
20
+ version: '7.0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ">="
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '5.0'
27
+ version: '7.0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: sqlite3
30
30
  requirement: !ruby/object:Gem::Requirement