bible270 1.10.0 → 1.10.2

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: 43fc7b160b27ec7e20797964b1e7a61244f85b2475ba61e5b8b16e0bfb48c491
4
- data.tar.gz: df5de443f785eed07c04db5efdbee1184a0dc39cbf2862a6feec79c3bb83fb3d
3
+ metadata.gz: cfe9cdd0fb7b5bc4a42b10a4c5a7dd25fe585d37b9178f5ffe367fa628824dc8
4
+ data.tar.gz: 92d8d22a9c0572082d756cc797a74c957e816a4d226fe59ad3435874edee59ff
5
5
  SHA512:
6
- metadata.gz: 047001d13b3e85efb775b5abcb63431ce22bf02e0a6e853b4cf63bcf472e5ea5d2e6d95f2af56d8a0004275d343aeaea4c13df1d54d1ae49d7145f79e16d55b8
7
- data.tar.gz: 06aa22e9592f1603f1136babc07b29657c3190f874d645f4e89deb66b0895e200fb155560f0cb628caa79e3c3fac1c8d2d40997e3a5ed6f18998b519fe13e3d0
6
+ metadata.gz: 12c01200bc093c99d11e1ee90773d633d49986001bf70c1673964d6302484c0e47cd9a1e88241ae3644769c0ed2de0dfe33874f98236a7cf48d511a052791a09
7
+ data.tar.gz: 59989b7ae98e4c9e796ab8be529755cbc1737cd9cb954e230bfce627d07e21b6d8dd1b448b7167c90c5fa901b53af6722aac6f321eae49c603de99a669059290
data/CHANGELOG.md CHANGED
@@ -4,14 +4,92 @@ All notable changes to bible270. Format follows [Keep a Changelog](https://keepa
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.10.1...main)**
8
+
9
+ ## [1.10.1] - 2026-10-18
10
+
11
+ ### Added
12
+
13
+ - let admins set each reader's theme
14
+
15
+ ### Changed
16
+
17
+ - show last activity with 24-hour time and keep completed-day passages in the Day link tooltip
18
+ - link reader emails and move Remove picture beside the upload controls on Admin reader pages
19
+ - move translation settings below Name and picture, followed by Theme and Email notifications
20
+
21
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.10.0...v1.10.1)**
22
+
23
+ ## [1.10.0] - 2026-10-18
24
+
25
+ ### Added
26
+
27
+ - add Forest and Midnight themes; rename Light and Dark to Parchment and Earth
28
+
29
+ ### Changed
30
+
31
+ - move Remove picture beside the Profile upload controls
32
+ - reduce avatar queries and defer offscreen avatar loading
33
+ - close the mobile menu on outside clicks or Escape
34
+ - show the plan's time zone beside reminder settings
35
+ - improve screen-reader labels for reflection reading selectors
36
+
37
+ ### Fixed
38
+
39
+ - leave profile settings and pictures unchanged when a profile update is invalid
40
+ - warn when a reflection draft cannot be saved in the browser
41
+ - isolate test uploads between parallel workers and remove them after testing
42
+
43
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.9.1...v1.10.0)**
44
+
45
+ ## [1.9.1] - 2026-10-16
46
+
47
+ ### Fixed
48
+
49
+ - keep the mobile menu icon readable in light and dark themes, including on iOS
50
+
51
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.9.0...v1.9.1)**
52
+
53
+ ## [1.9.0] - 2026-10-15
54
+
55
+ ### Added
56
+
57
+ - let readers choose Light, Dark, or System in Profile, with System as the default
58
+ - add a warm brown dark palette while keeping the completion dove bright
59
+
60
+ Upgrading hosts must install and run the new reader display-preference migration.
61
+
62
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.8.5...v1.9.0)**
63
+
64
+ ## [1.8.5] - 2026-09-27
65
+
7
66
  ### Changed
8
67
 
9
- - keep Proverbs 7 whole and divide Proverbs 10 and 16 into four readings
10
68
  - show likes and replies on My Progress and reader pages, with admin edit links on reader pages
11
69
  - show each reader's pace beside their completed-day count for admins on Community
12
70
  - add edit, like, and reply controls to reflections on Admin reader pages
13
71
 
