Skip to content

feat: share the game card the way the list shows it - #157

Merged
denis1011101 merged 2 commits into
mainfrom
feature/game-share-card
Aug 25, 2026
Merged

feat: share the game card the way the list shows it#157
denis1011101 merged 2 commits into
mainfrom
feature/game-share-card

Conversation

@denis1011101

Copy link
Copy Markdown
Owner

Share image рисовал абстрактный градиент, не имевший ничего общего с карточкой в списке игр. Теперь картинка повторяет games/_card: дата и время, корт, все метки (спорт, уровень, покрытие, крытый/открытый, тренировка, тренер, еженедельно, поиск игроков, погода), турнир, комментарий и счётчик мест.

Заодно чиним сам рендер: Active Storage закрывает загрузчики libvips через Vips.block_untrusted, из-за чего svgload падал и картинка не отдавалась вовсе — ни в кнопке Share image, ни в телеграм-карточках. Загрузчик SVG открываем точечно, под мьютексом и только на время своего рендера.

Share image рисовал абстрактный градиент, не имевший ничего общего с карточкой
в списке игр. Теперь картинка повторяет `games/_card`: дата и время, корт, все
метки (спорт, уровень, покрытие, крытый/открытый, тренировка, тренер,
еженедельно, поиск игроков, погода), турнир, комментарий и счётчик мест.

Заодно чиним сам рендер: Active Storage закрывает загрузчики libvips через
`Vips.block_untrusted`, из-за чего svgload падал и картинка не отдавалась вовсе
— ни в кнопке Share image, ни в телеграм-карточках. Загрузчик SVG открываем
точечно, под мьютексом и только на время своего рендера.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08a5d2df94

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/services/images/svg_rasterizer.rb Outdated
Comment on lines +16 to +18
Vips.block(SVG_LOADER, false)
begin
Vips::Image.svgload_buffer(svg, dpi: dpi)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the SVG loader blocked for concurrent requests

In a multi-threaded web process, Vips.block changes process-wide loader state, while LOCK serializes only callers of this module. During this unblock/load window, concurrent Active Storage processing can therefore select the SVG loader for attacker-controlled input, defeating the safeguard that this code says Rails enabled; repeated public share-card requests can make that race practical. Avoid toggling the global loader during requests, or isolate trusted SVG rendering from the process handling uploads.

Useful? React with 👍 / 👎.

Comment on lines +130 to +131
body << text(text_x, y + 20, display_date.strftime("%A"), size: 15, weight: 500, color: TITLE_COLOR) if display_date
body << text(text_x, y + 38, game_time.strftime("%I:%M %p"), size: 13, color: MUTED_COLOR) if game_time

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use locale-aware date and time formatting

For every non-English locale passed by the controller, Ruby's raw strftime directives ignore I18n.with_locale, so the card still displays an English weekday and a 12-hour AM/PM clock. Format these values through I18n.l or locale-specific translation formats so shared cards match the user's locale.

Useful? React with 👍 / 👎.

Comment on lines +403 to +405
key = [ value, size, weight ]
cache = (Thread.current[:share_card_text_widths] ||= {})
cache[key] ||= begin

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bound the per-thread text-width cache

On long-lived Puma threads, this hash retains every unique court name, comment fragment, tournament name, and badge string ever rendered. truncate_to can additionally cache every progressively shortened prefix of an overlong value, so normal traffic steadily increases worker memory and a long unbroken user value can cause disproportionate CPU and memory use in one request. Use a bounded cache or clear a request-local cache after each render.

Useful? React with 👍 / 👎.

`Vips.block` переключает состояние загрузчиков на весь процесс, а мьютекс держал
только своих: в окне между «открыли» и «закрыли» соседний поток Puma мог отправить
в тот же загрузчик пользовательскую картинку — ровно то, от чего Active Storage
и закрывает svgload. Теперь SVG растеризует отдельный процесс, где Rails не
загружается и блокировки нет, а в приложении она остаётся нетронутой.

Заодно по замечаниям ревью: кэш замеров ширины живёт один рендер вместо всей
жизни потока Puma, а обрезка длинной строки идёт бинарным поиском, а не
посимвольным перебором с замером на каждом шаге.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@denis1011101
denis1011101 merged commit 7930213 into main Aug 25, 2026
4 checks passed
@denis1011101
denis1011101 deleted the feature/game-share-card branch September 4, 2026 21:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant