timely-calendar 1.0.2 → 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: a336a4e6f30f78ab53e5da5005c8a95114d0dc6657d2c5323101615d3cfa4015
4
- data.tar.gz: fc5783786223c1d421832cb0cf46599192fb0f06386fae3c6a7cfc0050aeedf6
3
+ metadata.gz: 6c3e56d3da55afb67b478464bca8ebe80dbb0616f5c180f3f40e96969c9ef3d4
4
+ data.tar.gz: 0fbad81b0406bb69b21434c406d60ffdf663c9d94d8e8bec33bd51364eb492df
5
5
  SHA512:
6
- metadata.gz: 3a62d684e33d3f597748b142e18e0d0c5dc579d4bdb11c3d143efe4fec76129d982d5b47a4944b89e7466a72be92a680a8d10feac54539b1220a23048cc34cf4
7
- data.tar.gz: f2613ecb9a86d8febc5cd8de611c42b371b54440ee6a6c5b7c2c4bffabaf29854be4795d7ba9aa601f982fee6179962956096e567e0a27ba200d67254e3be1cf
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
@@ -345,6 +363,7 @@ module Timely
345
363
  .gsub(/-::~:~::~:~.*$/m, '') # Google Meet block
346
364
  .gsub(/_{3,}/, '') # Long underscore lines (Teams HR)
347
365
  .gsub(/-{5,}/, '') # Long dash lines
366
+ .gsub(/[━═─]{3,}/, '') # Heavy/double/light box-drawing lines
348
367
  .gsub(/\n{3,}/, "\n\n") # Collapse excessive blank lines
349
368
  .strip
350
369
  end
@@ -544,7 +563,7 @@ module Timely
544
563
 
545
564
  # Info bar: top row with bg color
546
565
  def render_info_bar
547
- title = " Timely".b
566
+ title = " Timely".bd
548
567
  date_str = @selected_date.strftime(" %A, %B %d, %Y")
549
568
  phase = Astronomy.moon_phase(@selected_date)
550
569
  moon = " #{phase[:symbol]} #{phase[:phase_name]} (#{(phase[:illumination] * 100).round}%)"
@@ -687,11 +706,11 @@ module Timely
687
706
  today_bg = @config.get('colors.today_bg', 246)
688
707
  today_fg = @config.get('colors.today_fg', 232)
689
708
  header = if is_sel && is_today
690
- header.b.u.fg(today_fg).bg(today_bg)
709
+ header.bd.ul.fg(today_fg).bg(today_bg)
691
710
  elsif is_sel
692
- header.b.u.fg(base_color).bg(sel_alt_a)
711
+ header.bd.ul.fg(base_color).bg(sel_alt_a)
693
712
  elsif is_today
694
- header.b.u.fg(today_fg).bg(today_bg)
713
+ header.bd.ul.fg(today_fg).bg(today_bg)
695
714
  else
696
715
  header.fg(base_color)
697
716
  end
@@ -728,7 +747,7 @@ module Timely
728
747
  max_allday.times do |row|
729
748
  allday_slot = -(max_allday - row) # top row = most negative, bottom = -1
730
749
  is_row_selected = (@selected_slot == allday_slot)
731
- parts = [is_row_selected ? " All".fg(255).b + " " : " " * time_col]
750
+ parts = [is_row_selected ? " All".fg(255).bd + " " : " " * time_col]
732
751
  7.times do |col|
733
752
  evt = week_allday[col][row]
734
753
  day = week_start + col
@@ -740,7 +759,7 @@ module Timely
740
759
  color = evt['calendar_color'] || 39
741
760
  marker = is_at ? ">" : " "
742
761
  entry = "#{marker}#{title}"[0, day_col - 1]
743
- 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)
744
763
  else
745
764
  cell = cell_bg ? " ".bg(cell_bg) : " "
746
765
  end
@@ -776,7 +795,7 @@ module Timely
776
795
 
777
796
  # Time label: highlight if selected
778
797
  time_label = format("%02d:%02d ", hour, minute)
779
- 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)
780
799
 
781
800
  parts = [time_label]
782
801
  7.times do |col|
@@ -808,7 +827,7 @@ module Timely
808
827
  color = evt['calendar_color'] || 39
809
828
  entry = "#{marker}#{title}"
810
829
  entry = entry[0, day_col - 1] + "." if entry.length > day_col
