diff --git a/backend/app/controllers/public/tournament_pages_controller.rb b/backend/app/controllers/public/tournament_pages_controller.rb
index 18a23e6..e4c4324 100644
--- a/backend/app/controllers/public/tournament_pages_controller.rb
+++ b/backend/app/controllers/public/tournament_pages_controller.rb
@@ -38,19 +38,21 @@ module Public
.includes(
:tournament_group,
:tournament_round,
+ :stream_sessions,
home_participant: { logo_file_attachment: :blob },
away_participant: { logo_file_attachment: :blob }
)
.order(Arel.sql("scheduled_at ASC NULLS LAST"), created_at: :asc)
- @live_sessions = StreamSession
+ broadcasting = StreamSession
.broadcasting
- .publicly_listed
- .where(platform: "matchlivetv")
.includes(:score_state, match: [:home_participant, :away_participant, { team: :club }])
.where(match_id: @tournament.matches.select(:id))
.order(Arel.sql("started_at DESC NULLS LAST"), created_at: :desc)
- @live_by_match_id = @live_sessions.index_by(&:match_id)
+ .to_a
+ @live_by_match_id = {}
+ broadcasting.each { |session| @live_by_match_id[session.match_id] ||= session }
+ @live_sessions = broadcasting.select(&:public_watchable?)
@recordings = Recording.ready.publicly_listed
.joins(stream_session: :match)
diff --git a/backend/app/helpers/public/tournaments_helper.rb b/backend/app/helpers/public/tournaments_helper.rb
index b82cc5b..289e82f 100644
--- a/backend/app/helpers/public/tournaments_helper.rb
+++ b/backend/app/helpers/public/tournaments_helper.rb
@@ -67,7 +67,7 @@ module Public
sessions = match.stream_sessions.to_a
latest = sessions.max_by(&:created_at)
if latest && !latest.status.in?(%w[ended error])
- return :live if latest.status.in?(%w[live reconnecting paused])
+ return :live if latest.status.in?(%w[live reconnecting paused connecting])
return :waiting_operator
end
@@ -106,6 +106,18 @@ module Public
:waiting
end
+ def tournament_public_watch_target(session)
+ return unless session
+ if session.matchlivetv_platform? && session.publicly_listed?
+ return [public_live_path(session), t("tournaments.page.watch_live"), {}]
+ end
+ if session.youtube_watch_url.present?
+ return [session.youtube_watch_url, t("live.show.youtube_watch_link"), { target: "_blank", rel: "noopener" }]
+ end
+
+ nil
+ end
+
def tournament_public_score_label(match)
return "#{match.home_score}–#{match.away_score}" if match.home_score.present? && match.away_score.present?
diff --git a/backend/app/models/stream_session.rb b/backend/app/models/stream_session.rb
index ebb7cd2..b0a638e 100644
--- a/backend/app/models/stream_session.rb
+++ b/backend/app/models/stream_session.rb
@@ -186,6 +186,12 @@ class StreamSession < ApplicationRecord
platform == "youtube" && youtube_watch_url.present?
end
+ def public_watchable?
+ return true if matchlivetv_platform? && publicly_listed?
+
+ youtube_ready?
+ end
+
def link_only?
privacy_status.in?(%w[unlisted private])
end
diff --git a/backend/app/views/layouts/marketing.html.erb b/backend/app/views/layouts/marketing.html.erb
index aeeca7c..ef34de4 100644
--- a/backend/app/views/layouts/marketing.html.erb
+++ b/backend/app/views/layouts/marketing.html.erb
@@ -10,7 +10,7 @@
<%= render "shared/analytics_suppress" %>
<%= yield :head %>
-
+
data-ga-id="<%= MatchLiveTv.google_analytics_measurement_id %>"<% end %>>
<%= render "shared/cookie_banner" %>
@@ -24,7 +24,7 @@
<%= render(@app_store_review_chrome ? "shared/marketing_footer_app_store" : "shared/marketing_footer") %>
-
+
diff --git a/backend/app/views/layouts/marketing_live.html.erb b/backend/app/views/layouts/marketing_live.html.erb
index 590c7b1..0110175 100644
--- a/backend/app/views/layouts/marketing_live.html.erb
+++ b/backend/app/views/layouts/marketing_live.html.erb
@@ -8,7 +8,7 @@
<%= render "shared/meta_tags" %>
<%= render "shared/analytics_suppress" %>
-
+
<%= yield :head %>
diff --git a/backend/app/views/public/tournament_pages/_board_row.html.erb b/backend/app/views/public/tournament_pages/_board_row.html.erb
index 20063be..b47ddd2 100644
--- a/backend/app/views/public/tournament_pages/_board_row.html.erb
+++ b/backend/app/views/public/tournament_pages/_board_row.html.erb
@@ -37,8 +37,12 @@
- <% if live_session %>
- <%= link_to t("tournaments.page.watch_live"), public_live_path(live_session), class: "tournament-board__cta tournament-board__cta--live" %>
+ <% watch = tournament_public_watch_target(live_session) %>
+ <% if watch %>
+ <% url, label, html_opts = watch %>
+ <%= link_to label, url, { class: "tournament-board__cta tournament-board__cta--live" }.merge(html_opts) %>
+ <% elsif live_session %>
+ <%= t("tournaments.page.no_media") %>
<% elsif recording %>
<%= link_to t("tournaments.page.watch_replay"), public_replay_path(recording.stream_session_id), class: "tournament-board__cta" %>
<% else %>
diff --git a/backend/app/views/public/tournament_pages/show.html.erb b/backend/app/views/public/tournament_pages/show.html.erb
index 7ae53d5..b54bf23 100644
--- a/backend/app/views/public/tournament_pages/show.html.erb
+++ b/backend/app/views/public/tournament_pages/show.html.erb
@@ -64,7 +64,11 @@
<%= t("live.index.badge_live") %>
<% end %>
- <%= link_to t("tournaments.page.watch_live"), public_live_path(session), class: "btn-watch" %>
+ <% watch = tournament_public_watch_target(session) %>
+ <% if watch %>
+ <% url, label, html_opts = watch %>
+ <%= link_to label, url, { class: "btn-watch" }.merge(html_opts) %>
+ <% end %>
<% end %>
diff --git a/backend/app/views/public/tournaments/_tab_calendario.html.erb b/backend/app/views/public/tournaments/_tab_calendario.html.erb
index f54ff8d..a784d92 100644
--- a/backend/app/views/public/tournaments/_tab_calendario.html.erb
+++ b/backend/app/views/public/tournaments/_tab_calendario.html.erb
@@ -8,88 +8,105 @@
<% if @matches.any? %>
<%= t("tournaments.hub.calendar_edit_hint") %>
-
- ">
-
-
- | <%= t("tournaments.hub.datetime") %> |
- <%= t("tournaments.hub.court") %> |
- <%= t("tournaments.hub.round") %> |
- <%= t("tournaments.hub.home") %> |
- |
- <%= t("tournaments.hub.away") %> |
- <%= t("tournaments.hub.result") %> |
- |
-
-
-
- <% @matches.each do |match| %>
- <% form_id = "match-edit-#{match.id}" %>
- <% courts = (@tournament.court_list + [match.court]).compact_blank.uniq %>
- <%= form_with url: public_tournament_match_path(@tournament, match), method: :patch, html: { id: form_id, class: "visually-hidden" } do %>
- <%= hidden_field_tag :tab, @tab, form: form_id %>
- <% end %>
-
- <% if @writable %>
- |
- <%= datetime_local_field_tag "match[scheduled_at]", tournament_datetime_local(match.scheduled_at),
- id: "match_at_#{match.id}", form: form_id, required: true, class: "tournament-match-form__datetime" %>
- |
-
- <%= select_tag "match[court]", options_for_select(courts, match.court),
- id: "match_court_#{match.id}", form: form_id, include_blank: true, class: "tournament-match-form__court" %>
- |
- <%= tournament_phase_label(match) %> |
- <%= render "public/tournaments/match_side_select", match: match, side: :home, form_id: form_id %> |
-
- <%= button_to public_swap_tournament_match_path(@tournament, match), method: :post,
- class: "tournament-match-swap__btn",
- title: t("tournaments.hub.swap_sides"),
- form: { class: "tournament-match-swap__form", data: { turbo: false } } do %>
-
- <%= t("tournaments.hub.swap_sides") %>
- <% end %>
- |
- <%= render "public/tournaments/match_side_select", match: match, side: :away, form_id: form_id %> |
-
- <% if match.played? || match.result_status.to_s.start_with?("walkover") %>
- <%= match.home_score %>–<%= match.away_score %>
- <% else %>
-
- <%= number_field_tag :home_score, match.home_score, id: "home_score_#{match.id}", form: form_id, data: { swap_score: "home" } %>
- –
- <%= number_field_tag :away_score, match.away_score, id: "away_score_#{match.id}", form: form_id, data: { swap_score: "away" } %>
-
- <% end %>
- |
-
- <%= submit_tag t("tournaments.hub.save_match"), form: form_id, class: "btn btn-secondary tournament-match-form__save" %>
- <% if match.deletable? %>
- <%= button_to t("matches.index.delete"), public_tournament_match_path(@tournament, match),
- method: :delete, class: "btn btn-secondary tournament-match-form__save",
- form: { class: "tournament-match-delete-form", data: { turbo_confirm: match.matchup_label } } %>
- <% end %>
- |
- <% else %>
- <%= match.scheduled_at ? l(match.scheduled_at, format: :short) : "—" %> |
- <%= match.court || "—" %> |
- <%= tournament_phase_label(match) %> |
- <%= tournament_team_chip(match.home_participant, name: match.home_display_name) %> |
- |
- <%= tournament_team_chip(match.away_participant, name: match.away_display_name) %> |
-
+ ">
+ <% @matches.each do |match| %>
+ <% form_id = "match-edit-#{match.id}" %>
+ <% courts = (@tournament.court_list + [match.court]).compact_blank.uniq %>
+ <%= form_with url: public_tournament_match_path(@tournament, match), method: :patch, html: { id: form_id, class: "visually-hidden" } do %>
+ <%= hidden_field_tag :tab, @tab, form: form_id %>
+ <% end %>
+
+ <% if @writable %>
+
+
+ <%= datetime_local_field_tag "match[scheduled_at]", tournament_datetime_local(match.scheduled_at),
+ id: "match_at_#{match.id}", form: form_id, required: true, class: "tournament-match-form__datetime" %>
+
+
+
+ <%= select_tag "match[court]", options_for_select(courts, match.court),
+ id: "match_court_#{match.id}", form: form_id, include_blank: true, class: "tournament-match-form__court" %>
+
+
+ <%= t("tournaments.hub.round") %>
+ <%= tournament_phase_label(match) %>
+
+
+
+ <%= t("tournaments.hub.home") %>
+ <%= render "public/tournaments/match_side_select", match: match, side: :home, form_id: form_id %>
+
+
+ <%= button_to public_swap_tournament_match_path(@tournament, match), method: :post,
+ class: "tournament-match-swap__btn",
+ title: t("tournaments.hub.swap_sides"),
+ form: { class: "tournament-match-swap__form", data: { turbo: false } } do %>
+
+ <%= t("tournaments.hub.swap_sides") %>
+ <% end %>
+
+
+ <%= t("tournaments.hub.away") %>
+ <%= render "public/tournaments/match_side_select", match: match, side: :away, form_id: form_id %>
+
+
+ <%= t("tournaments.hub.result") %>
+ <% if match.played? || match.result_status.to_s.start_with?("walkover") %>
+ <%= match.home_score %>–<%= match.away_score %>
+ <% else %>
+
+ <%= number_field_tag :home_score, match.home_score, id: "home_score_#{match.id}", form: form_id, data: { swap_score: "home" } %>
+ –
+ <%= number_field_tag :away_score, match.away_score, id: "away_score_#{match.id}", form: form_id, data: { swap_score: "away" } %>
+
+ <% end %>
+
+
+
+ <%= submit_tag t("tournaments.hub.save_match"), form: form_id, class: "btn btn-secondary tournament-match-form__save" %>
+ <% if match.deletable? %>
+ <%= button_to t("matches.index.delete"), public_tournament_match_path(@tournament, match),
+ method: :delete, class: "btn btn-secondary tournament-match-form__save",
+ form: { class: "tournament-match-delete-form", data: { turbo_confirm: match.matchup_label } } %>
+ <% end %>
+
+ <% else %>
+
+ <%= t("tournaments.hub.datetime") %>
+ <%= match.scheduled_at ? l(match.scheduled_at, format: :short) : "—" %>
+
+
+ <%= t("tournaments.hub.court") %>
+ <%= match.court || "—" %>
+
+
+ <%= t("tournaments.hub.round") %>
+ <%= tournament_phase_label(match) %>
+
+
+
+ <%= t("tournaments.hub.home") %>
+ <%= tournament_team_chip(match.home_participant, name: match.home_display_name) %>
+
+
+
+ <%= t("tournaments.hub.away") %>
+ <%= tournament_team_chip(match.away_participant, name: match.away_display_name) %>
+
+
+ <%= t("tournaments.hub.result") %>
+
<% if match.home_score.present? %>
<%= match.home_score %>–<%= match.away_score %>
<% else %>
—
<% end %>
- |
- |
- <% end %>
-
+
+
+
<% end %>
-
-
+
+ <% end %>
<% else %>
<%= t("tournaments.hub.no_matches") %>
diff --git a/backend/public/marketing.css b/backend/public/marketing.css
index d016ad1..c2c4d36 100644
--- a/backend/public/marketing.css
+++ b/backend/public/marketing.css
@@ -1183,6 +1183,93 @@ body.invite-editor--resizing {
.tournament-hub-hint { color: #888; margin: 0 0 12px; }
.tournament-table-wrap { overflow-x: auto; margin-top: 8px; }
+.tournament-match-list {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ margin-top: 8px;
+ min-width: 0;
+ overflow-x: clip;
+}
+.tournament-match-row {
+ display: grid;
+ grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.9fr) minmax(0, 0.7fr);
+ gap: 10px 12px;
+ align-items: end;
+ min-width: 0;
+ padding: 14px;
+ border: 1px solid #2a2a36;
+ border-radius: 12px;
+ background: #14141c;
+}
+.tournament-match-row__field,
+.tournament-match-row__side,
+.tournament-match-row__score {
+ min-width: 0;
+}
+.tournament-match-row__field label,
+.tournament-match-row__label {
+ display: block;
+ margin-bottom: 6px;
+ color: #9a9aa8;
+ font-size: 0.75rem;
+ letter-spacing: 0.02em;
+}
+.tournament-match-row__phase {
+ margin: 0;
+ padding: 8px 0;
+ color: #e8e8ee;
+ font-size: 0.95rem;
+}
+.tournament-match-row__sides {
+ grid-column: 1 / -1;
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) 44px minmax(0, 1fr) auto;
+ gap: 8px 10px;
+ align-items: end;
+ min-width: 0;
+}
+.tournament-match-row__actions {
+ grid-column: 1 / -1;
+ justify-content: flex-end;
+}
+.tournament-match-row .tournament-match-form__datetime,
+.tournament-match-row .tournament-match-form__court,
+.tournament-match-row .tournament-match-form__team {
+ width: 100%;
+ max-width: 100%;
+ min-width: 0;
+ margin-bottom: 0;
+ padding: 8px 10px;
+ font-size: 0.9rem;
+ box-sizing: border-box;
+}
+@media (max-width: 799px) {
+ .tournament-match-row {
+ grid-template-columns: 1fr 1fr;
+ }
+ .tournament-match-row__field--phase {
+ grid-column: 1 / -1;
+ }
+ .tournament-match-row__sides {
+ grid-template-columns: minmax(0, 1fr) 44px minmax(0, 1fr);
+ }
+ .tournament-match-row__score {
+ grid-column: 1 / -1;
+ }
+}
+@media (max-width: 560px) {
+ .tournament-match-row,
+ .tournament-match-row__sides {
+ grid-template-columns: minmax(0, 1fr);
+ }
+ .tournament-match-row__field--phase {
+ grid-column: auto;
+ }
+ .tournament-match-swap-col {
+ justify-self: center;
+ }
+}
.tournament-index-actions {
display: flex;
flex-wrap: wrap;
@@ -1205,19 +1292,19 @@ body.invite-editor--resizing {
background: #12121a;
flex-shrink: 0;
}
-.tournament-match-table .tournament-match-form__datetime {
+table.tournament-match-table .tournament-match-form__datetime {
min-width: 190px;
margin-bottom: 0;
padding: 8px 10px;
font-size: 0.9rem;
}
-.tournament-match-table .tournament-match-form__court {
+table.tournament-match-table .tournament-match-form__court {
min-width: 120px;
margin-bottom: 0;
padding: 8px 10px;
font-size: 0.9rem;
}
-.tournament-match-table .tournament-match-form__team {
+table.tournament-match-table .tournament-match-form__team {
min-width: 160px;
max-width: 220px;
margin-bottom: 0;
@@ -1260,6 +1347,8 @@ body.invite-editor--resizing {
padding: 4px 10px;
font-size: 0.8rem;
margin: 0;
+ flex-shrink: 0;
+ white-space: nowrap;
}
.tournament-match-swap-col {
width: 44px;
diff --git a/backend/public/tournament-calendar.js b/backend/public/tournament-calendar.js
index 1d31242..75394a2 100644
--- a/backend/public/tournament-calendar.js
+++ b/backend/public/tournament-calendar.js
@@ -10,7 +10,7 @@
event.stopImmediatePropagation();
if (form.dataset.swapBusy === "1") return;
- var row = form.closest("tr");
+ var row = form.closest(".tournament-match-row") || form.closest("tr");
if (!row) return;
form.dataset.swapBusy = "1";
diff --git a/backend/spec/requests/public/tournaments_spec.rb b/backend/spec/requests/public/tournaments_spec.rb
index 033273f..a0b0523 100644
--- a/backend/spec/requests/public/tournaments_spec.rb
+++ b/backend/spec/requests/public/tournaments_spec.rb
@@ -366,6 +366,7 @@ RSpec.describe "Tournaments", type: :request do
get public_tournament_path(tournament, tab: "calendario")
expect(response.body).to include("tournament-match-swap__btn")
+ expect(response.body).to include("tournament-match-row")
expect(response.body).to include(public_swap_tournament_match_path(tournament, match))
expect(response.body).to include("tournament-calendar.js")
@@ -782,6 +783,50 @@ RSpec.describe "Tournaments", type: :request do
expect(response.body).to include(public_tournament_page_path(tournament.slug))
end
+ it "marca In diretta una gara YouTube o in collegamento, non In attesa" do
+ assign_plan!("premium_full")
+ login!
+ tournament = Tournaments::Create.call(
+ club: club,
+ attrs: {
+ name: "Open Diretta YouTube",
+ sport_key: "basket",
+ starts_on: Date.current,
+ ends_on: Date.current,
+ format_kind: "free",
+ courts: "Campo A"
+ }
+ )
+ home = tournament.participants.create!(name: "Squadra 1")
+ away = tournament.participants.create!(name: "Squadra 3")
+ match = Tournaments::ScheduleMatch.call(
+ tournament: tournament,
+ attrs: {
+ home_participant_id: home.id,
+ away_participant_id: away.id,
+ court: "Campo A",
+ scheduled_at: 30.minutes.ago
+ }
+ )
+ post public_publish_tournament_path(tournament)
+
+ session = StreamSession.create!(
+ match: match, user: coach, platform: "youtube", status: "connecting",
+ privacy_status: "unlisted", youtube_broadcast_id: "ytLiveBoard1"
+ )
+ get public_tournament_page_path(tournament.slug)
+ expect(response.body).to include("tournament-live-status--live")
+ expect(response.body).to include("In diretta")
+ expect(response.body).not_to include("tournament-live-status--waiting")
+ expect(response.body).to include("Guarda su YouTube")
+ expect(response.body).to include(session.youtube_watch_url)
+
+ get public_tournament_path(tournament, tab: "dirette")
+ expect(response.body).to include("tournament-live-status--live")
+ expect(response.body).to include("In diretta")
+ expect(response.body).not_to include("tournament-live-status--waiting_operator")
+ end
+
it "marca Terminata una gara con risultato anche se l'orario è ancora futuro" do
assign_plan!("premium_full")
login!
diff --git a/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/streaming/overlay/CompactScoreboardElement.kt b/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/streaming/overlay/CompactScoreboardElement.kt
index 8de8e32..eb044ea 100644
--- a/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/streaming/overlay/CompactScoreboardElement.kt
+++ b/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/streaming/overlay/CompactScoreboardElement.kt
@@ -114,34 +114,38 @@ class CompactScoreboardElement : OverlayElement {
val accentColor = if (isHome) compact.homeAccentColor else compact.awayAccentColor
val logoUrl = if (isHome) compact.homeLogoUrl else compact.awayLogoUrl
val logo = OverlayLogoCache.get(logoUrl)
- val rawName = if (isHome) compact.homeTeamName else compact.awayTeamName
- val name = ellipsize(rawName.trim(), labelPaint, maxWidth * 0.55f)
+ val rawName = (if (isHome) compact.homeTeamName else compact.awayTeamName).trim()
+ val barHalfH = logoSize * 0.45f
+ val textY = centerY + labelPaint.textSize * 0.35f
if (isHome) {
var x = rectLeft
accentBarPaint.color = accentColor
- canvas.drawRect(x, centerY - logoSize * 0.45f, x + barW, centerY + logoSize * 0.45f, accentBarPaint)
+ canvas.drawRect(x, centerY - barHalfH, x + barW, centerY + barHalfH, accentBarPaint)
x += barW + gap
if (logo != null) {
val dest = RectF(x, centerY - logoSize / 2f, x + logoSize, centerY + logoSize / 2f)
canvas.drawBitmap(logo, null, dest, logoPaint)
x += logoSize + gap
}
- canvas.drawText(name, x, centerY + labelPaint.textSize * 0.35f, labelPaint)
+ val name = ellipsize(rawName, labelPaint, (rectRight - x).coerceAtMost(maxWidth))
+ canvas.drawText(name, x, textY, labelPaint)
} else {
+ // Specchio del lato casa: barra, logo, poi nome a sinistra del logo.
var x = rectRight
accentBarPaint.color = accentColor
- canvas.drawRect(x - barW, centerY - logoSize * 0.45f, x, centerY + logoSize * 0.45f, accentBarPaint)
+ canvas.drawRect(x - barW, centerY - barHalfH, x, centerY + barHalfH, accentBarPaint)
x -= barW + gap
- labelPaint.textAlign = Paint.Align.RIGHT
- canvas.drawText(name, x, centerY + labelPaint.textSize * 0.35f, labelPaint)
- labelPaint.textAlign = Paint.Align.LEFT
- x -= gap
if (logo != null) {
x -= logoSize
val dest = RectF(x, centerY - logoSize / 2f, x + logoSize, centerY + logoSize / 2f)
canvas.drawBitmap(logo, null, dest, logoPaint)
+ x -= gap
}
+ val name = ellipsize(rawName, labelPaint, (x - rectLeft).coerceAtMost(maxWidth))
+ labelPaint.textAlign = Paint.Align.RIGHT
+ canvas.drawText(name, x, textY, labelPaint)
+ labelPaint.textAlign = Paint.Align.LEFT
}
}
diff --git a/native/ios/MatchLiveTv/Streaming/Overlay/CompactScoreboardElement.swift b/native/ios/MatchLiveTv/Streaming/Overlay/CompactScoreboardElement.swift
index 72449cd..b4ece2f 100644
--- a/native/ios/MatchLiveTv/Streaming/Overlay/CompactScoreboardElement.swift
+++ b/native/ios/MatchLiveTv/Streaming/Overlay/CompactScoreboardElement.swift
@@ -67,32 +67,37 @@ struct CompactScoreboardElement: OverlayElement {
let accent = isHome ? compact.homeAccentColor : compact.awayAccentColor
let logoUrl = isHome ? compact.homeLogoUrl : compact.awayLogoUrl
let logo = OverlayLogoCache.get(logoUrl)
- let rawName = isHome ? compact.homeTeamName : compact.awayTeamName
- let name = ellipsize(rawName.trimmingCharacters(in: .whitespacesAndNewlines), font: labelFont, maxWidth: maxWidth * 0.55)
+ let rawName = (isHome ? compact.homeTeamName : compact.awayTeamName)
+ .trimmingCharacters(in: .whitespacesAndNewlines)
let attrs: [NSAttributedString.Key: Any] = [.font: labelFont, .foregroundColor: UIColor.white]
+ let textY = centerY + labelFont.pointSize * 0.35 - labelFont.lineHeight
+ let barHalfH = CGFloat(logoSize) * 0.45
if isHome {
var x = rectLeft
context.setFillColor(accent.cgColor)
- context.fill(CGRect(x: x, y: centerY - CGFloat(logoSize) * 0.45, width: CGFloat(barW), height: CGFloat(logoSize) * 0.9))
+ context.fill(CGRect(x: x, y: centerY - barHalfH, width: CGFloat(barW), height: CGFloat(logoSize) * 0.9))
x += CGFloat(barW + gap)
if let logo, let cg = logo.cgImage {
context.draw(cg, in: CGRect(x: x, y: centerY - CGFloat(logoSize) / 2, width: CGFloat(logoSize), height: CGFloat(logoSize)))
x += CGFloat(logoSize + gap)
}
- (name as NSString).draw(at: CGPoint(x: x, y: centerY + labelFont.pointSize * 0.35 - labelFont.lineHeight), withAttributes: attrs)
+ let name = ellipsize(rawName, font: labelFont, maxWidth: min(rectRight - x, maxWidth))
+ (name as NSString).draw(at: CGPoint(x: x, y: textY), withAttributes: attrs)
} else {
+ // Specchio del lato casa: barra, logo, poi nome a sinistra del logo.
var x = rectRight
context.setFillColor(accent.cgColor)
- context.fill(CGRect(x: x - CGFloat(barW), y: centerY - CGFloat(logoSize) * 0.45, width: CGFloat(barW), height: CGFloat(logoSize) * 0.9))
+ context.fill(CGRect(x: x - CGFloat(barW), y: centerY - barHalfH, width: CGFloat(barW), height: CGFloat(logoSize) * 0.9))
x -= CGFloat(barW + gap)
- let nameSize = (name as NSString).size(withAttributes: attrs)
- (name as NSString).draw(at: CGPoint(x: x - nameSize.width, y: centerY + labelFont.pointSize * 0.35 - labelFont.lineHeight), withAttributes: attrs)
- x -= CGFloat(gap)
if let logo, let cg = logo.cgImage {
x -= CGFloat(logoSize)
context.draw(cg, in: CGRect(x: x, y: centerY - CGFloat(logoSize) / 2, width: CGFloat(logoSize), height: CGFloat(logoSize)))
+ x -= CGFloat(gap)
}
+ let name = ellipsize(rawName, font: labelFont, maxWidth: min(x - rectLeft, maxWidth))
+ let nameSize = (name as NSString).size(withAttributes: attrs)
+ (name as NSString).draw(at: CGPoint(x: x - nameSize.width, y: textY), withAttributes: attrs)
}
}
|