14
- **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.8.1...main)**
72
+ ### Fixed
73
+
74
+ - align like and reply controls across reflection listings
75
+
76
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.8.4...v1.8.5)**
77
+
78
+ ## [1.8.4] - 2026-09-25
79
+
80
+ ### Changed
81
+
82
+ - show start date, completed days, and ahead/behind status together in the Admin reader list
83
+
84
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.8.3...v1.8.4)**
85
+
86
+ ## [1.8.3] - 2026-09-21
87
+
88
+ ### Changed
89
+
90
+ - keep Proverbs 7 whole and divide Proverbs 10 and 16 into four readings
91
+
92
+ **[Full Changelog](https://github.com/avonderluft/bible270/compare/v1.8.1...v1.8.3)**
15
93
 
16
94
  ## [1.8.1] - 2026-09-19
17
95
 
@@ -785,7 +863,14 @@ This is the initial public release.
785
863
 
786
864
  * Email sign-in requires working Action Mailer delivery in the host application. Set `config.mailer_from`; delivery is inline by default, or set `email_sign_in_deliver_later` when a queue backend is available.
787
865
 
788
- [Unreleased]: https://github.com/avonderluft/bible270/compare/v1.8.1...HEAD
866
+ [Unreleased]: https://github.com/avonderluft/bible270/compare/v1.10.1...HEAD
867
+ [1.10.1]: https://github.com/avonderluft/bible270/releases/tag/v1.10.1
868
+ [1.10.0]: https://github.com/avonderluft/bible270/releases/tag/v1.10.0
869
+ [1.9.1]: https://github.com/avonderluft/bible270/releases/tag/v1.9.1
870
+ [1.9.0]: https://github.com/avonderluft/bible270/releases/tag/v1.9.0
871
+ [1.8.5]: https://github.com/avonderluft/bible270/releases/tag/v1.8.5
872
+ [1.8.4]: https://github.com/avonderluft/bible270/releases/tag/v1.8.4
873
+ [1.8.3]: https://github.com/avonderluft/bible270/releases/tag/v1.8.3
789
874
  [1.8.1]: https://github.com/avonderluft/bible270/releases/tag/v1.8.1
790
875
  [1.8.0]: https://github.com/avonderluft/bible270/releases/tag/v1.8.0
791
876
  [1.7.3]: https://github.com/avonderluft/bible270/releases/tag/v1.7.3
data/README.md CHANGED
@@ -272,6 +272,8 @@ Admins get an extra "Admin" link in the header. The broadcast form can send an i
272
272
  message either to every reader with an email address or only to readers recognized as administrators.
273
273
  From a reader's page you can:
274
274
 
275
+ - **set their theme** — Parchment, Earth, Forest, Midnight, or System, independently of your own theme;
276
+
275
277
  - **move them to a day** — "put them on day 42 as of today" back-dates the start date; check-offs are
276
278
  keyed to day numbers, so nothing in their history moves;
277
279
  - **set their progress** — mark complete through day N (this also clears anything after, so it sets
@@ -22,7 +22,7 @@ module Bible270
22
22
 
23
23
  before_action :require_admin!
24
24
  before_action :load_reader,
25
- only: %i[show destroy update_start update_profile update_notifications update_completion_animation
25
+ only: %i[show destroy update_start update_profile update_theme update_notifications update_completion_animation
26
26
  remove_avatar complete_through toggle_day]
27
27
  before_action :load_comment, only: %i[hide_comment unhide_comment destroy_comment]
28
28
 
@@ -248,6 +248,22 @@ module Bible270
248
248
  end
249
249
  end
250
250
 
251
+ def update_theme
252
+ unless Reader.display_mode_column?
253
+ return redirect_to admin_reader_path(@reader),
254
+ alert: 'Run the pending Bible270 database migration before changing the theme.'
255
+ end
256
+
257
+ mode = params[:display_mode].to_s
258
+ unless Reader::DISPLAY_MODES.include?(mode)
259
+ return redirect_to admin_reader_path(@reader), alert: 'Choose a theme from the list.'
260
+ end
261
+
262
+ @reader.reload unless @reader.has_attribute?(:display_mode)
263
+ @reader.update!(display_mode: mode)
264
+ redirect_to admin_reader_path(@reader), notice: 'Theme updated.'
265
+ end
266
+
251
267
  def update_notifications
252
268
  unless Bible270.config.mention_notifications
253
269
  return redirect_to admin_reader_path(@reader), alert: 'Reflection emails are disabled for this installation.'
@@ -182,12 +182,16 @@ module Bible270
182
182
  local&.strftime('%b %-d, %Y at %-I:%M %p')
183
183
  end
184
184
 
185
+ def b270_activity_datetime(time)
186
+ local = Bible270.local_time(time)
187
+ local&.strftime('%b %-d, %Y %H:%M')
188
+ end
189
+
185
190
  def b270_reader_activity_description(activity)
186
191
  day_link = link_to "Day #{activity.day}", day_path(activity.day), title: b270_day_readings(activity.day)
187
192
 
188
193
  if activity.day_completed?
189
- readings = Plan.readings_for(activity.day).values.compact.join(', ')
190
- safe_join(['completed ', day_link, " (#{readings})"])
194
+ safe_join(['completed ', day_link])
191
195
  else
192
196
  reference = Plan.parts_for(activity.day, activity.track).fetch(activity.part)
193
197
  safe_join(["checked off “#{reference}” for ", day_link])
@@ -77,7 +77,7 @@
77
77
 
78
78
  <div class="b270-list">
79
79
  <% @readers.each do |reader| %>
80
- <div class="b270-li">
80
+ <div class="b270-li b270-reader-theme" data-display-mode="<%= reader.effective_display_mode %>">
81
81
  <%= link_to b270_avatar(reader, size: 72), admin_reader_path(reader),
82
82
  "aria-label": reader.display_name %>
83
83
  <div>
@@ -96,7 +96,7 @@
96
96
  </div>
97
97
  <div class="sub b270-reader-activity">
98
98
  <% if (activity = @recent_reader_activities[reader.id]) %>
99
- <%= b270_date(activity.occurred_at) %>: <%= b270_reader_activity_description(activity) %>
99
+ <%= b270_activity_datetime(activity.occurred_at) %>: <%= b270_reader_activity_description(activity) %>
100
100
  <% else %>
101
101
  No reading activity yet
102
102
  <% end %>
@@ -3,7 +3,7 @@
3
3
  <p class="b270-eyebrow"><%= link_to 'Admin', admin_path %></p>
4
4
  <h1><%= @reader.display_name %></h1>
5
5
  <p class="lede">
6
- <%= @reader.email.presence || @reader.provider %> ·
6
+ <%= @reader.email.present? ? mail_to(@reader.email) : @reader.provider %> ·
7
7
  <%= @days_completed %> of <%= Bible270::Plan::DAYS %> days ·
8
8
  <%= @reader.completion_percent %>%
9
9
  <% if @reader.today_day %>· day <%= @reader.today_day %> today
@@ -18,13 +18,19 @@
18
18
  <div class="b270-avatarrow">
19
19
  <%= b270_avatar(@reader, size: 72, loading: 'eager') %>
20
20
  <% if Bible270::Reader.avatar_uploads? %>
21
- <label class="b270-field" style="flex:1">
22
- <span>Picture</span>
23
- <%= file_field_tag :avatar, accept: Bible270::Avatars.content_types.join(',') %>
24
- <span class="b270-hint" style="margin:0">
25
- PNG, JPEG, GIF or WebP, up to <%= Bible270::Avatars.human_size(Bible270::Avatars.max_bytes) %>.
26
- </span>
27
- </label>
21
+ <div class="b270-avatarcontrols" style="flex:1;min-width:0">
22
+ <label class="b270-field">
23
+ <span>Picture</span>
24
+ <%= file_field_tag :avatar, accept: Bible270::Avatars.content_types.join(',') %>
25
+ <span class="b270-hint" style="margin:0">
26
+ PNG, JPEG, GIF or WebP, up to <%= Bible270::Avatars.human_size(Bible270::Avatars.max_bytes) %>.
27
+ </span>
28
+ </label>
29
+ <% if @reader.avatar_uploaded? %>
30
+ <%= button_tag "Remove picture", type: "submit", class: "b270-linkbtn",
31
+ form: "b270-remove-picture" %>
32
+ <% end %>
33
+ </div>
28
34
  <% end %>
29
35
  </div>
30
36
 
@@ -40,9 +46,54 @@
40
46
  <% end %>
41
47
 
42
48
  <% if @reader.avatar_uploaded? %>
43
- <%= button_to "Remove picture", admin_reader_avatar_path(@reader), method: :delete,
44
- class: 'b270-linkbtn',
45
- form: { data: { turbo_confirm: "Remove #{@reader.display_name}'s picture?" } } %>
49
+ <%# Keep picture removal separate from unsaved name and upload changes. %>
50
+ <%= form_with url: admin_reader_avatar_path(@reader), method: :delete,
51
+ html: { id: "b270-remove-picture", hidden: true },
52
+ data: { turbo_confirm: "Remove #{@reader.display_name}'s picture?" } do %>
53
+ <% end %>
54
+ <% end %>
55
+ </div>
56
+
57
+ <div class="b270-panel">
58
+ <h2 class="b270-subhead">Which translation they read</h2>
59
+ <p class="b270-hint" style="margin-top:0">
60
+ Reading links open in this translation.
61
+ <% if @reader.bible_version.blank? %>
62
+ They have expressed no preference, so they follow the site default
63
+ (<%= Bible270.config.bible_version %>).
64
+ <% end %>
65
+ </p>
66
+
67
+ <%= form_with url: admin_reader_version_path(@reader), method: :patch, class: "b270-form" do %>
68
+ <div class="row">
69
+ <%= select_tag :bible_version,
70
+ options_for_select([["Site default (#{Bible270.config.bible_version})", ""]] +
71
+ Bible270::Translations.options,
72
+ @reader.bible_version.to_s),
73
+ class: "b270-select", style: "width:auto" %>
74
+ </div>
75
+ <%= render "bible270/shared/passage_source", reader: @reader %>
76
+ <%= submit_tag "Save", class: "b270-btn" %>
77
+ <% end %>
78
+ </div>
79
+
80
+ <div class="b270-panel">
81
+ <h2 class="b270-subhead" id="b270-theme-heading">Theme</h2>
82
+ <% if Bible270::Reader.display_mode_column? %>
83
+ <%= form_with url: admin_reader_theme_path(@reader), method: :patch, class: "b270-emailform" do %>
84
+ <%= select_tag :display_mode,
85
+ options_for_select([["Parchment", "light"], ["Earth", "dark"], ["Forest", "dark_green"],
86
+ ["Midnight", "dark_blue"], ["System", "system"]], @reader.effective_display_mode),
87
+ class: "b270-select", aria: { labelledby: "b270-theme-heading", describedby: "b270-theme-hint" } %>
88
+ <p id="b270-theme-hint" class="b270-hint" style="margin:0">
89
+ System follows the reader's device setting: Parchment for light, Earth for dark.
90
+ </p>
91
+ <%= submit_tag "Save", class: "b270-btn" %>
92
+ <% end %>
93
+ <% else %>
94
+ <p class="b270-flash alert" style="margin:0">
95
+ Run the pending Bible270 database migration before changing the theme.
96
+ </p>
46
97
  <% end %>
47
98
  </div>
48
99
 
@@ -119,28 +170,6 @@
119
170
  <%= render "bible270/shared/reflections", comments: @comments, moderate: true, editable: true, actions: true %>
120
171
  </div>
121
172
 
122
- <div class="b270-panel">
123
- <h2 class="b270-subhead">Which translation they read</h2>
124
- <p class="b270-hint" style="margin-top:0">
125
- Reading links open in this translation.
126
- <% if @reader.bible_version.blank? %>
127
- They have expressed no preference, so they follow the site default
128
- (<%= Bible270.config.bible_version %>).
129
- <% end %>
130
- </p>
131
-
132
- <%= form_with url: admin_reader_version_path(@reader), method: :patch, class: "b270-form" do %>
133
- <div class="row">
134
- <%= select_tag :bible_version,
135
- options_for_select([["Site default (#{Bible270.config.bible_version})", ""]] +
136
- Bible270::Translations.options,
137
- @reader.bible_version.to_s),
138
- class: "b270-select", style: "width:auto" %>
139
- </div>
140
- <%= render "bible270/shared/passage_source", reader: @reader %>
141
- <%= submit_tag "Save", class: "b270-btn" %>
142
- <% end %>
143
- </div>
144
173
 
145
174
  <div class="b270-panel">
146
175
  <h2 class="b270-subhead">Completions</h2>
@@ -1,4 +1,6 @@
1
1
  <style>
2
+ /* Reset every palette variable on themed rows so they do not inherit the admin's theme. */
3
+ .b270-reader-theme,
2
4
  .b270{
3
5
  --paper:#ece6da; --card:#f4efe6; --ink:#231f18; --muted:#5d564c; --faint:#6e665b;
4
6
  --line:#d7cfbf; --line-soft:#e2dbcd; --teal:#2f6a67; --oxblood:#8a2f3b; --gold:#80631d;
@@ -11,12 +13,16 @@
11
13
  --alert-surface:#f6e4e2; --alert-ink:#7a2b28; --alert-line:#e6c3bf;
12
14
  --notice-surface:#e7efe6; --notice-ink:#2f5d34; --notice-line:#c6dcc6;
13
15
  color-scheme:light;
16
+ }
17
+ .b270{
14
18
  margin:0; background:radial-gradient(120% 80% at 100% 0%,rgba(165,129,44,.06),transparent 55%),var(--paper);
15
19
  color:var(--ink); font-family:"Inter",system-ui,sans-serif; line-height:1.2; -webkit-font-smoothing:antialiased;
16
20
  }
17
21
  /* Explicit light keeps native controls light even when the OS is dark.
18
22
  Only system mode follows the media query, including live OS changes. */
23
+ .b270-reader-theme[data-display-mode="light"],
19
24
  .b270[data-display-mode="light"]{color-scheme:light}
25
+ .b270-reader-theme[data-display-mode="dark"],
20
26
  .b270[data-display-mode="dark"]{
21
27
  color-scheme:dark;
22
28
  background-image:none;
@@ -32,6 +38,7 @@
32
38
  --alert-surface:#42282a; --alert-ink:#ffc0b8; --alert-line:#a66d68;
33
39
  --notice-surface:#25382a; --notice-ink:#b6dfb6; --notice-line:#6d956e;
34
40
  }
41
+ .b270-reader-theme[data-display-mode="dark_green"],
35
42
  .b270[data-display-mode="dark_green"]{
36
43
  color-scheme:dark;
37
44
  background-image:none;
@@ -47,6 +54,7 @@
47
54
  --alert-surface:#3e282c; --alert-ink:#ffc1c2; --alert-line:#a87479;
48
55
  --notice-surface:#243b2b; --notice-ink:#c1e2b9; --notice-line:#779c70;
49
56
  }
57
+ .b270-reader-theme[data-display-mode="dark_blue"],
50
58
  .b270[data-display-mode="dark_blue"]{
51
59
  color-scheme:dark;
52
60
  background-image:none;
@@ -63,6 +71,7 @@
63
71
  --notice-surface:#1e3430; --notice-ink:#b7decc; --notice-line:#6b9787;
64
72
  }
65
73
  @media (prefers-color-scheme:dark){
74
+ .b270-reader-theme[data-display-mode="system"],
66
75
  .b270[data-display-mode="system"]{
67
76
  color-scheme:dark;
68
77
  background-image:none;
@@ -410,6 +419,7 @@
410
419
  .b270-reader-stats-dialog pre{max-height:65vh;overflow:auto;margin:0;padding:12px;border:1px solid var(--line-soft);border-radius:9px;background:var(--control);color:var(--ink);font:12.5px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
411
420
  .b270-list{background:var(--card);border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow);overflow:hidden}
412
421
  .b270-li{display:flex;align-items:center;gap:14px;padding:14px 18px}
422
+ .b270-li.b270-reader-theme{background:var(--card);color:var(--ink)}
413
423
  .b270-li+.b270-li{border-top:1px solid var(--line-soft)}
414
424
  .b270-li .name{font-weight:600}
415
425
  .b270-li .sub{font-size:12.5px;color:var(--faint)}
data/config/routes.rb CHANGED
@@ -23,6 +23,7 @@ Bible270::Engine.routes.draw do
23
23
  get 'admin/readers/:id', to: 'admin#show', as: :admin_reader
24
24
  delete 'admin/readers/:id', to: 'admin#destroy'
25
25
  patch 'admin/readers/:id/profile', to: 'admin#update_profile', as: :admin_reader_profile
26
+ patch 'admin/readers/:id/theme', to: 'admin#update_theme', as: :admin_reader_theme
26
27
  patch 'admin/readers/:id/notifications', to: 'admin#update_notifications', as: :admin_reader_notifications
27
28
  patch 'admin/readers/:id/completion-animation', to: 'admin#update_completion_animation',
28
29
  as: :admin_reader_completion_animation
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bible270
4
- VERSION = '1.10.0'
4
+ VERSION = '1.10.2'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bible270
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew vonderLuft