811
- 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)
812
831
  else
813
832
  cell = " ".bg(cell_bg)
814
833
  end
@@ -850,7 +869,7 @@ module Timely
850
869
  time_info = st.strftime('%a %Y-%m-%d %H:%M')
851
870
  time_info += " - #{Time.at(evt['end_time'].to_i).strftime('%H:%M')}" if evt['end_time']
852
871
  end
853
- lines << " #{title}".fg(color).b + " #{time_info}".fg(252)
872
+ lines << " #{title}".fg(color).bd + " #{time_info}".fg(252)
854
873
 
855
874
  # Line 2: Location + Organizer + Calendar on same line
856
875
  details = []
@@ -897,7 +916,7 @@ module Timely
897
916
 
898
917
  else
899
918
  # No events: show day summary
900
- lines << " #{@selected_date.strftime('%A, %B %d, %Y')}".b
919
+ lines << " #{@selected_date.strftime('%A, %B %d, %Y')}".bd
901
920
 
902
921
  # Astronomical events (solstices, meteor showers, etc.)
903
922
  lat = @config.get('location.lat', 59.9139)
@@ -985,7 +1004,7 @@ module Timely
985
1004
  if calendars.size > 1
986
1005
  cal_list = calendars.each_with_index.map { |c, i| "#{i + 1}:#{c['name']}" }.join(" ")
987
1006
  default_idx = calendars.index(cal) || 0
988
- blank_bottom(" New Event".fg(cal_color).b)
1007
+ blank_bottom(" New Event".fg(cal_color).bd)
989
1008
  pick = bottom_ask(" Calendar (#{cal_list}): ", (default_idx + 1).to_s)
990
1009
  return cancel_create if pick.nil?
991
1010
  idx = pick.strip.to_i - 1
@@ -993,11 +1012,11 @@ module Timely
993
1012
  cal_color = cal['color'] || 39
994
1013
  end
995
1014
 
996
- 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)
997
1016
  title = bottom_ask(" Title: ", "")
998
1017
  return cancel_create if title.nil? || title.strip.empty?
999
1018
 
1000
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1019
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1001
1020
  time_str = bottom_ask(" Start time (HH:MM or 'all day'): ", default_time)
1002
1021
  return cancel_create if time_str.nil?
1003
1022
 
@@ -1012,7 +1031,7 @@ module Timely
1012
1031
  minute = (parts[1] || 0).to_i
1013
1032
  start_ts = Time.new(@selected_date.year, @selected_date.month, @selected_date.day, hour, minute, 0).to_i
1014
1033
 
1015
- 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)
1016
1035
  dur_str = bottom_ask(" Duration in minutes: ", "60")
1017
1036
  return cancel_create if dur_str.nil?
1018
1037
  duration = dur_str.strip.to_i
@@ -1021,12 +1040,12 @@ module Timely
1021
1040
  end
1022
1041
 
1023
1042
  # Location
1024
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1043
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1025
1044
  location = bottom_ask(" Location (Enter to skip): ", "")
1026
1045
  location = nil if location.nil? || location.strip.empty?
1027
1046
 
1028
1047
  # Invitees
1029
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1048
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1030
1049
  invitees_str = bottom_ask(" Invite (comma-separated emails, Enter to skip): ", "")
1031
1050
  attendees = nil
1032
1051
  if invitees_str && !invitees_str.strip.empty?
@@ -1034,7 +1053,7 @@ module Timely
1034
1053
  end
1035
1054
 
1036
1055
  # Attachments via rtfm --pick
1037
- blank_bottom(" #{title.strip}".fg(cal_color).b)
1056
+ blank_bottom(" #{title.strip}".fg(cal_color).bd)
1038
1057
  attach_str = bottom_ask(" Add attachments? (y/N): ", "")
1039
1058
  attachments = nil
1040
1059
  if attach_str&.strip&.downcase == 'y'
@@ -1118,7 +1137,7 @@ module Timely
1118
1137
  evt = event_at_selected_slot
1119
1138
  return show_feedback("No event at this time slot", 245) unless evt
1120
1139
 
1121
- blank_bottom(" Edit Event".b)
1140
+ blank_bottom(" Edit Event".bd)
1122
1141
  new_title = bottom_ask(" Title: ", evt['title'] || "")
1123
1142
  return if new_title.nil?
1124
1143
 
