Aggiunge modulo Replay, Garage dev e YouTube a livello società.

Pipeline registrazione/upload con storage S3, archivio web e app, proxy replay
per il browser, OAuth YouTube sulla pagina club (Premium Full) e footer legale.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-03 07:53:11 +02:00
parent a87cda156b
commit 1f273f849d
87 changed files with 2952 additions and 195 deletions

View File

@@ -1,39 +1,58 @@
<% content_for :title, "Replay — #{@match.team.name} vs #{@match.opponent_name}" %>
<% content_for :meta_description, "Replay partita #{@match.team.name} vs #{@match.opponent_name} su Match Live TV." %>
<% content_for :robots, "noindex, nofollow" %>
<% content_for :title, "Replay — #{@recording.title_or_default}" %>
<% content_for :meta_description, "Replay #{@recording.title_or_default} su Match Live TV." %>
<% content_for :robots, @recording.publicly_listed? ? "index, follow" : "noindex, nofollow" %>
<div class="wrap">
<%= link_to "← Tutte le dirette", public_live_index_path, class: "back-link" %>
<div class="wrap replay-show">
<%= link_to "← Live passate", public_replay_index_path, class: "back-link" %>
<h1>Replay</h1>
<p style="color:#aaa"><%= @match.team.name %> vs <%= @match.opponent_name %></p>
<header class="replay-show__header">
<h1><%= @recording.title_or_default %></h1>
<p class="replay-show__meta">
<%= @match.team.club.name %> · <%= l_local(@recording.recorded_at_or_fallback) %>
· <%= @recording.views_label %>
</p>
</header>
<% if @recording %>
<div class="card" style="margin:16px 0">
<% if @session.hls_playback_url.present? %>
<video id="replay-player" class="replay-video" controls playsinline></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@1.5.7"></script>
<script>
(function() {
var src = "<%= j @session.hls_playback_url %>";
var video = document.getElementById("replay-player");
if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = src;
} else if (typeof Hls !== "undefined" && Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(src);
hls.attachMedia(video);
} else {
video.outerHTML = "<p>Il replay non è disponibile su questo browser.</p>";
}
})();
</script>
<% else %>
<p>Registrazione indicizzata. Il playback dipende dalla retention del piano Premium.</p>
<% end %>
<% if @recording.expires_at %>
<p class="stream-ended-meta" style="margin-top:12px">Disponibile fino al <%= l_local(@recording.expires_at) %></p>
<% end %>
<% if @recording.status == "processing" %>
<div class="card replay-show__status">
<p>Registrazione in elaborazione. Riceverai unemail quando sarà pronta.</p>
</div>
<% elsif @recording.ready? %>
<div class="replay-show__player card">
<video id="replay-player" class="replay-video" controls playsinline preload="metadata"
<% if @recording.thumbnail_url %> poster="<%= @recording.thumbnail_url %>"<% end %>>
<source src="<%= public_replay_stream_path(@session) %>" type="video/mp4">
</video>
</div>
<div class="replay-show__details card">
<p class="replay-show__details-line">
<span>Durata <%= @recording.duration_label %></span>
<% if @recording.expires_at %>
<span>· Disponibile fino al <%= l_local(@recording.expires_at) %></span>
<% end %>
<span>· <%= @recording.publicly_listed? ? "Pubblico" : "Privato (link)" %></span>
<% if @recording.byte_size.to_i.positive? %>
<span>· <%= @recording.byte_size_label %></span>
<% end %>
</p>
<% ent = @recording.team.entitlements %>
<div class="replay-show__actions">
<% if ent.phone_download_enabled? && (logged_in? || @recording.unlisted?) %>
<%= link_to "Scarica MP4", public_replay_download_path(@session), class: "btn btn-primary" %>
<% end %>
<% if @recording.youtube_watch_url %>
<%= link_to "Apri su YouTube", @recording.youtube_watch_url, class: "btn btn-secondary", target: "_blank", rel: "noopener" %>
<% end %>
</div>
</div>
<% elsif @recording.status == "failed" %>
<div class="card replay-show__status">
<p>Replay non disponibile: <%= @recording.error_message.presence || "errore di elaborazione" %>.</p>
</div>
<% else %>
<div class="card replay-show__status">
<p>Replay non più disponibile.</p>
</div>
<% end %>
</div>