From 793cfaaaf103d52498980a0fb8477e04cf4f322d Mon Sep 17 00:00:00 2001 From: Emiliano Frascaro Date: Sat, 20 Jun 2026 16:15:44 +0200 Subject: [PATCH] Fix avanzamento quarto basket e regia senza cronometro. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normalizza il periodo nel backend quando l'app invia "Q1" via cable, così advance_period aggiorna regia e overlay; rimuove i controlli cronometro dalla regia e rende più tollerante il decode iOS al resume sessione. Co-authored-by: Cursor --- .../controllers/public/regia_controller.rb | 1 + backend/app/models/score_state.rb | 2 +- .../scoring/engines/period_engine_mixin.rb | 20 +- backend/app/services/scoring/period_data.rb | 32 + .../app/views/public/regia/_basket.html.erb | 9 +- .../app/views/public/regia/_timed.html.erb | 9 +- backend/app/views/public/regia/show.html.erb | 4 +- backend/public/regia.js | 47 +- backend/spec/requests/public/regia_spec.rb | 66 ++ .../spec/services/scoring/period_data_spec.rb | 66 ++ .../match_live_tv/domain/ScoreState.kt | 2 +- .../ios/MatchLiveTv.xcodeproj/project.pbxproj | 824 +++++++++--------- .../xcschemes/MatchLiveTv.xcscheme | 10 +- native/ios/MatchLiveTv/Data/API/ApiDtos.swift | 32 +- .../ios/MatchLiveTv/Domain/ScoreState.swift | 3 +- .../ScoreActionDecodeTests.swift | 135 +++ .../ScoreControllerTests.swift | 19 + scripts/e2e_ios_simulator.sh | 32 +- 18 files changed, 861 insertions(+), 452 deletions(-) create mode 100644 backend/app/services/scoring/period_data.rb create mode 100644 backend/spec/services/scoring/period_data_spec.rb diff --git a/backend/app/controllers/public/regia_controller.rb b/backend/app/controllers/public/regia_controller.rb index 9da7c1c..83c8404 100644 --- a/backend/app/controllers/public/regia_controller.rb +++ b/backend/app/controllers/public/regia_controller.rb @@ -34,6 +34,7 @@ module Public def score cmd = params[:cmd].presence || params[:score_action].presence result = Scoring::ApplyAction.new(session: @session, action: cmd).call + @session.reload render json: status_payload.merge( set_won: result.set_won, match_won: result.match_won, diff --git a/backend/app/models/score_state.rb b/backend/app/models/score_state.rb index 60adff0..51a88e2 100644 --- a/backend/app/models/score_state.rb +++ b/backend/app/models/score_state.rb @@ -55,7 +55,7 @@ class ScoreState < ApplicationRecord end def current_period - (data || {})["period"].to_i.positive? ? (data || {})["period"].to_i : 1 + Scoring::PeriodData.number_from((data || {})["period"]) || 1 end def current_period_label diff --git a/backend/app/services/scoring/engines/period_engine_mixin.rb b/backend/app/services/scoring/engines/period_engine_mixin.rb index 5149b0f..6dc35d9 100644 --- a/backend/app/services/scoring/engines/period_engine_mixin.rb +++ b/backend/app/services/scoring/engines/period_engine_mixin.rb @@ -28,6 +28,7 @@ module Scoring def ensure_period_data(score) data = period_data(score) default_data.each { |k, v| data[k] = v unless data.key?(k) } + PeriodData.normalize_hash!(data) data end @@ -43,7 +44,7 @@ module Scoring end def period_label(data) - period = data["period"].to_i + period = PeriodData.number_from(data["period"]) || 1 return "OT" if data["overtime"] board = @match.effective_board_type @@ -63,15 +64,17 @@ module Scoring rules = period_rules max_periods = rules.periods + current = PeriodData.number_from(data["period"]) || 1 + if data["overtime"] - data["period"] = data["period"].to_i + 1 + data["period"] = current + 1 data["clock_secs"] = rules.overtime_duration_secs - elsif data["period"].to_i >= max_periods + elsif current >= max_periods data["overtime"] = true data["period"] = max_periods + 1 data["clock_secs"] = rules.overtime_duration_secs else - data["period"] = data["period"].to_i + 1 + data["period"] = current + 1 data["clock_secs"] = rules.period_duration_secs end data["clock_running"] = false @@ -109,7 +112,14 @@ module Scoring score = ensure_score(session) data = ensure_period_data(score) %w[period clock_secs clock_running home_score away_score overtime].each do |key| - data[key] = payload[key] if payload.key?(key) + next unless payload.key?(key) + + if key == "period" + period = PeriodData.number_from(payload[key]) + data["period"] = period if period&.positive? + else + data[key] = payload[key] + end end save_period_score!(score, data) score diff --git a/backend/app/services/scoring/period_data.rb b/backend/app/services/scoring/period_data.rb new file mode 100644 index 0000000..9753168 --- /dev/null +++ b/backend/app/services/scoring/period_data.rb @@ -0,0 +1,32 @@ +module Scoring + # Normalizza `score_states.data["period"]` (intero o etichetta "Q2" / "2° tempo"). + module PeriodData + module_function + + def number_from(raw) + case raw + when Integer, Float + value = raw.to_i + value.positive? ? value : nil + when String + text = raw.strip + return nil if text.empty? + + if (match = text.match(/\AQ(\d+)\z/i)) + match[1].to_i + elsif (match = text.match(/\A(\d+)\s*°/)) + match[1].to_i + elsif (value = text.to_i).positive? + value + end + end + end + + def normalize_hash!(data) + number = number_from(data["period"]) + data["period"] = number if number&.positive? + data["period"] = 1 unless data["period"].to_i.positive? + data + end + end +end diff --git a/backend/app/views/public/regia/_basket.html.erb b/backend/app/views/public/regia/_basket.html.erb index eeb6f72..7d1314d 100644 --- a/backend/app/views/public/regia/_basket.html.erb +++ b/backend/app/views/public/regia/_basket.html.erb @@ -2,7 +2,6 @@

<%= live_score_period_label(@match, @score) %>

<%= live_score_points_label(@match, @score) %>

-

Cronometro: <%= format_clock_secs(data["clock_secs"]) %>

@@ -13,7 +12,7 @@
-
<%= format_clock_secs(data["clock_secs"]) %>
+
<%= live_score_period_label(@match, @score) %>
<%= @match.opponent_name %>
<%= data["away_score"] || @score.away_points %>
@@ -23,8 +22,4 @@
-
- - - -
+ diff --git a/backend/app/views/public/regia/_timed.html.erb b/backend/app/views/public/regia/_timed.html.erb index 6fde355..62eaccd 100644 --- a/backend/app/views/public/regia/_timed.html.erb +++ b/backend/app/views/public/regia/_timed.html.erb @@ -2,7 +2,6 @@

<%= live_score_period_label(@match, @score) %>

<%= live_score_points_label(@match, @score) %>

-

Cronometro: <%= format_clock_secs(data["clock_secs"]) %>

@@ -11,7 +10,7 @@
-
<%= format_clock_secs(data["clock_secs"]) %>
+
<%= live_score_period_label(@match, @score) %>
<%= @match.opponent_name %>
<%= data["away_score"] || @score.away_points %>
@@ -19,8 +18,4 @@
-
- - - -
+ diff --git a/backend/app/views/public/regia/show.html.erb b/backend/app/views/public/regia/show.html.erb index a8002bf..cc0a91f 100644 --- a/backend/app/views/public/regia/show.html.erb +++ b/backend/app/views/public/regia/show.html.erb @@ -29,7 +29,7 @@

<%= @team.name %> vs <%= @match.opponent_name %>

-

Regia · <%= regia_header_subtitle(@match, @score) %>

+

Regia · <%= regia_header_subtitle(@match, @score) %>