@@ -1152,7 +1171,7 @@ module Timely
1152
1171
  evt = event_at_selected_slot
1153
1172
  return show_feedback("No event at this time slot", 245) unless evt
1154
1173
 
1155
- blank_bottom(" Delete Event".b)
1174
+ blank_bottom(" Delete Event".bd)
1156
1175
  confirm = bottom_ask(" Delete '#{evt['title']}'? (y/n): ", "")
1157
1176
  return unless confirm&.strip&.downcase == 'y'
1158
1177
 
@@ -1213,7 +1232,7 @@ module Timely
1213
1232
  color = evt['calendar_color'] || 39
1214
1233
  lines = []
1215
1234
  lines << ""
1216
- lines << " #{evt['title'] || '(No title)'}".fg(color).b
1235
+ lines << " #{evt['title'] || '(No title)'}".fg(color).bd
1217
1236
  lines << ""
1218
1237
 
1219
1238
  if evt['all_day'].to_i == 1
@@ -1383,7 +1402,7 @@ module Timely
1383
1402
  # --- ICS Import ---
1384
1403
 
1385
1404
  def import_ics_file
1386
- blank_bottom(" Import ICS File".b)
1405
+ blank_bottom(" Import ICS File".bd)
1387
1406
  path = bottom_ask(" File path: ", "")
1388
1407
  return cancel_create if path.nil? || path.strip.empty?
1389
1408
 
@@ -1405,7 +1424,7 @@ module Timely
1405
1424
  # --- Google Calendar ---
1406
1425
 
1407
1426
  def setup_google_calendar
1408
- blank_bottom(" Google Calendar Setup".b.fg(39))
1427
+ blank_bottom(" Google Calendar Setup".bd.fg(39))
1409
1428
  email = bottom_ask(" Google email: ", "")
1410
1429
  return cancel_create if email.nil? || email.strip.empty?
1411
1430
  email = email.strip
@@ -1431,7 +1450,7 @@ module Timely
1431
1450
 
1432
1451
  # Show calendars and let user pick
1433
1452
  cal_list = calendars.each_with_index.map { |c, i| "#{i + 1}:#{c[:summary]}" }.join(" ")
1434
- blank_bottom(" Found #{calendars.size} calendar(s)".fg(39).b)
1453
+ blank_bottom(" Found #{calendars.size} calendar(s)".fg(39).bd)
1435
1454
  pick = bottom_ask(" Add which? (#{cal_list}, 'all', or ESC): ", "all")
1436
1455
  return cancel_create if pick.nil?
1437
1456
 
@@ -1485,7 +1504,7 @@ module Timely
1485
1504
  # --- Outlook Calendar ---
1486
1505
 
1487
1506
  def setup_outlook_calendar
1488
- blank_bottom(" Outlook/365 Calendar Setup".b.fg(33))
1507
+ blank_bottom(" Outlook/365 Calendar Setup".bd.fg(33))
1489
1508
 
1490
1509
  # Get client_id (from Azure app registration)
1491
1510
  default_client_id = @config.get('outlook.client_id', '')
@@ -1521,11 +1540,11 @@ module Timely
1521
1540
  user_code = auth['user_code']
1522
1541
  verify_url = auth['verification_uri'] || 'https://microsoft.com/devicelogin'
1523
1542
 
1524
- blank_bottom(" Outlook Device Login".b.fg(33))
1543
+ blank_bottom(" Outlook Device Login".bd.fg(33))
1525
1544
  lines = [("-" * @w).fg(238)]
1526
1545
  lines << ""
1527
1546
  lines << " Go to: #{verify_url}".fg(51)
1528
- lines << " Enter code: #{user_code}".fg(226).b
1547
+ lines << " Enter code: #{user_code}".fg(226).bd
1529
1548
  lines << ""
1530
1549
  lines << " Waiting for authorization...".fg(245)
1531
1550
  while lines.length < @panes[:bottom].h
@@ -1560,7 +1579,7 @@ module Timely
1560
1579
 
1561
1580
  # Let user pick calendars
1562
1581
  cal_list = calendars.each_with_index.map { |c, i| "#{i + 1}:#{c[:name]}" }.join(" ")