<%= @stream_closed ? "Terminata" : (@session.paused? ? "In pausa" : (@on_air ? "In onda" : "In attesa")) %> @@ -93,4 +93,4 @@ - + diff --git a/backend/public/regia.js b/backend/public/regia.js index e591180..8408c92 100644 --- a/backend/public/regia.js +++ b/backend/public/regia.js @@ -35,7 +35,8 @@ modalCancel: document.getElementById("modal-cancel"), preview: document.getElementById("regia-preview"), previewPlaceholder: document.getElementById("regia-preview-placeholder"), - btnPause: document.getElementById("btn-pause") + btnPause: document.getElementById("btn-pause"), + subtitle: document.getElementById("regia-subtitle") }; let pendingAction = null; @@ -99,6 +100,31 @@ return `${m}:${String(s).padStart(2, "0")}`; } + function resolvePeriodLabel(score, board) { + const raw = score.period; + if (typeof raw === "string" && raw.trim()) return raw.trim(); + if (typeof raw === "number" && raw > 0) { + return board === "basket" ? `Q${raw}` : `${raw}° tempo`; + } + const nested = score.data || {}; + const dataPeriod = nested.period ?? nested["period"]; + const periodNum = parseInt(dataPeriod, 10); + if (periodNum > 0) { + if (nested.overtime || nested["overtime"]) { + return board === "basket" ? `OT${Math.max(periodNum - 4, 1)}` : "Suppl."; + } + return board === "basket" ? `Q${periodNum}` : `${periodNum}° tempo`; + } + return "—"; + } + + function updateRegiaSubtitle(periodLabel, board) { + if (!els.subtitle) return; + if (board === "basket" || board === "timed") { + els.subtitle.textContent = `Regia · ${periodLabel}`; + } + } + function applyScorePayload(data) { const s = data.score; if (!s) return; @@ -109,8 +135,7 @@ const homeSets = s.home_sets ?? s.homeSets; const awaySets = s.away_sets ?? s.awaySets; const currentSet = s.current_set ?? s.currentSet; - const period = s.period; - const clockSecs = s.clock_secs ?? s.clockSecs ?? s.data?.clock_secs; + const periodLabel = resolvePeriodLabel(s, board); const awayEl = document.getElementById("away-points"); const centerHint = document.getElementById("center-hint"); const clockLine = document.getElementById("clock-line"); @@ -119,11 +144,12 @@ if (awayEl) awayEl.textContent = awayPts; if (board === "basket" || board === "timed") { - if (els.setsLine) els.setsLine.textContent = period || "—"; + if (els.setsLine) els.setsLine.textContent = periodLabel; if (els.scoreLine) els.scoreLine.textContent = `${cfg.homeName} ${homePts} - ${awayPts} ${cfg.awayName}`; - if (centerHint) centerHint.textContent = formatClock(clockSecs); - if (clockLine) clockLine.textContent = `Cronometro: ${formatClock(clockSecs)}`; + if (centerHint) centerHint.textContent = periodLabel; + updateRegiaSubtitle(periodLabel, board); } else if (board === "timer") { + const clockSecs = s.clock_secs ?? s.clockSecs ?? s.data?.clock_secs; if (els.setsLine) els.setsLine.textContent = "Cronometro"; if (clockLine) clockLine.textContent = formatClock(clockSecs, true); } else if (board === "generic") { @@ -184,11 +210,18 @@ async function handleAction(action) { const prevHome = els.homePoints?.textContent; const prevAway = document.getElementById("away-points")?.textContent; + const trigger = root.querySelector(`[data-action="${action}"]`); + if (trigger) trigger.disabled = true; try { const data = await postScore(action); applyScorePayload(data); setBadge(data); + if (action === "advance_period") { + const periodLabel = resolvePeriodLabel(data.score || {}, cfg.board); + toast(periodLabel === "—" ? "Periodo aggiornato" : `Ora in ${periodLabel}`); + } + if (cfg.board === "volley" || cfg.board === "racket") { if (data.set_won && action !== "close_set") { const winner = data.winner === "home" ? cfg.homeName : cfg.awayName; @@ -204,6 +237,8 @@ const awayEl = document.getElementById("away-points"); if (prevAway != null && awayEl) awayEl.textContent = prevAway; toast(e.message || "Errore"); + } finally { + if (trigger) trigger.disabled = false; } } diff --git a/backend/spec/requests/public/regia_spec.rb b/backend/spec/requests/public/regia_spec.rb index f01e0da..5f85e17 100644 --- a/backend/spec/requests/public/regia_spec.rb +++ b/backend/spec/requests/public/regia_spec.rb @@ -62,6 +62,72 @@ RSpec.describe "Public regia", type: :request do expect(response.parsed_body.dig("score", "board_type")).to eq("basket") end + it "avanza il quarto basket via API" do + basket_team = club.teams.create!(name: "U13 Basket", sport_key: "basket") + basket_match = basket_team.matches.create!(opponent_name: "Avversario", sport: "basket") + basket_session = StreamSession.create!(match: basket_match, user: user, platform: "matchlivetv", status: "live") + basket_session.create_score_state!( + board_type: "basket", + home_sets: 0, + away_sets: 0, + home_points: 0, + away_points: 0, + current_set: 1, + data: { + "period" => 1, + "clock_secs" => 600, + "clock_running" => false, + "home_score" => 0, + "away_score" => 4, + "overtime" => false + } + ) + token = Sessions::RegiaAccess.new(basket_session).issue_token! + + patch public_regia_score_path(token), params: { cmd: "advance_period" }, as: :json + expect(response).to have_http_status(:ok) + body = response.parsed_body + expect(body.dig("score", "period")).to eq("Q2") + expect(body.dig("score", "data", "period")).to eq(2) + expect(basket_session.score_state.reload.data["period"]).to eq(2) + end + + it "avanza il quarto basket anche con periodo Q1 corrotto in data" do + basket_team = club.teams.create!(name: "U13 Basket", sport_key: "basket") + basket_match = basket_team.matches.create!(opponent_name: "Avversario", sport: "basket") + basket_session = StreamSession.create!(match: basket_match, user: user, platform: "matchlivetv", status: "live") + basket_session.create_score_state!( + board_type: "basket", + data: { + "period" => "Q1", + "home_score" => 0, + "away_score" => 4, + "clock_secs" => 600, + "clock_running" => false, + "overtime" => false + } + ) + token = Sessions::RegiaAccess.new(basket_session).issue_token! + + patch public_regia_score_path(token), params: { cmd: "advance_period" }, as: :json + expect(response).to have_http_status(:ok) + expect(response.parsed_body.dig("score", "period")).to eq("Q2") + end + + it "non mostra controlli cronometro sulla regia basket" do + basket_team = club.teams.create!(name: "U13 Basket", sport_key: "basket") + basket_match = basket_team.matches.create!(opponent_name: "Avversario", sport: "basket") + basket_session = StreamSession.create!(match: basket_match, user: user, platform: "matchlivetv", status: "live") + basket_session.create_score_state!(board_type: "basket", data: { "period" => 1, "home_score" => 0, "away_score" => 0 }) + token = Sessions::RegiaAccess.new(basket_session).issue_token! + + get public_regia_path(token) + expect(response).to have_http_status(:ok) + expect(response.body).to include("Prossimo quarto") + expect(response.body).not_to include("cronometro") + expect(response.body).not_to include("Cronometro:") + end + it "mette in pausa e riprende la diretta" do mtx = instance_double( Mediamtx::Client, diff --git a/backend/spec/services/scoring/period_data_spec.rb b/backend/spec/services/scoring/period_data_spec.rb new file mode 100644 index 0000000..4898d2b --- /dev/null +++ b/backend/spec/services/scoring/period_data_spec.rb @@ -0,0 +1,66 @@ +require "rails_helper" + +RSpec.describe Scoring::PeriodData do + describe ".number_from" do + it "legge interi e etichette basket/timed" do + expect(described_class.number_from(2)).to eq(2) + expect(described_class.number_from("Q3")).to eq(3) + expect(described_class.number_from("2° tempo")).to eq(2) + expect(described_class.number_from("Q1")).to eq(1) + expect(described_class.number_from("")).to be_nil + end + end +end + +RSpec.describe "Basket advance_period con periodo corrotto" do + let!(:user) { User.create!(email: "period@test.it", name: "U", password: "password123", role: "coach") } + let!(:club) { Club.create!(name: "C", sport: "basket", primary_color: "#e53935", secondary_color: "#ffffff") } + let!(:team) { club.teams.create!(name: "U13", sport_key: "basket") } + let!(:match) { team.matches.create!(opponent_name: "Opp", sport: "basket") } + let!(:session) { StreamSession.create!(match: match, user: user, platform: "matchlivetv", status: "live") } + + it "avanza il quarto anche se data.period è la stringa Q1 (sync app mobile)" do + session.create_score_state!( + board_type: "basket", + home_points: 0, + away_points: 4, + data: { + "period" => "Q1", + "home_score" => 0, + "away_score" => 4, + "clock_secs" => 600, + "clock_running" => false, + "overtime" => false + } + ) + + Scoring::ApplyAction.new(session: session, action: "advance_period").call + score = session.score_state.reload + + expect(score.data["period"]).to eq(2) + expect(score.current_period_label).to eq("Q2") + expect(score.as_cable_payload[:period]).to eq("Q2") + end + + it "normalizza period in sync Action Cable" do + session.create_score_state!( + board_type: "basket", + data: { "period" => 1, "home_score" => 0, "away_score" => 0 } + ) + + Scoring::SyncState.new( + session: session, + payload: { + "type" => "score_update", + "board_type" => "basket", + "period" => "Q1", + "home_score" => 2, + "away_score" => 1 + } + ).call + + score = session.score_state.reload + expect(score.data["period"]).to eq(1) + expect(score.data["home_score"]).to eq(2) + end +end diff --git a/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/domain/ScoreState.kt b/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/domain/ScoreState.kt index 2f7a16b..d2bc458 100644 --- a/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/domain/ScoreState.kt +++ b/native/android/app/src/main/kotlin/com/matchlivetv/match_live_tv/domain/ScoreState.kt @@ -38,7 +38,7 @@ data class ScoreState( "timeout_away" to timeoutAway, ) if (boardType in PERIOD_BOARDS) { - payload["period"] = periodLabel ?: period.toString() + payload["period"] = period payload["clock_secs"] = clockSecs payload["clock_running"] = clockRunning payload["home_score"] = homePoints diff --git a/native/ios/MatchLiveTv.xcodeproj/project.pbxproj b/native/ios/MatchLiveTv.xcodeproj/project.pbxproj index f61cedf..4a55ebe 100644 --- a/native/ios/MatchLiveTv.xcodeproj/project.pbxproj +++ b/native/ios/MatchLiveTv.xcodeproj/project.pbxproj @@ -7,183 +7,183 @@ objects = { /* Begin PBXBuildFile section */ - 00BDF215CB7942A799F06774 /* TeamColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6D45B70859402BA3ABD014 /* TeamColorPicker.swift */; }; - 045086A670F24B1192E0DF8F /* SessionRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C3663CA3AD648B48EA4405D /* SessionRepository.swift */; }; - 08F123F9692D48EA94EBD94D /* KeepScreenOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0DC8A3443404B0CAD323B11 /* KeepScreenOn.swift */; }; - 0CE091822CAA4D88B1BE3AF4 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAEE3C8BBB684FEBA230480A /* LoginScreen.swift */; }; - 0E03BE40DAF14E98A35051CE /* ScoreRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA8EB774A34C4E259AFB1C88 /* ScoreRepository.swift */; }; - 138294291C614F218D71B1CD /* ModalRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C3A3F3250284150B0A0BCD4 /* ModalRoutes.swift */; }; - 15EBD3E3D95D4AE5BABB6776 /* ScoreboardElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA61FF84F91473DA84438A8 /* ScoreboardElement.swift */; }; - 191F31088FCE4A82932B6FBB /* LiveScoreActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D1C27A80A842A1B531051C /* LiveScoreActions.swift */; }; - 22A2A4F3BBD845C5B4E1DD6E /* DeviceTelemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC5C7905A24E4AE1A0600511 /* DeviceTelemetry.swift */; }; - 2498A1488A034D058E6997B0 /* ScoreActionDecodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96BA0FAD47DC40D48F063FC8 /* ScoreActionDecodeTests.swift */; }; - 284F82D0FB65448BAB38C6BE /* TokenStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8D2302B51D94A8984EC6A56 /* TokenStore.swift */; }; - 28A607B3D84448308B130ECF /* WatermarkElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DBA84B5B0CA459E89779309 /* WatermarkElement.swift */; }; - 2D3FAEEE0372415381467FC7 /* ApiDtos.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3DF95A27A584535A1511035 /* ApiDtos.swift */; }; - 3027E88493BA43B09B150BA1 /* MatchSessionLauncher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9316C1429F9448ABC7BA7B6 /* MatchSessionLauncher.swift */; }; - 30F21F19C7234BBF8B2B77D4 /* BroadcastPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44FFA851A3BC44A784DF353A /* BroadcastPermissions.swift */; }; - 35FE18027B054D5BBC20DC9C /* MatchScoringRulesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 049297E3B0D44FF8840B8E76 /* MatchScoringRulesTests.swift */; }; - 39E01672805E4B8A88DA0FA9 /* ActionCableClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = D36C4F09E5D04392B0B82EF8 /* ActionCableClient.swift */; }; - 3A08990CB238458CA25C07C9 /* ShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D603A791C926456D9B565F78 /* ShareSheet.swift */; }; - 3AA28F966201426380DEE174 /* BroadcastOrientationPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43DEDBA98F24BE996528018 /* BroadcastOrientationPolicyTests.swift */; }; - 4598E75CCCF5492CB2F0B006 /* MatchColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2349A6BFDD4708B821C659 /* MatchColors.swift */; }; - 464C286CAE724604AF9CC1FD /* MatchSecondaryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1144C664590842258CBE9998 /* MatchSecondaryButton.swift */; }; - 48719B5718B2419E96AE6AF2 /* SessionCableService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8AA247685DD45FD980465B0 /* SessionCableService.swift */; }; - 4A67DD768F074E7885DFDF43 /* WizardShellScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96E61E730231499C9F119309 /* WizardShellScreen.swift */; }; - 4A6973ACDCA743B29ACC1E2E /* OverlayRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C397B3162F38497C9AD0C9CF /* OverlayRenderer.swift */; }; - 4BD05489BDAB4E309311B1C7 /* BroadcastVideoOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBA94A102E6C4E1BAF934D53 /* BroadcastVideoOrientation.swift */; }; - 4C2639382FE6A0440015AAF3 /* HaishinKit in Frameworks */ = {isa = PBXBuildFile; productRef = DFA0D0CEB1F1428D9E3FB3DB /* HaishinKit */; }; - 4C2639392FE6A0440015AAF3 /* RTMPHaishinKit in Frameworks */ = {isa = PBXBuildFile; productRef = AA756D8C68BC4B3D8EC96D5E /* RTMPHaishinKit */; }; - 4CD8A3EB76C14F878BF1026C /* LiveScoreDialogHostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42DAF0103FD4213BE778C7C /* LiveScoreDialogHostTests.swift */; }; - 51B03D8318114D3AB94A41CA /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D65108DA4C4A5BB95C0E51 /* SplashScreen.swift */; }; - 52DCD38F408B4BAE8A0A673D /* AppContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A62D39BF1BD343E2B314A150 /* AppContainer.swift */; }; - 53A492E3510D4C8A9A5C94B7 /* ScoreController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88C71579DA2945D5B0FA780C /* ScoreController.swift */; }; - 59BB3212FCBA4F68B23337F3 /* LiveBroadcastEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD491B8176A0430A9C3AB7B9 /* LiveBroadcastEngine.swift */; }; - 5A8E598237CF41BFB62B83D8 /* WizardSessionHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF24FBB15BA4493EAEA78436 /* WizardSessionHolder.swift */; }; - 5D4E00AC5D4E44A09E3743DE /* MatchLiveTvApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3458504736B4137A749812C /* MatchLiveTvApp.swift */; }; - 5E33700F7C694E9D8EC997D7 /* ScreenOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = E31852C7972040328E39C991 /* ScreenOrientation.swift */; }; - 644B22C2C7E54983A6BE393D /* LiveBroadcastCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB11018606164DAFBDC4E7A1 /* LiveBroadcastCoordinatorTests.swift */; }; - 66539A1D77EA4B368F5BDE2E /* StepMatchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B469A9557164A2682CEA145 /* StepMatchScreen.swift */; }; - 6C52A9292D694A728A372551 /* ScoreControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C58DA984475413DB55C3E1B /* ScoreControllerTests.swift */; }; - 6CA1DE649AEE455C994D0E94 /* MediaUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0487DB6D2DEB4508B5EF5FCC /* MediaUrl.swift */; }; - 6CC11041AFC64969BC9195D0 /* MatchScoringRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4974F7EF092B4FC697A30E00 /* MatchScoringRules.swift */; }; - 6DAD6078CC8D46FCB1AE0A75 /* MatchLiveWordmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE69B3EE8D0E4D8EAA8B853B /* MatchLiveWordmark.swift */; }; - 6E09F9E1FBB3459B94343BDD /* OverlayLogoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 224057D043A541C287071B37 /* OverlayLogoCache.swift */; }; - 7862CEBEB345430F908DE135 /* OverlayState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE44F992D17E408D8713CC95 /* OverlayState.swift */; }; - 7B4182E19F93484B8B0D07DF /* WizardComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3490DEC22A543F890FEA661 /* WizardComponents.swift */; }; - 7DCAA615F27C4853B8A0F889 /* SponsorElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8799BE797C4B4A409E32E753 /* SponsorElement.swift */; }; - 82ADD6499C394031B87D7A96 /* ApiInstant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 691EB1B5F9EA4DFB902E0D37 /* ApiInstant.swift */; }; - 8BAE2CEB56064BA3A3A16B53 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = D17AB6B00BBC4568A6D0457E /* Models.swift */; }; - 91C697AC57284A26A9893DFD /* OverlayMappings.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC8DDF8DE68C4281B9062AD0 /* OverlayMappings.swift */; }; - 91F1D3111F2C4BDFAB7435BF /* MatchScreenScaffold.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8FE87562E85488A946F8C86 /* MatchScreenScaffold.swift */; }; - 921A1A2729B244C08A9BD3FD /* BroadcastControlsOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E0E8585555C42A6A220FF29 /* BroadcastControlsOverlay.swift */; }; - 96E2427E81E744289D1C9B9B /* BroadcastModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC65D1EBC15F4ECB921A94F5 /* BroadcastModels.swift */; }; - 991371D458954C06A798AC0E /* LiveBroadcastCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E0CCB4B0554F96B04BDB07 /* LiveBroadcastCoordinator.swift */; }; - 994148BB9CCE4E6F800CD89A /* ColorHex.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4770AC3C14D451F89B35533 /* ColorHex.swift */; }; - 9D241B051BD54105A9D764DD /* BroadcastOrientationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBD03F804A944D6D84464875 /* BroadcastOrientationPolicy.swift */; }; - 9E770D39394E41838877BC62 /* AuthRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0B5292C4B7344E98043FA55 /* AuthRepository.swift */; }; - AEE1728EFF3F491A81B1156B /* LivePreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1123FED73ED4983BFBE9BB6 /* LivePreviewView.swift */; }; - B3DD2F8E837649B2B007CEAF /* MatchHubFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4570572C5D4745A990B291D6 /* MatchHubFilter.swift */; }; - B7D592901EC34D4B97DCE549 /* StepTransmissionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74D13551050B4A51A21B0A67 /* StepTransmissionScreen.swift */; }; - C5EEE95F92D44046994659FC /* BroadcastScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94110FC43754C50AC862D5C /* BroadcastScreen.swift */; }; - C6B059D6435243208A8FC338 /* MatchesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40924F02DDFA4CCDA9488D64 /* MatchesScreen.swift */; }; - CAABC65179F6467996D85730 /* UserFacingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C5ECE7DA4A94297899495FF /* UserFacingError.swift */; }; - D015D7ACCFE54071B1831C74 /* MatchPrimaryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36263581FBC9465FB59A54A3 /* MatchPrimaryButton.swift */; }; - D0BAD147978244529A46C040 /* CompactScoreboardElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B9968E881924270973373DD /* CompactScoreboardElement.swift */; }; - D3C28481960E4E14A0909DCB /* Routes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290C51105D0B4ABE997FA155 /* Routes.swift */; }; - D501A7EE3BAD467A9A63E63C /* AppNavHost.swift in Sources */ = {isa = PBXBuildFile; fileRef = A3B41DFCE8AF4993A93F756A /* AppNavHost.swift */; }; - D77980669AE84165AAF94AF2 /* MatchRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76B77E9A6C51421D9AEDFF51 /* MatchRepository.swift */; }; - D916D4368A9A4298BDB3430F /* AppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07588FE10B4143D8971F8A1F /* AppConfig.swift */; }; - EA533D28A4EF4171B410B56E /* ScoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134FD1D616EF4F82A0175E28 /* ScoreState.swift */; }; - EB8D708E665A46B398EB0C4F /* MatchLiveAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BCA039B9842405DBCB38BA5 /* MatchLiveAPI.swift */; }; - EBB063DFDBE443F3BC12A67A /* ApiInstantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C0FE41B109A41519495E952 /* ApiInstantTests.swift */; }; - EE689B65571A474CA19A792C /* OverlayCanvasRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C561AB7965264974822DBD60 /* OverlayCanvasRenderer.swift */; }; - EF83C38F78144E0996C33807 /* StepNetworkTestScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0D156DFC16945A3A8467EF0 /* StepNetworkTestScreen.swift */; }; - F13AA7F009F1421FB996956B /* TeamBrandingEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AC1BB5EDAEE43359749B95A /* TeamBrandingEditor.swift */; }; - F13DF021E1084F6C844CB7AB /* MatchStatusBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA7FA4E0FD3142D9957B764F /* MatchStatusBadge.swift */; }; - FE21BE8932864B5D96D1BA41 /* MatchLiveTv/Resources/Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FE0CBD099ED14E62B752AB7F /* MatchLiveTv/Resources/Assets.xcassets */; }; + 05E2509B1F96460F9A8FBDEE /* MatchScoringRulesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51257C93F3A4464F8AA4B5B5 /* MatchScoringRulesTests.swift */; }; + 0811090F35B647A9AAE98018 /* ApiInstant.swift in Sources */ = {isa = PBXBuildFile; fileRef = F52E5A9320FD4A9C82C64092 /* ApiInstant.swift */; }; + 0ABF8F2EAEF84F3CB3510FCA /* MatchHubFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C298D589A644368A5B3DB79 /* MatchHubFilter.swift */; }; + 0AEA80531D74475A9279AAF8 /* LoginScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C77C273929F4A4A9079A55E /* LoginScreen.swift */; }; + 0B2C36335D034737BD753D22 /* BroadcastControlsOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9652ABD17F34BF7B781F9CB /* BroadcastControlsOverlay.swift */; }; + 1191C9F3433D4C79BB1D55CA /* DeviceTelemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD66A152068843A89E25EA2A /* DeviceTelemetry.swift */; }; + 16D77B1BA1694BC9AAEACACA /* ScoreState.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7B37C6177BA4FC7AD4DE2C9 /* ScoreState.swift */; }; + 17F54C8204F346CCA9EBFF89 /* TokenStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6CC04AA64F244128D7069F7 /* TokenStore.swift */; }; + 1B65AFB2A2A54BD69FE9D4D3 /* MatchLiveAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7485A29DA1E4F7EB3D4116D /* MatchLiveAPI.swift */; }; + 1DF38DB813DC491C94C206CD /* SponsorElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EF4D8B887F6467699C4E184 /* SponsorElement.swift */; }; + 1F26CA550156447B89B3EC01 /* MatchLiveWordmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D5396F45B5E40B1B1787C6E /* MatchLiveWordmark.swift */; }; + 2094E19DDAD0464B9CED0495 /* ScoreActionDecodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9493EA978E6460FACFB7831 /* ScoreActionDecodeTests.swift */; }; + 228CC71E4BBA4CF0A7712FDD /* ApiInstantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EFBCE62B1AD4A318A676B29 /* ApiInstantTests.swift */; }; + 252646FBD7F94CCEB49EE534 /* ScoreController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78C62B9683F44AA2A14D424A /* ScoreController.swift */; }; + 255C09F3A1AB4FCC80DC403D /* KeepScreenOn.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56E3FD0A68DC4FB6BB6F5DC3 /* KeepScreenOn.swift */; }; + 2F05B27C846F4284A533573D /* AuthRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FF6D203D77042EBAF2DB51F /* AuthRepository.swift */; }; + 2F9195CCAE9949C087CECAA2 /* LiveScoreActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7122CAE2FBF04D59B28E3393 /* LiveScoreActions.swift */; }; + 33848EA261D540879BABC0EC /* LiveBroadcastCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35FA1B77E81F48C5B4E55CD9 /* LiveBroadcastCoordinator.swift */; }; + 344B17113ADF4C548146080C /* MatchLiveTv/Resources/Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4F01AFBFEF6044C68CB26E01 /* MatchLiveTv/Resources/Assets.xcassets */; }; + 34C4FE9AC892423FA42B0FA1 /* SessionRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87978C769F4E4D468052CC33 /* SessionRepository.swift */; }; + 3D6496F4394A4A8B8280CCD7 /* MatchStatusBadge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 351CF0707AD942A58C630254 /* MatchStatusBadge.swift */; }; + 412D04EC8F8344F3941D7774 /* ScoreRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB392D77E64247B3B093F616 /* ScoreRepository.swift */; }; + 44412124BE71497F89A100A7 /* OverlayState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A14E10B5AA8D45859AC6A1A4 /* OverlayState.swift */; }; + 4661478CC7C343379C100A7E /* MatchRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = E00E4AADECC140CDAD8C2AE6 /* MatchRepository.swift */; }; + 4B6FFF5D05164AE9AFB2833C /* StepMatchScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FCAE846D294A19A7981CA2 /* StepMatchScreen.swift */; }; + 4BF1F3719177402988F3E680 /* MatchLiveTvApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA1FADDBD6A478FBA4D4047 /* MatchLiveTvApp.swift */; }; + 4C2639442FE6D7CF0015AAF3 /* HaishinKit in Frameworks */ = {isa = PBXBuildFile; productRef = 363FFDAD444D4381B6D23159 /* HaishinKit */; }; + 4C2639452FE6D7CF0015AAF3 /* RTMPHaishinKit in Frameworks */ = {isa = PBXBuildFile; productRef = 3CEE882EC45E49D49BF6B568 /* RTMPHaishinKit */; }; + 4E3828F9935743CCB4B15F01 /* WizardComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 727F818455854A5C95A36750 /* WizardComponents.swift */; }; + 57499374CE314E5C9B19E857 /* OverlayLogoCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = A399280B3F39439986A8B8CA /* OverlayLogoCache.swift */; }; + 5A085BBBD09B49A98A261FD1 /* StepNetworkTestScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1575FE5CDD584E119971A738 /* StepNetworkTestScreen.swift */; }; + 5BD7A70803AE4BFCBED02E69 /* WizardSessionHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C680C09D954141B3992BAE /* WizardSessionHolder.swift */; }; + 62147CCDD37243B9AB328357 /* ColorHex.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2944504F54A4FFBBC27890E /* ColorHex.swift */; }; + 62F8E9A68AF84E04B5B25C0E /* LiveBroadcastEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03E8C38FF8F45E3B60876C4 /* LiveBroadcastEngine.swift */; }; + 6312973A866D4191BA2E2E5E /* BroadcastPermissions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B905649882624CD4BDFBAA1E /* BroadcastPermissions.swift */; }; + 64D51E5990C34E64BBDD6153 /* MediaUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F5C50636970455FBD3C4C90 /* MediaUrl.swift */; }; + 6F38CD1E29CE4EDF92D2FCBD /* AppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 218CB473E8054075A604031B /* AppConfig.swift */; }; + 70385A94466D4A2EA11DDB3B /* LivePreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9BE69BF72BE4435BEDA9133 /* LivePreviewView.swift */; }; + 71A4EBF7C11441ED8202C4A5 /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91EC9ED467E84061B684745A /* SplashScreen.swift */; }; + 72458A3A5D6D40D8B2B4362A /* ActionCableClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E73FCF20F1D4F148B9CD4B3 /* ActionCableClient.swift */; }; + 72B22BECDAD64FE88CD38A25 /* BroadcastOrientationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = FED568E49E4044838349A540 /* BroadcastOrientationPolicy.swift */; }; + 7360468C628E48AF950EF5CB /* StepTransmissionScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64DFCC6BD2024FDBAB16BB74 /* StepTransmissionScreen.swift */; }; + 7FAB1EF0F8D3459CB1A05CD5 /* OverlayCanvasRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F2481408D6640FB9CC2CB2F /* OverlayCanvasRenderer.swift */; }; + 844259AFBAF448C6ADBDE30C /* ApiDtos.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1AD2477B899435F8D082A92 /* ApiDtos.swift */; }; + 85680F15BAC247B1AA97DC4D /* MatchPrimaryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EB0CC339DE745259373D142 /* MatchPrimaryButton.swift */; }; + 871F7D73227B4E699B65FE3D /* TeamBrandingEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E32781A593654542B0650E57 /* TeamBrandingEditor.swift */; }; + 8B26B443AD5C4FF388D448F5 /* LiveBroadcastCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB5D916A7D894E119711065F /* LiveBroadcastCoordinatorTests.swift */; }; + 9187B987AC034AAD887F6393 /* BroadcastOrientationPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D291E7B6E7644EC49B08B1E3 /* BroadcastOrientationPolicyTests.swift */; }; + 942E7C8159B2490A9058D20A /* MatchScreenScaffold.swift in Sources */ = {isa = PBXBuildFile; fileRef = 324AD8EC837D48F5B6FFCEAA /* MatchScreenScaffold.swift */; }; + 953EFFA2B63946A0818C82A1 /* CompactScoreboardElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 994567EE1DE14A20B92F4E96 /* CompactScoreboardElement.swift */; }; + A5767FD88F8D4123A68224CD /* BroadcastScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72E46A99EFD841C5A1647DB8 /* BroadcastScreen.swift */; }; + ABA512B1D2C7407E892623DE /* WatermarkElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16A9445555754FB7BDAADD3A /* WatermarkElement.swift */; }; + AD41DBD5504E4D3CB34B81B1 /* OverlayMappings.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC64A2E1500E4ADB9ACE1A86 /* OverlayMappings.swift */; }; + AD9A1CB58F8C44EC92C5B4AE /* MatchScoringRules.swift in Sources */ = {isa = PBXBuildFile; fileRef = B820270757EE42759E42FEEE /* MatchScoringRules.swift */; }; + ADA537BB60354316AB3D343D /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 500277E50C1A4646920A8543 /* Models.swift */; }; + B6CA255BE2A840A7B21CDCCB /* ShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 638CBB9E0E874F7F95CBE204 /* ShareSheet.swift */; }; + B9DFB757CD3942AEBC1953F0 /* WizardShellScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828F33DF188D43AFB37FB0FE /* WizardShellScreen.swift */; }; + BCA11E5347BE4070B1883A58 /* AppNavHost.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90C96BCB45B4C70A4EFEDDA /* AppNavHost.swift */; }; + BDAA05C294674E0A837D27AB /* MatchSecondaryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8363E5303ADB4FD78519684F /* MatchSecondaryButton.swift */; }; + BDF21E4064AC48D2BF2D3182 /* MatchSessionLauncher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99BA29C831B4470DB25B2180 /* MatchSessionLauncher.swift */; }; + C0E26D8B51484304B9234F89 /* BroadcastModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0E9DB4FB233435987DE957D /* BroadcastModels.swift */; }; + C2479C699DF24364951AFFEC /* Routes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AB101F16AF1494E8A143D0A /* Routes.swift */; }; + C6B8E801C3E449ABBFA44F33 /* MatchColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33DE04949BC459E88BE9366 /* MatchColors.swift */; }; + D44A9E22D1C241EA83B7A897 /* BroadcastVideoOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0997030621F749A3B9CDF588 /* BroadcastVideoOrientation.swift */; }; + D4EED1F5722B435695F1C09D /* ScreenOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E331937B64477698ACF9B4 /* ScreenOrientation.swift */; }; + D6ED4D033BA74DFFA968FC50 /* OverlayRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE8079EC41BD47469013C0B2 /* OverlayRenderer.swift */; }; + D74402BB72E04D8A816BC980 /* SessionCableService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 153C1BAFFFD94507B3F4960D /* SessionCableService.swift */; }; + DAA27DA77F904BA9B59684B1 /* ScoreboardElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0128206567441BB807BB13 /* ScoreboardElement.swift */; }; + DF8D47F8D9604F60B03E87F2 /* AppContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF647CAD4FA457A8F37C5F0 /* AppContainer.swift */; }; + E2D089A57F9F49D887C0D233 /* ModalRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9818CDD6BBDF4E68B2F56E32 /* ModalRoutes.swift */; }; + E2E74A83D86544BA8FB85AAB /* TeamColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6338B84D52DA4FBA93DAE49A /* TeamColorPicker.swift */; }; + E8D2C2E91DBE41BB9A1B59AF /* UserFacingError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E556E7CE8E4407B926500E /* UserFacingError.swift */; }; + F3907C6CC01447B786FF633F /* MatchesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8258C8C208E4AE2B37636E8 /* MatchesScreen.swift */; }; + FB09138978B3408ABBE91CD9 /* ScoreControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7814A010936047EBB4193446 /* ScoreControllerTests.swift */; }; + FEE2AE0621F94EA393524C47 /* LiveScoreDialogHostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 740D32B076064CCDBE6A688F /* LiveScoreDialogHostTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - ACB2FE70CE4841CCB7A0ACC7 /* PBXContainerItemProxy */ = { + 90C62964E51147DCABB6E3C2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 76FC637A5DFB4F018A0D1441 /* Project object */; + containerPortal = DBE4153B1FC34F91BC390462 /* Project object */; proxyType = 1; - remoteGlobalIDString = AE6E9D532CE6492D8B82687F; + remoteGlobalIDString = 2F039DD838234B1F9B1B2FF5; remoteInfo = MatchLiveTv; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0487DB6D2DEB4508B5EF5FCC /* MediaUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MediaUrl.swift; path = MatchLiveTv/Core/MediaUrl.swift; sourceTree = ""; }; - 049297E3B0D44FF8840B8E76 /* MatchScoringRulesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchScoringRulesTests.swift; path = MatchLiveTvTests/MatchScoringRulesTests.swift; sourceTree = ""; }; - 07588FE10B4143D8971F8A1F /* AppConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppConfig.swift; path = MatchLiveTv/Core/AppConfig.swift; sourceTree = ""; }; - 1144C664590842258CBE9998 /* MatchSecondaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchSecondaryButton.swift; path = MatchLiveTv/UI/Components/MatchSecondaryButton.swift; sourceTree = ""; }; - 134FD1D616EF4F82A0175E28 /* ScoreState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreState.swift; path = MatchLiveTv/Domain/ScoreState.swift; sourceTree = ""; }; - 1C3663CA3AD648B48EA4405D /* SessionRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SessionRepository.swift; path = MatchLiveTv/Data/Repository/SessionRepository.swift; sourceTree = ""; }; - 1C58DA984475413DB55C3E1B /* ScoreControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreControllerTests.swift; path = MatchLiveTvTests/ScoreControllerTests.swift; sourceTree = ""; }; - 224057D043A541C287071B37 /* OverlayLogoCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayLogoCache.swift; path = MatchLiveTv/Streaming/Overlay/OverlayLogoCache.swift; sourceTree = ""; }; - 290C51105D0B4ABE997FA155 /* Routes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Routes.swift; path = MatchLiveTv/UI/Navigation/Routes.swift; sourceTree = ""; }; - 2C3A3F3250284150B0A0BCD4 /* ModalRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ModalRoutes.swift; path = MatchLiveTv/UI/Navigation/ModalRoutes.swift; sourceTree = ""; }; - 36263581FBC9465FB59A54A3 /* MatchPrimaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchPrimaryButton.swift; path = MatchLiveTv/UI/Components/MatchPrimaryButton.swift; sourceTree = ""; }; - 3C5ECE7DA4A94297899495FF /* UserFacingError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = UserFacingError.swift; path = MatchLiveTv/Core/UserFacingError.swift; sourceTree = ""; }; - 40924F02DDFA4CCDA9488D64 /* MatchesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchesScreen.swift; path = MatchLiveTv/UI/Matches/MatchesScreen.swift; sourceTree = ""; }; - 44FFA851A3BC44A784DF353A /* BroadcastPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastPermissions.swift; path = MatchLiveTv/UI/Permissions/BroadcastPermissions.swift; sourceTree = ""; }; - 4570572C5D4745A990B291D6 /* MatchHubFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchHubFilter.swift; path = MatchLiveTv/Domain/MatchHubFilter.swift; sourceTree = ""; }; - 45C19E63F6E14B8A9B34AD29 /* MatchLiveTvTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MatchLiveTvTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 4974F7EF092B4FC697A30E00 /* MatchScoringRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchScoringRules.swift; path = MatchLiveTv/Domain/MatchScoringRules.swift; sourceTree = ""; }; - 4B469A9557164A2682CEA145 /* StepMatchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StepMatchScreen.swift; path = MatchLiveTv/UI/Wizard/StepMatchScreen.swift; sourceTree = ""; }; - 691EB1B5F9EA4DFB902E0D37 /* ApiInstant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ApiInstant.swift; path = MatchLiveTv/Core/ApiInstant.swift; sourceTree = ""; }; - 6E0E8585555C42A6A220FF29 /* BroadcastControlsOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastControlsOverlay.swift; path = MatchLiveTv/UI/Broadcast/BroadcastControlsOverlay.swift; sourceTree = ""; }; - 6EA61FF84F91473DA84438A8 /* ScoreboardElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreboardElement.swift; path = MatchLiveTv/Streaming/Overlay/ScoreboardElement.swift; sourceTree = ""; }; - 6F6D45B70859402BA3ABD014 /* TeamColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TeamColorPicker.swift; path = MatchLiveTv/UI/Wizard/TeamColorPicker.swift; sourceTree = ""; }; - 74D13551050B4A51A21B0A67 /* StepTransmissionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StepTransmissionScreen.swift; path = MatchLiveTv/UI/Wizard/StepTransmissionScreen.swift; sourceTree = ""; }; - 74D65108DA4C4A5BB95C0E51 /* SplashScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SplashScreen.swift; path = MatchLiveTv/UI/Splash/SplashScreen.swift; sourceTree = ""; }; - 76B77E9A6C51421D9AEDFF51 /* MatchRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchRepository.swift; path = MatchLiveTv/Data/Repository/MatchRepository.swift; sourceTree = ""; }; - 7B2349A6BFDD4708B821C659 /* MatchColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchColors.swift; path = MatchLiveTv/UI/Theme/MatchColors.swift; sourceTree = ""; }; - 7B9968E881924270973373DD /* CompactScoreboardElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompactScoreboardElement.swift; path = MatchLiveTv/Streaming/Overlay/CompactScoreboardElement.swift; sourceTree = ""; }; - 8799BE797C4B4A409E32E753 /* SponsorElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SponsorElement.swift; path = MatchLiveTv/Streaming/Overlay/SponsorElement.swift; sourceTree = ""; }; - 88C71579DA2945D5B0FA780C /* ScoreController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreController.swift; path = MatchLiveTv/Data/Scoring/ScoreController.swift; sourceTree = ""; }; - 8DBA84B5B0CA459E89779309 /* WatermarkElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WatermarkElement.swift; path = MatchLiveTv/Streaming/Overlay/WatermarkElement.swift; sourceTree = ""; }; - 96BA0FAD47DC40D48F063FC8 /* ScoreActionDecodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreActionDecodeTests.swift; path = MatchLiveTvTests/ScoreActionDecodeTests.swift; sourceTree = ""; }; - 96E61E730231499C9F119309 /* WizardShellScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WizardShellScreen.swift; path = MatchLiveTv/UI/Wizard/WizardShellScreen.swift; sourceTree = ""; }; - 9AC1BB5EDAEE43359749B95A /* TeamBrandingEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TeamBrandingEditor.swift; path = MatchLiveTv/UI/Wizard/TeamBrandingEditor.swift; sourceTree = ""; }; - 9BCA039B9842405DBCB38BA5 /* MatchLiveAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchLiveAPI.swift; path = MatchLiveTv/Data/API/MatchLiveAPI.swift; sourceTree = ""; }; - 9C0FE41B109A41519495E952 /* ApiInstantTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ApiInstantTests.swift; path = MatchLiveTvTests/ApiInstantTests.swift; sourceTree = ""; }; - A0DC8A3443404B0CAD323B11 /* KeepScreenOn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = KeepScreenOn.swift; path = MatchLiveTv/UI/System/KeepScreenOn.swift; sourceTree = ""; }; - A3B41DFCE8AF4993A93F756A /* AppNavHost.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppNavHost.swift; path = MatchLiveTv/UI/Navigation/AppNavHost.swift; sourceTree = ""; }; - A62D39BF1BD343E2B314A150 /* AppContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppContainer.swift; path = MatchLiveTv/Data/AppContainer.swift; sourceTree = ""; }; - A8FE87562E85488A946F8C86 /* MatchScreenScaffold.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchScreenScaffold.swift; path = MatchLiveTv/UI/Components/MatchScreenScaffold.swift; sourceTree = ""; }; - AAB84103176746DB89E76F33 /* MatchLiveTv.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MatchLiveTv.app; sourceTree = BUILT_PRODUCTS_DIR; }; - B1123FED73ED4983BFBE9BB6 /* LivePreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LivePreviewView.swift; path = MatchLiveTv/Streaming/Preview/LivePreviewView.swift; sourceTree = ""; }; - B43DEDBA98F24BE996528018 /* BroadcastOrientationPolicyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastOrientationPolicyTests.swift; path = MatchLiveTvTests/BroadcastOrientationPolicyTests.swift; sourceTree = ""; }; - BA7FA4E0FD3142D9957B764F /* MatchStatusBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchStatusBadge.swift; path = MatchLiveTv/UI/Components/MatchStatusBadge.swift; sourceTree = ""; }; - BA8EB774A34C4E259AFB1C88 /* ScoreRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreRepository.swift; path = MatchLiveTv/Data/Repository/ScoreRepository.swift; sourceTree = ""; }; - BC5C7905A24E4AE1A0600511 /* DeviceTelemetry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeviceTelemetry.swift; path = MatchLiveTv/Core/DeviceTelemetry.swift; sourceTree = ""; }; - BC65D1EBC15F4ECB921A94F5 /* BroadcastModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastModels.swift; path = MatchLiveTv/Streaming/BroadcastModels.swift; sourceTree = ""; }; - BE69B3EE8D0E4D8EAA8B853B /* MatchLiveWordmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchLiveWordmark.swift; path = MatchLiveTv/UI/Components/MatchLiveWordmark.swift; sourceTree = ""; }; - C3458504736B4137A749812C /* MatchLiveTvApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchLiveTvApp.swift; path = MatchLiveTv/App/MatchLiveTvApp.swift; sourceTree = ""; }; - C397B3162F38497C9AD0C9CF /* OverlayRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayRenderer.swift; path = MatchLiveTv/Streaming/Overlay/OverlayRenderer.swift; sourceTree = ""; }; - C561AB7965264974822DBD60 /* OverlayCanvasRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayCanvasRenderer.swift; path = MatchLiveTv/Streaming/Overlay/OverlayCanvasRenderer.swift; sourceTree = ""; }; - C7D1C27A80A842A1B531051C /* LiveScoreActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveScoreActions.swift; path = MatchLiveTv/UI/Broadcast/LiveScoreActions.swift; sourceTree = ""; }; - C8AA247685DD45FD980465B0 /* SessionCableService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SessionCableService.swift; path = MatchLiveTv/Data/Cable/SessionCableService.swift; sourceTree = ""; }; - C8D2302B51D94A8984EC6A56 /* TokenStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TokenStore.swift; path = MatchLiveTv/Core/TokenStore.swift; sourceTree = ""; }; - CBA94A102E6C4E1BAF934D53 /* BroadcastVideoOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastVideoOrientation.swift; path = MatchLiveTv/Streaming/BroadcastVideoOrientation.swift; sourceTree = ""; }; - CD491B8176A0430A9C3AB7B9 /* LiveBroadcastEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveBroadcastEngine.swift; path = MatchLiveTv/Streaming/LiveBroadcastEngine.swift; sourceTree = ""; }; - D17AB6B00BBC4568A6D0457E /* Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Models.swift; path = MatchLiveTv/Domain/Models.swift; sourceTree = ""; }; - D36C4F09E5D04392B0B82EF8 /* ActionCableClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ActionCableClient.swift; path = MatchLiveTv/Data/Cable/ActionCableClient.swift; sourceTree = ""; }; - D4CD1243AC3D4BB8815BBE83 /* MatchLiveTv/Resources/Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = MatchLiveTv/Resources/Info.plist; sourceTree = ""; }; - D603A791C926456D9B565F78 /* ShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ShareSheet.swift; path = MatchLiveTv/UI/System/ShareSheet.swift; sourceTree = ""; }; - D9316C1429F9448ABC7BA7B6 /* MatchSessionLauncher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchSessionLauncher.swift; path = MatchLiveTv/Data/Repository/MatchSessionLauncher.swift; sourceTree = ""; }; - DE44F992D17E408D8713CC95 /* OverlayState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayState.swift; path = MatchLiveTv/Streaming/Overlay/OverlayState.swift; sourceTree = ""; }; - E0B5292C4B7344E98043FA55 /* AuthRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AuthRepository.swift; path = MatchLiveTv/Data/Repository/AuthRepository.swift; sourceTree = ""; }; - E31852C7972040328E39C991 /* ScreenOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScreenOrientation.swift; path = MatchLiveTv/UI/System/ScreenOrientation.swift; sourceTree = ""; }; - E4770AC3C14D451F89B35533 /* ColorHex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ColorHex.swift; path = MatchLiveTv/Core/ColorHex.swift; sourceTree = ""; }; - E8E0CCB4B0554F96B04BDB07 /* LiveBroadcastCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveBroadcastCoordinator.swift; path = MatchLiveTv/Streaming/LiveBroadcastCoordinator.swift; sourceTree = ""; }; - E94110FC43754C50AC862D5C /* BroadcastScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastScreen.swift; path = MatchLiveTv/UI/Broadcast/BroadcastScreen.swift; sourceTree = ""; }; - EAEE3C8BBB684FEBA230480A /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LoginScreen.swift; path = MatchLiveTv/UI/Login/LoginScreen.swift; sourceTree = ""; }; - EB11018606164DAFBDC4E7A1 /* LiveBroadcastCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveBroadcastCoordinatorTests.swift; path = MatchLiveTvTests/LiveBroadcastCoordinatorTests.swift; sourceTree = ""; }; - EBD03F804A944D6D84464875 /* BroadcastOrientationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastOrientationPolicy.swift; path = MatchLiveTv/Streaming/BroadcastOrientationPolicy.swift; sourceTree = ""; }; - F0D156DFC16945A3A8467EF0 /* StepNetworkTestScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StepNetworkTestScreen.swift; path = MatchLiveTv/UI/Wizard/StepNetworkTestScreen.swift; sourceTree = ""; }; - F3490DEC22A543F890FEA661 /* WizardComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WizardComponents.swift; path = MatchLiveTv/UI/Wizard/WizardComponents.swift; sourceTree = ""; }; - F3DF95A27A584535A1511035 /* ApiDtos.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ApiDtos.swift; path = MatchLiveTv/Data/API/ApiDtos.swift; sourceTree = ""; }; - F42DAF0103FD4213BE778C7C /* LiveScoreDialogHostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveScoreDialogHostTests.swift; path = MatchLiveTvTests/LiveScoreDialogHostTests.swift; sourceTree = ""; }; - FC8DDF8DE68C4281B9062AD0 /* OverlayMappings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayMappings.swift; path = MatchLiveTv/Streaming/Overlay/OverlayMappings.swift; sourceTree = ""; }; - FE0CBD099ED14E62B752AB7F /* MatchLiveTv/Resources/Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = MatchLiveTv/Resources/Assets.xcassets; sourceTree = ""; }; - FF24FBB15BA4493EAEA78436 /* WizardSessionHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WizardSessionHolder.swift; path = MatchLiveTv/Data/WizardSessionHolder.swift; sourceTree = ""; }; + 0997030621F749A3B9CDF588 /* BroadcastVideoOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastVideoOrientation.swift; path = MatchLiveTv/Streaming/BroadcastVideoOrientation.swift; sourceTree = ""; }; + 0FF6D203D77042EBAF2DB51F /* AuthRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AuthRepository.swift; path = MatchLiveTv/Data/Repository/AuthRepository.swift; sourceTree = ""; }; + 153C1BAFFFD94507B3F4960D /* SessionCableService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SessionCableService.swift; path = MatchLiveTv/Data/Cable/SessionCableService.swift; sourceTree = ""; }; + 1575FE5CDD584E119971A738 /* StepNetworkTestScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StepNetworkTestScreen.swift; path = MatchLiveTv/UI/Wizard/StepNetworkTestScreen.swift; sourceTree = ""; }; + 16A9445555754FB7BDAADD3A /* WatermarkElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WatermarkElement.swift; path = MatchLiveTv/Streaming/Overlay/WatermarkElement.swift; sourceTree = ""; }; + 218CB473E8054075A604031B /* AppConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppConfig.swift; path = MatchLiveTv/Core/AppConfig.swift; sourceTree = ""; }; + 2D5396F45B5E40B1B1787C6E /* MatchLiveWordmark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchLiveWordmark.swift; path = MatchLiveTv/UI/Components/MatchLiveWordmark.swift; sourceTree = ""; }; + 324AD8EC837D48F5B6FFCEAA /* MatchScreenScaffold.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchScreenScaffold.swift; path = MatchLiveTv/UI/Components/MatchScreenScaffold.swift; sourceTree = ""; }; + 351CF0707AD942A58C630254 /* MatchStatusBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchStatusBadge.swift; path = MatchLiveTv/UI/Components/MatchStatusBadge.swift; sourceTree = ""; }; + 358F960727AF4821B82A7791 /* MatchLiveTv/Resources/Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = MatchLiveTv/Resources/Info.plist; sourceTree = ""; }; + 35FA1B77E81F48C5B4E55CD9 /* LiveBroadcastCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveBroadcastCoordinator.swift; path = MatchLiveTv/Streaming/LiveBroadcastCoordinator.swift; sourceTree = ""; }; + 38E556E7CE8E4407B926500E /* UserFacingError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = UserFacingError.swift; path = MatchLiveTv/Core/UserFacingError.swift; sourceTree = ""; }; + 3AB101F16AF1494E8A143D0A /* Routes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Routes.swift; path = MatchLiveTv/UI/Navigation/Routes.swift; sourceTree = ""; }; + 3E73FCF20F1D4F148B9CD4B3 /* ActionCableClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ActionCableClient.swift; path = MatchLiveTv/Data/Cable/ActionCableClient.swift; sourceTree = ""; }; + 3EF4D8B887F6467699C4E184 /* SponsorElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SponsorElement.swift; path = MatchLiveTv/Streaming/Overlay/SponsorElement.swift; sourceTree = ""; }; + 4BA1FADDBD6A478FBA4D4047 /* MatchLiveTvApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchLiveTvApp.swift; path = MatchLiveTv/App/MatchLiveTvApp.swift; sourceTree = ""; }; + 4C77C273929F4A4A9079A55E /* LoginScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LoginScreen.swift; path = MatchLiveTv/UI/Login/LoginScreen.swift; sourceTree = ""; }; + 4F01AFBFEF6044C68CB26E01 /* MatchLiveTv/Resources/Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = MatchLiveTv/Resources/Assets.xcassets; sourceTree = ""; }; + 500277E50C1A4646920A8543 /* Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Models.swift; path = MatchLiveTv/Domain/Models.swift; sourceTree = ""; }; + 51257C93F3A4464F8AA4B5B5 /* MatchScoringRulesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchScoringRulesTests.swift; path = MatchLiveTvTests/MatchScoringRulesTests.swift; sourceTree = ""; }; + 56E3FD0A68DC4FB6BB6F5DC3 /* KeepScreenOn.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = KeepScreenOn.swift; path = MatchLiveTv/UI/System/KeepScreenOn.swift; sourceTree = ""; }; + 60E331937B64477698ACF9B4 /* ScreenOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScreenOrientation.swift; path = MatchLiveTv/UI/System/ScreenOrientation.swift; sourceTree = ""; }; + 6338B84D52DA4FBA93DAE49A /* TeamColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TeamColorPicker.swift; path = MatchLiveTv/UI/Wizard/TeamColorPicker.swift; sourceTree = ""; }; + 638CBB9E0E874F7F95CBE204 /* ShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ShareSheet.swift; path = MatchLiveTv/UI/System/ShareSheet.swift; sourceTree = ""; }; + 64DFCC6BD2024FDBAB16BB74 /* StepTransmissionScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StepTransmissionScreen.swift; path = MatchLiveTv/UI/Wizard/StepTransmissionScreen.swift; sourceTree = ""; }; + 6EB0CC339DE745259373D142 /* MatchPrimaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchPrimaryButton.swift; path = MatchLiveTv/UI/Components/MatchPrimaryButton.swift; sourceTree = ""; }; + 6F2481408D6640FB9CC2CB2F /* OverlayCanvasRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayCanvasRenderer.swift; path = MatchLiveTv/Streaming/Overlay/OverlayCanvasRenderer.swift; sourceTree = ""; }; + 7122CAE2FBF04D59B28E3393 /* LiveScoreActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveScoreActions.swift; path = MatchLiveTv/UI/Broadcast/LiveScoreActions.swift; sourceTree = ""; }; + 727F818455854A5C95A36750 /* WizardComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WizardComponents.swift; path = MatchLiveTv/UI/Wizard/WizardComponents.swift; sourceTree = ""; }; + 72E46A99EFD841C5A1647DB8 /* BroadcastScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastScreen.swift; path = MatchLiveTv/UI/Broadcast/BroadcastScreen.swift; sourceTree = ""; }; + 740D32B076064CCDBE6A688F /* LiveScoreDialogHostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveScoreDialogHostTests.swift; path = MatchLiveTvTests/LiveScoreDialogHostTests.swift; sourceTree = ""; }; + 7814A010936047EBB4193446 /* ScoreControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreControllerTests.swift; path = MatchLiveTvTests/ScoreControllerTests.swift; sourceTree = ""; }; + 78C62B9683F44AA2A14D424A /* ScoreController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreController.swift; path = MatchLiveTv/Data/Scoring/ScoreController.swift; sourceTree = ""; }; + 7C298D589A644368A5B3DB79 /* MatchHubFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchHubFilter.swift; path = MatchLiveTv/Domain/MatchHubFilter.swift; sourceTree = ""; }; + 7F5C50636970455FBD3C4C90 /* MediaUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MediaUrl.swift; path = MatchLiveTv/Core/MediaUrl.swift; sourceTree = ""; }; + 828F33DF188D43AFB37FB0FE /* WizardShellScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WizardShellScreen.swift; path = MatchLiveTv/UI/Wizard/WizardShellScreen.swift; sourceTree = ""; }; + 8363E5303ADB4FD78519684F /* MatchSecondaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchSecondaryButton.swift; path = MatchLiveTv/UI/Components/MatchSecondaryButton.swift; sourceTree = ""; }; + 87978C769F4E4D468052CC33 /* SessionRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SessionRepository.swift; path = MatchLiveTv/Data/Repository/SessionRepository.swift; sourceTree = ""; }; + 8F0128206567441BB807BB13 /* ScoreboardElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreboardElement.swift; path = MatchLiveTv/Streaming/Overlay/ScoreboardElement.swift; sourceTree = ""; }; + 8FF647CAD4FA457A8F37C5F0 /* AppContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppContainer.swift; path = MatchLiveTv/Data/AppContainer.swift; sourceTree = ""; }; + 91EC9ED467E84061B684745A /* SplashScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SplashScreen.swift; path = MatchLiveTv/UI/Splash/SplashScreen.swift; sourceTree = ""; }; + 9818CDD6BBDF4E68B2F56E32 /* ModalRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ModalRoutes.swift; path = MatchLiveTv/UI/Navigation/ModalRoutes.swift; sourceTree = ""; }; + 994567EE1DE14A20B92F4E96 /* CompactScoreboardElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CompactScoreboardElement.swift; path = MatchLiveTv/Streaming/Overlay/CompactScoreboardElement.swift; sourceTree = ""; }; + 99BA29C831B4470DB25B2180 /* MatchSessionLauncher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchSessionLauncher.swift; path = MatchLiveTv/Data/Repository/MatchSessionLauncher.swift; sourceTree = ""; }; + 9EFBCE62B1AD4A318A676B29 /* ApiInstantTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ApiInstantTests.swift; path = MatchLiveTvTests/ApiInstantTests.swift; sourceTree = ""; }; + A0E9DB4FB233435987DE957D /* BroadcastModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastModels.swift; path = MatchLiveTv/Streaming/BroadcastModels.swift; sourceTree = ""; }; + A14E10B5AA8D45859AC6A1A4 /* OverlayState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayState.swift; path = MatchLiveTv/Streaming/Overlay/OverlayState.swift; sourceTree = ""; }; + A1AD2477B899435F8D082A92 /* ApiDtos.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ApiDtos.swift; path = MatchLiveTv/Data/API/ApiDtos.swift; sourceTree = ""; }; + A2DCC5443E58454998461BDB /* MatchLiveTv.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MatchLiveTv.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A399280B3F39439986A8B8CA /* OverlayLogoCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayLogoCache.swift; path = MatchLiveTv/Streaming/Overlay/OverlayLogoCache.swift; sourceTree = ""; }; + A5FCAE846D294A19A7981CA2 /* StepMatchScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StepMatchScreen.swift; path = MatchLiveTv/UI/Wizard/StepMatchScreen.swift; sourceTree = ""; }; + A9BE69BF72BE4435BEDA9133 /* LivePreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LivePreviewView.swift; path = MatchLiveTv/Streaming/Preview/LivePreviewView.swift; sourceTree = ""; }; + B2944504F54A4FFBBC27890E /* ColorHex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ColorHex.swift; path = MatchLiveTv/Core/ColorHex.swift; sourceTree = ""; }; + B7485A29DA1E4F7EB3D4116D /* MatchLiveAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchLiveAPI.swift; path = MatchLiveTv/Data/API/MatchLiveAPI.swift; sourceTree = ""; }; + B820270757EE42759E42FEEE /* MatchScoringRules.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchScoringRules.swift; path = MatchLiveTv/Domain/MatchScoringRules.swift; sourceTree = ""; }; + B8258C8C208E4AE2B37636E8 /* MatchesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchesScreen.swift; path = MatchLiveTv/UI/Matches/MatchesScreen.swift; sourceTree = ""; }; + B905649882624CD4BDFBAA1E /* BroadcastPermissions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastPermissions.swift; path = MatchLiveTv/UI/Permissions/BroadcastPermissions.swift; sourceTree = ""; }; + BB5D916A7D894E119711065F /* LiveBroadcastCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveBroadcastCoordinatorTests.swift; path = MatchLiveTvTests/LiveBroadcastCoordinatorTests.swift; sourceTree = ""; }; + C33DE04949BC459E88BE9366 /* MatchColors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchColors.swift; path = MatchLiveTv/UI/Theme/MatchColors.swift; sourceTree = ""; }; + C7B37C6177BA4FC7AD4DE2C9 /* ScoreState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreState.swift; path = MatchLiveTv/Domain/ScoreState.swift; sourceTree = ""; }; + C90C96BCB45B4C70A4EFEDDA /* AppNavHost.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppNavHost.swift; path = MatchLiveTv/UI/Navigation/AppNavHost.swift; sourceTree = ""; }; + CC64A2E1500E4ADB9ACE1A86 /* OverlayMappings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayMappings.swift; path = MatchLiveTv/Streaming/Overlay/OverlayMappings.swift; sourceTree = ""; }; + CE8079EC41BD47469013C0B2 /* OverlayRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = OverlayRenderer.swift; path = MatchLiveTv/Streaming/Overlay/OverlayRenderer.swift; sourceTree = ""; }; + D291E7B6E7644EC49B08B1E3 /* BroadcastOrientationPolicyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastOrientationPolicyTests.swift; path = MatchLiveTvTests/BroadcastOrientationPolicyTests.swift; sourceTree = ""; }; + D6DC6A6529B74BACBD05E817 /* MatchLiveTvTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MatchLiveTvTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + D7C680C09D954141B3992BAE /* WizardSessionHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WizardSessionHolder.swift; path = MatchLiveTv/Data/WizardSessionHolder.swift; sourceTree = ""; }; + D9493EA978E6460FACFB7831 /* ScoreActionDecodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreActionDecodeTests.swift; path = MatchLiveTvTests/ScoreActionDecodeTests.swift; sourceTree = ""; }; + DB392D77E64247B3B093F616 /* ScoreRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ScoreRepository.swift; path = MatchLiveTv/Data/Repository/ScoreRepository.swift; sourceTree = ""; }; + E00E4AADECC140CDAD8C2AE6 /* MatchRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MatchRepository.swift; path = MatchLiveTv/Data/Repository/MatchRepository.swift; sourceTree = ""; }; + E32781A593654542B0650E57 /* TeamBrandingEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TeamBrandingEditor.swift; path = MatchLiveTv/UI/Wizard/TeamBrandingEditor.swift; sourceTree = ""; }; + E6CC04AA64F244128D7069F7 /* TokenStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TokenStore.swift; path = MatchLiveTv/Core/TokenStore.swift; sourceTree = ""; }; + F03E8C38FF8F45E3B60876C4 /* LiveBroadcastEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LiveBroadcastEngine.swift; path = MatchLiveTv/Streaming/LiveBroadcastEngine.swift; sourceTree = ""; }; + F52E5A9320FD4A9C82C64092 /* ApiInstant.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ApiInstant.swift; path = MatchLiveTv/Core/ApiInstant.swift; sourceTree = ""; }; + F9652ABD17F34BF7B781F9CB /* BroadcastControlsOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastControlsOverlay.swift; path = MatchLiveTv/UI/Broadcast/BroadcastControlsOverlay.swift; sourceTree = ""; }; + FD66A152068843A89E25EA2A /* DeviceTelemetry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeviceTelemetry.swift; path = MatchLiveTv/Core/DeviceTelemetry.swift; sourceTree = ""; }; + FED568E49E4044838349A540 /* BroadcastOrientationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = BroadcastOrientationPolicy.swift; path = MatchLiveTv/Streaming/BroadcastOrientationPolicy.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 2DFB0C53187A482B83E1F38B /* Frameworks */ = { + EC74ACD5FC794566A431A35D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4C2639392FE6A0440015AAF3 /* RTMPHaishinKit in Frameworks */, - 4C2639382FE6A0440015AAF3 /* HaishinKit in Frameworks */, + 4C2639452FE6D7CF0015AAF3 /* RTMPHaishinKit in Frameworks */, + 4C2639442FE6D7CF0015AAF3 /* HaishinKit in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - C180AAFADE0640639A940144 /* Frameworks */ = { + F4997458E6A441FFAF9F30AD /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -193,108 +193,108 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 14EA3A4718794D36964484DB = { + 04C16256D74947F49F3C9F65 /* Products */ = { isa = PBXGroup; children = ( - EB01519A0F5446FABA7B5012 /* MatchLiveTv */, - C469ABBC533140A1A97C78AA /* MatchLiveTvTests */, - 6668FF0B6F2E4C60861A918C /* Products */, - ); - sourceTree = ""; - }; - 6668FF0B6F2E4C60861A918C /* Products */ = { - isa = PBXGroup; - children = ( - AAB84103176746DB89E76F33 /* MatchLiveTv.app */, - 45C19E63F6E14B8A9B34AD29 /* MatchLiveTvTests.xctest */, + A2DCC5443E58454998461BDB /* MatchLiveTv.app */, + D6DC6A6529B74BACBD05E817 /* MatchLiveTvTests.xctest */, ); name = Products; sourceTree = ""; }; - C469ABBC533140A1A97C78AA /* MatchLiveTvTests */ = { + 24B89ABF583C445F8BE6725C /* MatchLiveTvTests */ = { isa = PBXGroup; children = ( - 9C0FE41B109A41519495E952 /* ApiInstantTests.swift */, - B43DEDBA98F24BE996528018 /* BroadcastOrientationPolicyTests.swift */, - EB11018606164DAFBDC4E7A1 /* LiveBroadcastCoordinatorTests.swift */, - F42DAF0103FD4213BE778C7C /* LiveScoreDialogHostTests.swift */, - 049297E3B0D44FF8840B8E76 /* MatchScoringRulesTests.swift */, - 96BA0FAD47DC40D48F063FC8 /* ScoreActionDecodeTests.swift */, - 1C58DA984475413DB55C3E1B /* ScoreControllerTests.swift */, + 9EFBCE62B1AD4A318A676B29 /* ApiInstantTests.swift */, + D291E7B6E7644EC49B08B1E3 /* BroadcastOrientationPolicyTests.swift */, + BB5D916A7D894E119711065F /* LiveBroadcastCoordinatorTests.swift */, + 740D32B076064CCDBE6A688F /* LiveScoreDialogHostTests.swift */, + 51257C93F3A4464F8AA4B5B5 /* MatchScoringRulesTests.swift */, + D9493EA978E6460FACFB7831 /* ScoreActionDecodeTests.swift */, + 7814A010936047EBB4193446 /* ScoreControllerTests.swift */, ); name = MatchLiveTvTests; sourceTree = ""; }; - EB01519A0F5446FABA7B5012 /* MatchLiveTv */ = { + 64400CD6009C4B9FB7362229 = { isa = PBXGroup; children = ( - C3458504736B4137A749812C /* MatchLiveTvApp.swift */, - 691EB1B5F9EA4DFB902E0D37 /* ApiInstant.swift */, - 07588FE10B4143D8971F8A1F /* AppConfig.swift */, - E4770AC3C14D451F89B35533 /* ColorHex.swift */, - BC5C7905A24E4AE1A0600511 /* DeviceTelemetry.swift */, - 0487DB6D2DEB4508B5EF5FCC /* MediaUrl.swift */, - C8D2302B51D94A8984EC6A56 /* TokenStore.swift */, - 3C5ECE7DA4A94297899495FF /* UserFacingError.swift */, - F3DF95A27A584535A1511035 /* ApiDtos.swift */, - 9BCA039B9842405DBCB38BA5 /* MatchLiveAPI.swift */, - A62D39BF1BD343E2B314A150 /* AppContainer.swift */, - D36C4F09E5D04392B0B82EF8 /* ActionCableClient.swift */, - C8AA247685DD45FD980465B0 /* SessionCableService.swift */, - E0B5292C4B7344E98043FA55 /* AuthRepository.swift */, - 76B77E9A6C51421D9AEDFF51 /* MatchRepository.swift */, - D9316C1429F9448ABC7BA7B6 /* MatchSessionLauncher.swift */, - BA8EB774A34C4E259AFB1C88 /* ScoreRepository.swift */, - 1C3663CA3AD648B48EA4405D /* SessionRepository.swift */, - 88C71579DA2945D5B0FA780C /* ScoreController.swift */, - FF24FBB15BA4493EAEA78436 /* WizardSessionHolder.swift */, - 4570572C5D4745A990B291D6 /* MatchHubFilter.swift */, - 4974F7EF092B4FC697A30E00 /* MatchScoringRules.swift */, - D17AB6B00BBC4568A6D0457E /* Models.swift */, - 134FD1D616EF4F82A0175E28 /* ScoreState.swift */, - BC65D1EBC15F4ECB921A94F5 /* BroadcastModels.swift */, - EBD03F804A944D6D84464875 /* BroadcastOrientationPolicy.swift */, - CBA94A102E6C4E1BAF934D53 /* BroadcastVideoOrientation.swift */, - E8E0CCB4B0554F96B04BDB07 /* LiveBroadcastCoordinator.swift */, - CD491B8176A0430A9C3AB7B9 /* LiveBroadcastEngine.swift */, - 7B9968E881924270973373DD /* CompactScoreboardElement.swift */, - C561AB7965264974822DBD60 /* OverlayCanvasRenderer.swift */, - 224057D043A541C287071B37 /* OverlayLogoCache.swift */, - FC8DDF8DE68C4281B9062AD0 /* OverlayMappings.swift */, - C397B3162F38497C9AD0C9CF /* OverlayRenderer.swift */, - DE44F992D17E408D8713CC95 /* OverlayState.swift */, - 6EA61FF84F91473DA84438A8 /* ScoreboardElement.swift */, - 8799BE797C4B4A409E32E753 /* SponsorElement.swift */, - 8DBA84B5B0CA459E89779309 /* WatermarkElement.swift */, - B1123FED73ED4983BFBE9BB6 /* LivePreviewView.swift */, - 6E0E8585555C42A6A220FF29 /* BroadcastControlsOverlay.swift */, - E94110FC43754C50AC862D5C /* BroadcastScreen.swift */, - C7D1C27A80A842A1B531051C /* LiveScoreActions.swift */, - BE69B3EE8D0E4D8EAA8B853B /* MatchLiveWordmark.swift */, - 36263581FBC9465FB59A54A3 /* MatchPrimaryButton.swift */, - A8FE87562E85488A946F8C86 /* MatchScreenScaffold.swift */, - 1144C664590842258CBE9998 /* MatchSecondaryButton.swift */, - BA7FA4E0FD3142D9957B764F /* MatchStatusBadge.swift */, - EAEE3C8BBB684FEBA230480A /* LoginScreen.swift */, - 40924F02DDFA4CCDA9488D64 /* MatchesScreen.swift */, - A3B41DFCE8AF4993A93F756A /* AppNavHost.swift */, - 2C3A3F3250284150B0A0BCD4 /* ModalRoutes.swift */, - 290C51105D0B4ABE997FA155 /* Routes.swift */, - 44FFA851A3BC44A784DF353A /* BroadcastPermissions.swift */, - 74D65108DA4C4A5BB95C0E51 /* SplashScreen.swift */, - A0DC8A3443404B0CAD323B11 /* KeepScreenOn.swift */, - E31852C7972040328E39C991 /* ScreenOrientation.swift */, - D603A791C926456D9B565F78 /* ShareSheet.swift */, - 7B2349A6BFDD4708B821C659 /* MatchColors.swift */, - 4B469A9557164A2682CEA145 /* StepMatchScreen.swift */, - F0D156DFC16945A3A8467EF0 /* StepNetworkTestScreen.swift */, - 74D13551050B4A51A21B0A67 /* StepTransmissionScreen.swift */, - 9AC1BB5EDAEE43359749B95A /* TeamBrandingEditor.swift */, - 6F6D45B70859402BA3ABD014 /* TeamColorPicker.swift */, - F3490DEC22A543F890FEA661 /* WizardComponents.swift */, - 96E61E730231499C9F119309 /* WizardShellScreen.swift */, - FE0CBD099ED14E62B752AB7F /* MatchLiveTv/Resources/Assets.xcassets */, - D4CD1243AC3D4BB8815BBE83 /* MatchLiveTv/Resources/Info.plist */, + EA914F8374EB40228298872E /* MatchLiveTv */, + 24B89ABF583C445F8BE6725C /* MatchLiveTvTests */, + 04C16256D74947F49F3C9F65 /* Products */, + ); + sourceTree = ""; + }; + EA914F8374EB40228298872E /* MatchLiveTv */ = { + isa = PBXGroup; + children = ( + 4BA1FADDBD6A478FBA4D4047 /* MatchLiveTvApp.swift */, + F52E5A9320FD4A9C82C64092 /* ApiInstant.swift */, + 218CB473E8054075A604031B /* AppConfig.swift */, + B2944504F54A4FFBBC27890E /* ColorHex.swift */, + FD66A152068843A89E25EA2A /* DeviceTelemetry.swift */, + 7F5C50636970455FBD3C4C90 /* MediaUrl.swift */, + E6CC04AA64F244128D7069F7 /* TokenStore.swift */, + 38E556E7CE8E4407B926500E /* UserFacingError.swift */, + A1AD2477B899435F8D082A92 /* ApiDtos.swift */, + B7485A29DA1E4F7EB3D4116D /* MatchLiveAPI.swift */, + 8FF647CAD4FA457A8F37C5F0 /* AppContainer.swift */, + 3E73FCF20F1D4F148B9CD4B3 /* ActionCableClient.swift */, + 153C1BAFFFD94507B3F4960D /* SessionCableService.swift */, + 0FF6D203D77042EBAF2DB51F /* AuthRepository.swift */, + E00E4AADECC140CDAD8C2AE6 /* MatchRepository.swift */, + 99BA29C831B4470DB25B2180 /* MatchSessionLauncher.swift */, + DB392D77E64247B3B093F616 /* ScoreRepository.swift */, + 87978C769F4E4D468052CC33 /* SessionRepository.swift */, + 78C62B9683F44AA2A14D424A /* ScoreController.swift */, + D7C680C09D954141B3992BAE /* WizardSessionHolder.swift */, + 7C298D589A644368A5B3DB79 /* MatchHubFilter.swift */, + B820270757EE42759E42FEEE /* MatchScoringRules.swift */, + 500277E50C1A4646920A8543 /* Models.swift */, + C7B37C6177BA4FC7AD4DE2C9 /* ScoreState.swift */, + A0E9DB4FB233435987DE957D /* BroadcastModels.swift */, + FED568E49E4044838349A540 /* BroadcastOrientationPolicy.swift */, + 0997030621F749A3B9CDF588 /* BroadcastVideoOrientation.swift */, + 35FA1B77E81F48C5B4E55CD9 /* LiveBroadcastCoordinator.swift */, + F03E8C38FF8F45E3B60876C4 /* LiveBroadcastEngine.swift */, + 994567EE1DE14A20B92F4E96 /* CompactScoreboardElement.swift */, + 6F2481408D6640FB9CC2CB2F /* OverlayCanvasRenderer.swift */, + A399280B3F39439986A8B8CA /* OverlayLogoCache.swift */, + CC64A2E1500E4ADB9ACE1A86 /* OverlayMappings.swift */, + CE8079EC41BD47469013C0B2 /* OverlayRenderer.swift */, + A14E10B5AA8D45859AC6A1A4 /* OverlayState.swift */, + 8F0128206567441BB807BB13 /* ScoreboardElement.swift */, + 3EF4D8B887F6467699C4E184 /* SponsorElement.swift */, + 16A9445555754FB7BDAADD3A /* WatermarkElement.swift */, + A9BE69BF72BE4435BEDA9133 /* LivePreviewView.swift */, + F9652ABD17F34BF7B781F9CB /* BroadcastControlsOverlay.swift */, + 72E46A99EFD841C5A1647DB8 /* BroadcastScreen.swift */, + 7122CAE2FBF04D59B28E3393 /* LiveScoreActions.swift */, + 2D5396F45B5E40B1B1787C6E /* MatchLiveWordmark.swift */, + 6EB0CC339DE745259373D142 /* MatchPrimaryButton.swift */, + 324AD8EC837D48F5B6FFCEAA /* MatchScreenScaffold.swift */, + 8363E5303ADB4FD78519684F /* MatchSecondaryButton.swift */, + 351CF0707AD942A58C630254 /* MatchStatusBadge.swift */, + 4C77C273929F4A4A9079A55E /* LoginScreen.swift */, + B8258C8C208E4AE2B37636E8 /* MatchesScreen.swift */, + C90C96BCB45B4C70A4EFEDDA /* AppNavHost.swift */, + 9818CDD6BBDF4E68B2F56E32 /* ModalRoutes.swift */, + 3AB101F16AF1494E8A143D0A /* Routes.swift */, + B905649882624CD4BDFBAA1E /* BroadcastPermissions.swift */, + 91EC9ED467E84061B684745A /* SplashScreen.swift */, + 56E3FD0A68DC4FB6BB6F5DC3 /* KeepScreenOn.swift */, + 60E331937B64477698ACF9B4 /* ScreenOrientation.swift */, + 638CBB9E0E874F7F95CBE204 /* ShareSheet.swift */, + C33DE04949BC459E88BE9366 /* MatchColors.swift */, + A5FCAE846D294A19A7981CA2 /* StepMatchScreen.swift */, + 1575FE5CDD584E119971A738 /* StepNetworkTestScreen.swift */, + 64DFCC6BD2024FDBAB16BB74 /* StepTransmissionScreen.swift */, + E32781A593654542B0650E57 /* TeamBrandingEditor.swift */, + 6338B84D52DA4FBA93DAE49A /* TeamColorPicker.swift */, + 727F818455854A5C95A36750 /* WizardComponents.swift */, + 828F33DF188D43AFB37FB0FE /* WizardShellScreen.swift */, + 4F01AFBFEF6044C68CB26E01 /* MatchLiveTv/Resources/Assets.xcassets */, + 358F960727AF4821B82A7791 /* MatchLiveTv/Resources/Info.plist */, ); name = MatchLiveTv; sourceTree = ""; @@ -302,30 +302,13 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 64F84AC8A424490D945D5B65 /* MatchLiveTvTests */ = { + 2F039DD838234B1F9B1B2FF5 /* MatchLiveTv */ = { isa = PBXNativeTarget; - buildConfigurationList = E3DA5397819945D09DC337F6 /* Build configuration list for PBXNativeTarget "MatchLiveTvTests" */; + buildConfigurationList = 7F122D777A6E41C9BD148CDD /* Build configuration list for PBXNativeTarget "MatchLiveTv" */; buildPhases = ( - 3245C286B7A54008850C0923 /* Sources */, - C180AAFADE0640639A940144 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 4264391B98534ED485BCB343 /* PBXTargetDependency */, - ); - name = MatchLiveTvTests; - productName = MatchLiveTvTests; - productReference = 45C19E63F6E14B8A9B34AD29 /* MatchLiveTvTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - AE6E9D532CE6492D8B82687F /* MatchLiveTv */ = { - isa = PBXNativeTarget; - buildConfigurationList = 002C5EF177A5409AAE23DB38 /* Build configuration list for PBXNativeTarget "MatchLiveTv" */; - buildPhases = ( - AC8B6077C49C4F0086F06F1B /* Sources */, - 2DFB0C53187A482B83E1F38B /* Frameworks */, - 1C0CE5A5B45A41CBA8B910D1 /* Resources */, + AD28C1C2220D4921862D734A /* Sources */, + EC74ACD5FC794566A431A35D /* Frameworks */, + CA170C64969345F0974EA381 /* Resources */, ); buildRules = ( ); @@ -333,23 +316,40 @@ ); name = MatchLiveTv; packageProductDependencies = ( - DFA0D0CEB1F1428D9E3FB3DB /* HaishinKit */, - AA756D8C68BC4B3D8EC96D5E /* RTMPHaishinKit */, + 363FFDAD444D4381B6D23159 /* HaishinKit */, + 3CEE882EC45E49D49BF6B568 /* RTMPHaishinKit */, ); productName = MatchLiveTv; - productReference = AAB84103176746DB89E76F33 /* MatchLiveTv.app */; + productReference = A2DCC5443E58454998461BDB /* MatchLiveTv.app */; productType = "com.apple.product-type.application"; }; + F441C7131D0345549D8CA917 /* MatchLiveTvTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 271ADC46052246A38FB0DFCE /* Build configuration list for PBXNativeTarget "MatchLiveTvTests" */; + buildPhases = ( + 79D8DB6A21534CC695AEAAD3 /* Sources */, + F4997458E6A441FFAF9F30AD /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 953DB6F101304B388EBFB376 /* PBXTargetDependency */, + ); + name = MatchLiveTvTests; + productName = MatchLiveTvTests; + productReference = D6DC6A6529B74BACBD05E817 /* MatchLiveTvTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 76FC637A5DFB4F018A0D1441 /* Project object */ = { + DBE4153B1FC34F91BC390462 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 0; LastSwiftUpdateCheck = 1600; }; - buildConfigurationList = 27F2A4CC59994B3CA41841F5 /* Build configuration list for PBXProject "MatchLiveTv" */; + buildConfigurationList = 1E22BBCE2E7C4E1DBD22BF81 /* Build configuration list for PBXProject "MatchLiveTv" */; compatibilityVersion = "Xcode 15.0"; developmentRegion = it; hasScannedForEncodings = 0; @@ -358,130 +358,164 @@ en, Base, ); - mainGroup = 14EA3A4718794D36964484DB; + mainGroup = 64400CD6009C4B9FB7362229; packageReferences = ( - 2DAE333E666A41BE8A5F1148 /* XCRemoteSwiftPackageReference "HaishinKit" */, + 3FD2C0913F9E4659A9B8920D /* XCRemoteSwiftPackageReference "HaishinKit" */, ); - productRefGroup = 6668FF0B6F2E4C60861A918C /* Products */; + productRefGroup = 04C16256D74947F49F3C9F65 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - AE6E9D532CE6492D8B82687F /* MatchLiveTv */, - 64F84AC8A424490D945D5B65 /* MatchLiveTvTests */, + 2F039DD838234B1F9B1B2FF5 /* MatchLiveTv */, + F441C7131D0345549D8CA917 /* MatchLiveTvTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 1C0CE5A5B45A41CBA8B910D1 /* Resources */ = { + CA170C64969345F0974EA381 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - FE21BE8932864B5D96D1BA41 /* MatchLiveTv/Resources/Assets.xcassets in Resources */, + 344B17113ADF4C548146080C /* MatchLiveTv/Resources/Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 3245C286B7A54008850C0923 /* Sources */ = { + 79D8DB6A21534CC695AEAAD3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - EBB063DFDBE443F3BC12A67A /* ApiInstantTests.swift in Sources */, - 3AA28F966201426380DEE174 /* BroadcastOrientationPolicyTests.swift in Sources */, - 644B22C2C7E54983A6BE393D /* LiveBroadcastCoordinatorTests.swift in Sources */, - 4CD8A3EB76C14F878BF1026C /* LiveScoreDialogHostTests.swift in Sources */, - 35FE18027B054D5BBC20DC9C /* MatchScoringRulesTests.swift in Sources */, - 2498A1488A034D058E6997B0 /* ScoreActionDecodeTests.swift in Sources */, - 6C52A9292D694A728A372551 /* ScoreControllerTests.swift in Sources */, + 228CC71E4BBA4CF0A7712FDD /* ApiInstantTests.swift in Sources */, + 9187B987AC034AAD887F6393 /* BroadcastOrientationPolicyTests.swift in Sources */, + 8B26B443AD5C4FF388D448F5 /* LiveBroadcastCoordinatorTests.swift in Sources */, + FEE2AE0621F94EA393524C47 /* LiveScoreDialogHostTests.swift in Sources */, + 05E2509B1F96460F9A8FBDEE /* MatchScoringRulesTests.swift in Sources */, + 2094E19DDAD0464B9CED0495 /* ScoreActionDecodeTests.swift in Sources */, + FB09138978B3408ABBE91CD9 /* ScoreControllerTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - AC8B6077C49C4F0086F06F1B /* Sources */ = { + AD28C1C2220D4921862D734A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 5D4E00AC5D4E44A09E3743DE /* MatchLiveTvApp.swift in Sources */, - 82ADD6499C394031B87D7A96 /* ApiInstant.swift in Sources */, - D916D4368A9A4298BDB3430F /* AppConfig.swift in Sources */, - 994148BB9CCE4E6F800CD89A /* ColorHex.swift in Sources */, - 22A2A4F3BBD845C5B4E1DD6E /* DeviceTelemetry.swift in Sources */, - 6CA1DE649AEE455C994D0E94 /* MediaUrl.swift in Sources */, - 284F82D0FB65448BAB38C6BE /* TokenStore.swift in Sources */, - CAABC65179F6467996D85730 /* UserFacingError.swift in Sources */, - 2D3FAEEE0372415381467FC7 /* ApiDtos.swift in Sources */, - EB8D708E665A46B398EB0C4F /* MatchLiveAPI.swift in Sources */, - 52DCD38F408B4BAE8A0A673D /* AppContainer.swift in Sources */, - 39E01672805E4B8A88DA0FA9 /* ActionCableClient.swift in Sources */, - 48719B5718B2419E96AE6AF2 /* SessionCableService.swift in Sources */, - 9E770D39394E41838877BC62 /* AuthRepository.swift in Sources */, - D77980669AE84165AAF94AF2 /* MatchRepository.swift in Sources */, - 3027E88493BA43B09B150BA1 /* MatchSessionLauncher.swift in Sources */, - 0E03BE40DAF14E98A35051CE /* ScoreRepository.swift in Sources */, - 045086A670F24B1192E0DF8F /* SessionRepository.swift in Sources */, - 53A492E3510D4C8A9A5C94B7 /* ScoreController.swift in Sources */, - 5A8E598237CF41BFB62B83D8 /* WizardSessionHolder.swift in Sources */, - B3DD2F8E837649B2B007CEAF /* MatchHubFilter.swift in Sources */, - 6CC11041AFC64969BC9195D0 /* MatchScoringRules.swift in Sources */, - 8BAE2CEB56064BA3A3A16B53 /* Models.swift in Sources */, - EA533D28A4EF4171B410B56E /* ScoreState.swift in Sources */, - 96E2427E81E744289D1C9B9B /* BroadcastModels.swift in Sources */, - 9D241B051BD54105A9D764DD /* BroadcastOrientationPolicy.swift in Sources */, - 4BD05489BDAB4E309311B1C7 /* BroadcastVideoOrientation.swift in Sources */, - 991371D458954C06A798AC0E /* LiveBroadcastCoordinator.swift in Sources */, - 59BB3212FCBA4F68B23337F3 /* LiveBroadcastEngine.swift in Sources */, - D0BAD147978244529A46C040 /* CompactScoreboardElement.swift in Sources */, - EE689B65571A474CA19A792C /* OverlayCanvasRenderer.swift in Sources */, - 6E09F9E1FBB3459B94343BDD /* OverlayLogoCache.swift in Sources */, - 91C697AC57284A26A9893DFD /* OverlayMappings.swift in Sources */, - 4A6973ACDCA743B29ACC1E2E /* OverlayRenderer.swift in Sources */, - 7862CEBEB345430F908DE135 /* OverlayState.swift in Sources */, - 15EBD3E3D95D4AE5BABB6776 /* ScoreboardElement.swift in Sources */, - 7DCAA615F27C4853B8A0F889 /* SponsorElement.swift in Sources */, - 28A607B3D84448308B130ECF /* WatermarkElement.swift in Sources */, - AEE1728EFF3F491A81B1156B /* LivePreviewView.swift in Sources */, - 921A1A2729B244C08A9BD3FD /* BroadcastControlsOverlay.swift in Sources */, - C5EEE95F92D44046994659FC /* BroadcastScreen.swift in Sources */, - 191F31088FCE4A82932B6FBB /* LiveScoreActions.swift in Sources */, - 6DAD6078CC8D46FCB1AE0A75 /* MatchLiveWordmark.swift in Sources */, - D015D7ACCFE54071B1831C74 /* MatchPrimaryButton.swift in Sources */, - 91F1D3111F2C4BDFAB7435BF /* MatchScreenScaffold.swift in Sources */, - 464C286CAE724604AF9CC1FD /* MatchSecondaryButton.swift in Sources */, - F13DF021E1084F6C844CB7AB /* MatchStatusBadge.swift in Sources */, - 0CE091822CAA4D88B1BE3AF4 /* LoginScreen.swift in Sources */, - C6B059D6435243208A8FC338 /* MatchesScreen.swift in Sources */, - D501A7EE3BAD467A9A63E63C /* AppNavHost.swift in Sources */, - 138294291C614F218D71B1CD /* ModalRoutes.swift in Sources */, - D3C28481960E4E14A0909DCB /* Routes.swift in Sources */, - 30F21F19C7234BBF8B2B77D4 /* BroadcastPermissions.swift in Sources */, - 51B03D8318114D3AB94A41CA /* SplashScreen.swift in Sources */, - 08F123F9692D48EA94EBD94D /* KeepScreenOn.swift in Sources */, - 5E33700F7C694E9D8EC997D7 /* ScreenOrientation.swift in Sources */, - 3A08990CB238458CA25C07C9 /* ShareSheet.swift in Sources */, - 4598E75CCCF5492CB2F0B006 /* MatchColors.swift in Sources */, - 66539A1D77EA4B368F5BDE2E /* StepMatchScreen.swift in Sources */, - EF83C38F78144E0996C33807 /* StepNetworkTestScreen.swift in Sources */, - B7D592901EC34D4B97DCE549 /* StepTransmissionScreen.swift in Sources */, - F13AA7F009F1421FB996956B /* TeamBrandingEditor.swift in Sources */, - 00BDF215CB7942A799F06774 /* TeamColorPicker.swift in Sources */, - 7B4182E19F93484B8B0D07DF /* WizardComponents.swift in Sources */, - 4A67DD768F074E7885DFDF43 /* WizardShellScreen.swift in Sources */, + 4BF1F3719177402988F3E680 /* MatchLiveTvApp.swift in Sources */, + 0811090F35B647A9AAE98018 /* ApiInstant.swift in Sources */, + 6F38CD1E29CE4EDF92D2FCBD /* AppConfig.swift in Sources */, + 62147CCDD37243B9AB328357 /* ColorHex.swift in Sources */, + 1191C9F3433D4C79BB1D55CA /* DeviceTelemetry.swift in Sources */, + 64D51E5990C34E64BBDD6153 /* MediaUrl.swift in Sources */, + 17F54C8204F346CCA9EBFF89 /* TokenStore.swift in Sources */, + E8D2C2E91DBE41BB9A1B59AF /* UserFacingError.swift in Sources */, + 844259AFBAF448C6ADBDE30C /* ApiDtos.swift in Sources */, + 1B65AFB2A2A54BD69FE9D4D3 /* MatchLiveAPI.swift in Sources */, + DF8D47F8D9604F60B03E87F2 /* AppContainer.swift in Sources */, + 72458A3A5D6D40D8B2B4362A /* ActionCableClient.swift in Sources */, + D74402BB72E04D8A816BC980 /* SessionCableService.swift in Sources */, + 2F05B27C846F4284A533573D /* AuthRepository.swift in Sources */, + 4661478CC7C343379C100A7E /* MatchRepository.swift in Sources */, + BDF21E4064AC48D2BF2D3182 /* MatchSessionLauncher.swift in Sources */, + 412D04EC8F8344F3941D7774 /* ScoreRepository.swift in Sources */, + 34C4FE9AC892423FA42B0FA1 /* SessionRepository.swift in Sources */, + 252646FBD7F94CCEB49EE534 /* ScoreController.swift in Sources */, + 5BD7A70803AE4BFCBED02E69 /* WizardSessionHolder.swift in Sources */, + 0ABF8F2EAEF84F3CB3510FCA /* MatchHubFilter.swift in Sources */, + AD9A1CB58F8C44EC92C5B4AE /* MatchScoringRules.swift in Sources */, + ADA537BB60354316AB3D343D /* Models.swift in Sources */, + 16D77B1BA1694BC9AAEACACA /* ScoreState.swift in Sources */, + C0E26D8B51484304B9234F89 /* BroadcastModels.swift in Sources */, + 72B22BECDAD64FE88CD38A25 /* BroadcastOrientationPolicy.swift in Sources */, + D44A9E22D1C241EA83B7A897 /* BroadcastVideoOrientation.swift in Sources */, + 33848EA261D540879BABC0EC /* LiveBroadcastCoordinator.swift in Sources */, + 62F8E9A68AF84E04B5B25C0E /* LiveBroadcastEngine.swift in Sources */, + 953EFFA2B63946A0818C82A1 /* CompactScoreboardElement.swift in Sources */, + 7FAB1EF0F8D3459CB1A05CD5 /* OverlayCanvasRenderer.swift in Sources */, + 57499374CE314E5C9B19E857 /* OverlayLogoCache.swift in Sources */, + AD41DBD5504E4D3CB34B81B1 /* OverlayMappings.swift in Sources */, + D6ED4D033BA74DFFA968FC50 /* OverlayRenderer.swift in Sources */, + 44412124BE71497F89A100A7 /* OverlayState.swift in Sources */, + DAA27DA77F904BA9B59684B1 /* ScoreboardElement.swift in Sources */, + 1DF38DB813DC491C94C206CD /* SponsorElement.swift in Sources */, + ABA512B1D2C7407E892623DE /* WatermarkElement.swift in Sources */, + 70385A94466D4A2EA11DDB3B /* LivePreviewView.swift in Sources */, + 0B2C36335D034737BD753D22 /* BroadcastControlsOverlay.swift in Sources */, + A5767FD88F8D4123A68224CD /* BroadcastScreen.swift in Sources */, + 2F9195CCAE9949C087CECAA2 /* LiveScoreActions.swift in Sources */, + 1F26CA550156447B89B3EC01 /* MatchLiveWordmark.swift in Sources */, + 85680F15BAC247B1AA97DC4D /* MatchPrimaryButton.swift in Sources */, + 942E7C8159B2490A9058D20A /* MatchScreenScaffold.swift in Sources */, + BDAA05C294674E0A837D27AB /* MatchSecondaryButton.swift in Sources */, + 3D6496F4394A4A8B8280CCD7 /* MatchStatusBadge.swift in Sources */, + 0AEA80531D74475A9279AAF8 /* LoginScreen.swift in Sources */, + F3907C6CC01447B786FF633F /* MatchesScreen.swift in Sources */, + BCA11E5347BE4070B1883A58 /* AppNavHost.swift in Sources */, + E2D089A57F9F49D887C0D233 /* ModalRoutes.swift in Sources */, + C2479C699DF24364951AFFEC /* Routes.swift in Sources */, + 6312973A866D4191BA2E2E5E /* BroadcastPermissions.swift in Sources */, + 71A4EBF7C11441ED8202C4A5 /* SplashScreen.swift in Sources */, + 255C09F3A1AB4FCC80DC403D /* KeepScreenOn.swift in Sources */, + D4EED1F5722B435695F1C09D /* ScreenOrientation.swift in Sources */, + B6CA255BE2A840A7B21CDCCB /* ShareSheet.swift in Sources */, + C6B8E801C3E449ABBFA44F33 /* MatchColors.swift in Sources */, + 4B6FFF5D05164AE9AFB2833C /* StepMatchScreen.swift in Sources */, + 5A085BBBD09B49A98A261FD1 /* StepNetworkTestScreen.swift in Sources */, + 7360468C628E48AF950EF5CB /* StepTransmissionScreen.swift in Sources */, + 871F7D73227B4E699B65FE3D /* TeamBrandingEditor.swift in Sources */, + E2E74A83D86544BA8FB85AAB /* TeamColorPicker.swift in Sources */, + 4E3828F9935743CCB4B15F01 /* WizardComponents.swift in Sources */, + B9DFB757CD3942AEBC1953F0 /* WizardShellScreen.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 4264391B98534ED485BCB343 /* PBXTargetDependency */ = { + 953DB6F101304B388EBFB376 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = AE6E9D532CE6492D8B82687F /* MatchLiveTv */; - targetProxy = ACB2FE70CE4841CCB7A0ACC7 /* PBXContainerItemProxy */; + target = 2F039DD838234B1F9B1B2FF5 /* MatchLiveTv */; + targetProxy = 90C62964E51147DCABB6E3C2 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 10AA1592F59B4796984A3DF8 /* Release */ = { + 10CF510EECBA46A28C005559 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 2A2B61A669994F488438E767 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 21; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + MARKETING_VERSION = 2.0.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv.tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MatchLiveTv.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/MatchLiveTv"; + }; + name = Debug; + }; + 3F95B64C066F4446ACEDEEFA /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 16.0; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 4F2ACFA1B72745E696F93445 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { API_BASE_URL = "https://www.matchlivetv.it"; @@ -507,15 +541,7 @@ }; name = Release; }; - 13D89B468B1A4BC7A4C411CC /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 3D4B16FD3007411E80F55942 /* Debug */ = { + C6FDF65D61EE4467A5089156 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { API_BASE_URL = "https://www.matchlivetv.it"; @@ -542,33 +568,7 @@ }; name = Debug; }; - 4112889F91F94934ADAC5A6E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 8EEBF4BEA19A487B9CA09A7E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 21; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.0; - MARKETING_VERSION = 2.0.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.matchlivetv.match-live-tv.tests"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MatchLiveTv.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/MatchLiveTv"; - }; - name = Debug; - }; - E449653FF06F4DCDB2AFC77A /* Release */ = { + E9E462592C9D4C8CB7EF2F7B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; @@ -589,29 +589,29 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 002C5EF177A5409AAE23DB38 /* Build configuration list for PBXNativeTarget "MatchLiveTv" */ = { + 1E22BBCE2E7C4E1DBD22BF81 /* Build configuration list for PBXProject "MatchLiveTv" */ = { isa = XCConfigurationList; buildConfigurations = ( - 3D4B16FD3007411E80F55942 /* Debug */, - 10AA1592F59B4796984A3DF8 /* Release */, + 10CF510EECBA46A28C005559 /* Debug */, + 3F95B64C066F4446ACEDEEFA /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 27F2A4CC59994B3CA41841F5 /* Build configuration list for PBXProject "MatchLiveTv" */ = { + 271ADC46052246A38FB0DFCE /* Build configuration list for PBXNativeTarget "MatchLiveTvTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 13D89B468B1A4BC7A4C411CC /* Debug */, - 4112889F91F94934ADAC5A6E /* Release */, + 2A2B61A669994F488438E767 /* Debug */, + E9E462592C9D4C8CB7EF2F7B /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - E3DA5397819945D09DC337F6 /* Build configuration list for PBXNativeTarget "MatchLiveTvTests" */ = { + 7F122D777A6E41C9BD148CDD /* Build configuration list for PBXNativeTarget "MatchLiveTv" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8EEBF4BEA19A487B9CA09A7E /* Debug */, - E449653FF06F4DCDB2AFC77A /* Release */, + C6FDF65D61EE4467A5089156 /* Debug */, + 4F2ACFA1B72745E696F93445 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -619,7 +619,7 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 2DAE333E666A41BE8A5F1148 /* XCRemoteSwiftPackageReference "HaishinKit" */ = { + 3FD2C0913F9E4659A9B8920D /* XCRemoteSwiftPackageReference "HaishinKit" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/shogo4405/HaishinKit.swift"; requirement = { @@ -630,17 +630,17 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - AA756D8C68BC4B3D8EC96D5E /* RTMPHaishinKit */ = { + 363FFDAD444D4381B6D23159 /* HaishinKit */ = { isa = XCSwiftPackageProductDependency; - package = 2DAE333E666A41BE8A5F1148 /* XCRemoteSwiftPackageReference "HaishinKit" */; - productName = RTMPHaishinKit; - }; - DFA0D0CEB1F1428D9E3FB3DB /* HaishinKit */ = { - isa = XCSwiftPackageProductDependency; - package = 2DAE333E666A41BE8A5F1148 /* XCRemoteSwiftPackageReference "HaishinKit" */; + package = 3FD2C0913F9E4659A9B8920D /* XCRemoteSwiftPackageReference "HaishinKit" */; productName = HaishinKit; }; + 3CEE882EC45E49D49BF6B568 /* RTMPHaishinKit */ = { + isa = XCSwiftPackageProductDependency; + package = 3FD2C0913F9E4659A9B8920D /* XCRemoteSwiftPackageReference "HaishinKit" */; + productName = RTMPHaishinKit; + }; /* End XCSwiftPackageProductDependency section */ }; - rootObject = 76FC637A5DFB4F018A0D1441 /* Project object */; + rootObject = DBE4153B1FC34F91BC390462 /* Project object */; } diff --git a/native/ios/MatchLiveTv.xcodeproj/xcshareddata/xcschemes/MatchLiveTv.xcscheme b/native/ios/MatchLiveTv.xcodeproj/xcshareddata/xcschemes/MatchLiveTv.xcscheme index c6774f0..1c9ceb4 100644 --- a/native/ios/MatchLiveTv.xcodeproj/xcshareddata/xcschemes/MatchLiveTv.xcscheme +++ b/native/ios/MatchLiveTv.xcodeproj/xcshareddata/xcschemes/MatchLiveTv.xcscheme @@ -3,28 +3,28 @@ - + - + - + - + - + diff --git a/native/ios/MatchLiveTv/Data/API/ApiDtos.swift b/native/ios/MatchLiveTv/Data/API/ApiDtos.swift index ce5199d..2b47a8b 100644 --- a/native/ios/MatchLiveTv/Data/API/ApiDtos.swift +++ b/native/ios/MatchLiveTv/Data/API/ApiDtos.swift @@ -235,8 +235,8 @@ struct ScoreStateDto: Decodable { let awayPoints: Int? let currentSet: Int? let setPartials: [SetPartialDto]? - let timeoutHome: Bool? - let timeoutAway: Bool? + let timeoutHome: FlexibleBool? + let timeoutAway: FlexibleBool? let period: FlexiblePeriod? let clockSecs: Int? let clockRunning: FlexibleBool? @@ -256,8 +256,8 @@ struct ScoreStateDto: Decodable { setPartials: (setPartials ?? []).map { SetPartial(set: $0.set ?? 1, home: $0.home ?? 0, away: $0.away ?? 0) }, - timeoutHome: timeoutHome ?? false, - timeoutAway: timeoutAway ?? false, + timeoutHome: timeoutHome?.value ?? false, + timeoutAway: timeoutAway?.value ?? false, boardType: board, period: parsePeriodNumber(periodLabel, currentSet: currentSet), periodLabel: periodLabel, @@ -331,6 +331,30 @@ struct ScoreStateDataDto: Decodable { let clockRunning: FlexibleBool? let period: Int? let overtime: FlexibleBool? + + enum CodingKeys: String, CodingKey { + case homeScore, awayScore, clockSecs, clockRunning, period, overtime + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + homeScore = Self.decodeInt(container, key: .homeScore) + awayScore = Self.decodeInt(container, key: .awayScore) + clockSecs = Self.decodeInt(container, key: .clockSecs) + clockRunning = try? container.decode(FlexibleBool.self, forKey: .clockRunning) + period = Self.decodeInt(container, key: .period) + overtime = try? container.decode(FlexibleBool.self, forKey: .overtime) + } + + private static func decodeInt( + _ container: KeyedDecodingContainer, + key: CodingKeys + ) -> Int? { + if let value = try? container.decode(Int.self, forKey: key) { return value } + if let text = try? container.decode(String.self, forKey: key), let value = Int(text) { return value } + if let value = try? container.decode(Double.self, forKey: key) { return Int(value) } + return nil + } } struct ScoreActionRequest: Encodable { diff --git a/native/ios/MatchLiveTv/Domain/ScoreState.swift b/native/ios/MatchLiveTv/Domain/ScoreState.swift index cb89397..70ac4ab 100644 --- a/native/ios/MatchLiveTv/Domain/ScoreState.swift +++ b/native/ios/MatchLiveTv/Domain/ScoreState.swift @@ -36,7 +36,8 @@ struct ScoreState: Equatable, Sendable { "timeout_away": timeoutAway, ] if Self.periodBoards.contains(boardType) { - payload["period"] = periodLabel ?? "\(period)" + // Il backend si aspetta un intero in sync Action Cable (non "Q1"). + payload["period"] = period payload["clock_secs"] = clockSecs payload["clock_running"] = clockRunning payload["home_score"] = homePoints diff --git a/native/ios/MatchLiveTvTests/ScoreActionDecodeTests.swift b/native/ios/MatchLiveTvTests/ScoreActionDecodeTests.swift index 1eab5c8..35671f5 100644 --- a/native/ios/MatchLiveTvTests/ScoreActionDecodeTests.swift +++ b/native/ios/MatchLiveTvTests/ScoreActionDecodeTests.swift @@ -99,4 +99,139 @@ final class ScoreActionDecodeTests: XCTestCase { XCTAssertEqual(score.clockSecs, 600) XCTAssertFalse(score.clockRunning) } + + func testDecodesResumeSessionDetailWithBasketScore() throws { + let json = """ + { + "id": "420fd5b9-b2ad-45af-9c1d-569c654866f8", + "match_id": "e887ce1d-10ee-4680-8323-79bb8f11e0aa", + "status": "paused", + "platform": "matchlivetv", + "rtmp_ingest_url": "rtmp://localhost:1935/live/key", + "hls_playback_url": "http://localhost:8888/live/key/index.m3u8", + "watch_page_url": "http://localhost:3000/live/abc", + "share_url": "http://localhost:3000/live/abc", + "youtube_watch_url": null, + "youtube_broadcast_id": null, + "youtube_ready": false, + "privacy_status": "unlisted", + "quality_preset": "720p_30_2.5mbps", + "target_bitrate": 2500000, + "started_at": "2026-06-19T10:30:00.000Z", + "disconnection_count": 0, + "score": { + "type": "score_update", + "board_type": "basket", + "home_sets": 0, + "away_sets": 0, + "home_points": 42, + "away_points": 38, + "current_set": 1, + "set_partials": [], + "timeout_home": false, + "timeout_away": false, + "period": "Q3", + "clock_secs": 312, + "clock_running": true, + "data": { + "home_score": 42, + "away_score": 38, + "period": 3, + "clock_secs": 312, + "clock_running": true, + "overtime": false + } + }, + "devices": [ + { + "type": "device_state", + "battery": 85, + "network": "wifi", + "bitrate": 2100, + "fps": 30, + "status": "paused" + } + ] + } + """.data(using: .utf8)! + let dto = try ApiInstant.decoder.decode(StreamSessionDto.self, from: json) + let score = try XCTUnwrap(dto.score?.toDomain()) + XCTAssertEqual(score.homePoints, 42) + XCTAssertEqual(score.periodLabel, "Q3") + XCTAssertEqual(dto.status, "paused") + } + + func testDecodesBasketScoreWithNumericTimeouts() throws { + let json = """ + { + "id": "a", + "match_id": "b", + "status": "paused", + "platform": "matchlivetv", + "score": { + "board_type": "basket", + "home_points": 10, + "away_points": 8, + "period": "Q2", + "clock_secs": 600, + "clock_running": false, + "timeout_home": 0, + "timeout_away": 0, + "data": { "home_score": 10, "away_score": 8, "period": 2, "overtime": false } + } + } + """.data(using: .utf8)! + let dto = try ApiInstant.decoder.decode(StreamSessionDto.self, from: json) + XCTAssertEqual(dto.score?.toDomain().homePoints, 10) + } + + func testDecodesBasketScoreWithStringPeriodInData() throws { + let json = """ + { + "id": "a", + "match_id": "b", + "status": "paused", + "platform": "matchlivetv", + "score": { + "board_type": "basket", + "home_points": 10, + "away_points": 8, + "period": "Q2", + "clock_secs": 600, + "clock_running": false, + "data": { "period": "2", "home_score": 10, "away_score": 8, "overtime": false } + } + } + """.data(using: .utf8)! + let dto = try ApiInstant.decoder.decode(StreamSessionDto.self, from: json) + XCTAssertEqual(dto.score?.toDomain().period, 2) + } + + func testDecodesCableAdvancePeriodPayload() throws { + let json = """ + { + "type": "score_update", + "board_type": "basket", + "home_points": 0, + "away_points": 4, + "period": "Q2", + "clock_secs": 600, + "clock_running": false, + "data": { + "period": 2, + "home_score": 0, + "away_score": 4, + "clock_secs": 600, + "clock_running": false, + "overtime": false + } + } + """.data(using: .utf8)! + let score = ScoreState.fromCablePayload(try JSONSerialization.jsonObject(with: json) as! [String: Any]) + XCTAssertEqual(score.period, 2) + XCTAssertEqual(score.periodLabel, "Q2") + XCTAssertEqual(score.homePoints, 0) + XCTAssertEqual(score.awayPoints, 4) + XCTAssertGreaterThan(score.progressKey(), ScoreState(boardType: "basket", period: 1, periodLabel: "Q1").progressKey()) + } } diff --git a/native/ios/MatchLiveTvTests/ScoreControllerTests.swift b/native/ios/MatchLiveTvTests/ScoreControllerTests.swift index d1c08a4..a4711fc 100644 --- a/native/ios/MatchLiveTvTests/ScoreControllerTests.swift +++ b/native/ios/MatchLiveTvTests/ScoreControllerTests.swift @@ -101,4 +101,23 @@ final class ScoreControllerTests: XCTestCase { XCTAssertEqual(controller.score.homePoints, 6) XCTAssertEqual(controller.score.awayPoints, 7) } + + func testCableAdvancePeriodUpdatesOverlayState() { + let controller = ScoreController( + scoreRepository: ScoreRepository(api: MatchLiveAPI()), + sessionCable: SessionCableService() + ) + var local = ScoreState(boardType: "basket", period: 1, periodLabel: "Q1") + local.homePoints = 0 + local.awayPoints = 4 + controller.bind(sessionId: "session-1", initial: local) + + var remote = ScoreState(boardType: "basket", period: 2, periodLabel: "Q2") + remote.homePoints = 0 + remote.awayPoints = 4 + controller.applyRemote(remote, source: .cable) + + XCTAssertEqual(controller.score.periodLabel, "Q2") + XCTAssertEqual(controller.score.period, 2) + } } diff --git a/scripts/e2e_ios_simulator.sh b/scripts/e2e_ios_simulator.sh index c6a92bf..a6a372e 100755 --- a/scripts/e2e_ios_simulator.sh +++ b/scripts/e2e_ios_simulator.sh @@ -98,7 +98,37 @@ score = s.get("score") or {} assert s.get("status") in ("live", "connecting", "reconnecting", "idle"), s.get("status") assert score.get("board_type") in ("volley", "racket", "basket", "timed", "generic", "timer"), score assert score.get("current_set") == 2, score -print("GET /sessions/:id OK — Riprendi diretta payload valido") +print("GET /sessions/:id OK — Riprendi diretta payload valido (volley)") +PY + +echo "== API: sessione basket in pausa + Riprendi diretta ==" +BASKET_MATCH=$(curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \ + "$API/api/v1/teams/$TEAM_ID/matches" \ + -d '{"opponent_name":"E2E Basket","sport_key":"basket"}') +BASKET_MATCH_ID=$(echo "$BASKET_MATCH" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])") + +BASKET_SESSION=$(curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \ + "$API/api/v1/matches/$BASKET_MATCH_ID/sessions" \ + -d '{"platform":"matchlivetv","privacy_status":"unlisted","quality_preset":"720p_30_2.5mbps"}') +BASKET_SESSION_ID=$(echo "$BASKET_SESSION" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])") +curl -sf -X PATCH -H "$AUTH" "$API/api/v1/sessions/$BASKET_SESSION_ID/start" > /dev/null +for _ in $(seq 1 5); do + curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \ + "$API/api/v1/sessions/$BASKET_SESSION_ID/score_action" \ + -d '{"score_action":"home_point"}' > /dev/null +done +curl -sf -X PATCH -H "$AUTH" "$API/api/v1/sessions/$BASKET_SESSION_ID/pause" > /dev/null + +BASKET_RESUME=$(curl -sf -H "$AUTH" "$API/api/v1/sessions/$BASKET_SESSION_ID") +python3 - <