1563
- blank_bottom(" Found #{calendars.size} Outlook calendar(s)".fg(33).b)
1582
+ blank_bottom(" Found #{calendars.size} Outlook calendar(s)".fg(33).bd)
1564
1583
  pick = bottom_ask(" Add which? (#{cal_list}, 'all', or ESC): ", "all")
1565
1584
  return cancel_create if pick.nil?
1566
1585
 
@@ -1732,14 +1751,14 @@ module Timely
1732
1751
  popup.full_refresh
1733
1752
  lines = []
1734
1753
  lines << ""
1735
- lines << " " + "Pick Color".b + " current: " + "\u2588\u2588".fg(sel) + " #{sel}"
1754
+ lines << " " + "Pick Color".bd + " current: " + "\u2588\u2588".fg(sel) + " #{sel}"
1736
1755
  lines << ""
1737
1756
  16.times do |row|
1738
1757
  line = " "
1739
1758
  16.times do |col|
1740
1759
  c = row * 16 + col
1741
1760
  if c == sel
1742
- line += "X ".bg(c).fg(255).b
1761
+ line += "X ".bg(c).fg(255).bd
1743
1762
  else
1744
1763
  line += " ".bg(c)
1745
1764
  end
@@ -1809,7 +1828,7 @@ module Timely
1809
1828
  popup.full_refresh
1810
1829
  lines = []
1811
1830
  lines << ""
1812
- lines << " " + "Calendars".b
1831
+ lines << " " + "Calendars".bd
1813
1832
  lines << " " + ("-" * [pw - 6, 1].max).fg(238)
1814
1833
 
1815
1834
  calendars.each_with_index do |cal, i|
@@ -1820,7 +1839,7 @@ module Timely
1820
1839
  src = cal['source_type'] || 'local'
1821
1840
  name = cal['name'] || '(unnamed)'
1822
1841
  display = " #{swatch} %-22s %s [%s]" % [name[0..21], status, src]
1823
- lines << (i == sel ? display.fg(39).b : display)
1842
+ lines << (i == sel ? display.fg(39).bd : display)
1824
1843
  end
1825
1844
 
1826
1845
  lines << ""
@@ -1914,7 +1933,7 @@ module Timely
1914
1933
  inner_w = pw - 4
1915
1934
  lines = []
1916
1935
  lines << ""
1917
- lines << " " + "Preferences".b
1936
+ lines << " " + "Preferences".bd
1918
1937
  lines << " " + ("\u2500" * [inner_w - 3, 1].max).fg(238)
1919
1938
 
1920
1939
  pref_keys.each_with_index do |(key, label, default), i|
@@ -1931,7 +1950,7 @@ module Timely
1931
1950
  display = " %-18s %s" % [label, val.to_s]
1932
1951
  end
1933
1952
  if i == sel
1934
- lines << display.fg(39).b
1953
+ lines << display.fg(39).bd
1935
1954
  else
1936
1955
  lines << display
1937
1956
  end
@@ -2024,9 +2043,9 @@ module Timely
2024
2043
 
2025
2044
  help = []
2026
2045
  help << ""
2027
- help << " " + "Timely - Terminal Calendar".b.fg(156)
2046
+ help << " " + "Timely - Terminal Calendar".bd.fg(156)
2028
2047
  help << sep
2029
- help << " " + "Navigation".b.fg(156)
2048
+ help << " " + "Navigation".bd.fg(156)
2030
2049
  help << " #{k['d/RIGHT']} #{d['Next day']} #{k['D/LEFT']} #{d['Prev day']}"
2031
2050
  help << " #{k['w']} #{d['Next week']} #{k['W']} #{d['Prev week']}"
2032
2051
  help << " #{k['m']} #{d['Next month']} #{k['M']} #{d['Prev month']}"
@@ -2037,7 +2056,7 @@ module Timely
2037
2056
  help << " #{k['e/E']} #{d['Jump to event (next/prev)']}"
2038
2057
  help << " #{k['t']} #{d['Today']} #{k['g']} #{d['Go to (date, Mon, yyyy)']}"
2039
2058
  help << sep
2040
- help << " " + "Events".b.fg(156)
2059
+ help << " " + "Events".bd.fg(156)
2041
2060
  help << " #{k['n']} #{d['New event']} #{k['ENTER']} #{d['Edit event']}"
2042
2061
  help << " #{k['x/DEL']} #{d['Delete event']} #{k['a']} #{d['Accept invite']}"
2043
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.2'
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.2
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-25 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