Skip to content

Commit 9651176

Browse files
committed
Merge branch 'dev' into feat/deeplink-param-backpack
2 parents f3e32a0 + aba4c69 commit 9651176

211 files changed

Lines changed: 9348 additions & 716 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/code-standards/SKILL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ user-invocable: false
2929

3030
**Exception:** serialized JSON DTO fields keep their wire-format casing — see *Serialized JSON DTOs* below.
3131

32+
**Namespaces are domain names, not folder paths** — never suppress a folder-namespace mismatch with `// ReSharper disable once CheckNamespace`; fix the namespace or leave the warning visible. Full rule: `docs/code-style-guidelines.md` § Namespaces.
33+
3234
## Member Ordering
3335

3436
Within a class, group members in this order:

.github/workflows/pr-comment-warnings.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ jobs:
7373
{
7474
echo "body<<EOF"
7575
echo "<!-- warning-ratchet -->"
76+
blocked=false
7677
if [ -z "$BASELINE" ]; then
7778
echo "**Warnings counted: $COUNT** (no baseline established yet)"
7879
elif [ "$COUNT" -lt "$BASELINE" ]; then
@@ -81,6 +82,27 @@ jobs:
8182
echo "**Warnings unchanged: $BASELINE => $COUNT** — allowed on release/hotfix branches."
8283
else
8384
echo "**Warnings not reduced: $BASELINE => $COUNT** — remove at least one warning to merge."
85+
blocked=true
86+
fi
87+
88+
# Always list the warnings/errors in files this PR changed; expand only when blocking.
89+
total=$(jq -r '.pr_findings_total // 0' warning-result.json)
90+
if [ "$total" -gt 0 ]; then
91+
open_attr=""
92+
[ "$blocked" = "true" ] && open_attr=" open"
93+
echo ""
94+
echo "<details$open_attr><summary>Warnings/errors in files changed by this PR ($total)</summary>"
95+
echo ""
96+
echo "| File | Line | Rule | Message |"
97+
echo "| --- | --- | --- | --- |"
98+
jq -r '.pr_findings[] | "| \(.file) | \(.line) | \(.rule) | \(.message | gsub("[|\r\n]"; " ")) |"' warning-result.json
99+
shown=$(jq -r '.pr_findings | length' warning-result.json)
100+
if [ "$total" -gt "$shown" ]; then
101+
echo ""
102+
echo "_…and $((total - shown)) more (see the \`csharp-lint-reports\` artifact)._"
103+
fi
104+
echo ""
105+
echo "</details>"
84106
fi
85107
echo "EOF"
86108
} >> "$GITHUB_OUTPUT"

.github/workflows/test.yml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,44 @@ jobs:
398398
aws s3 cp baseline.json "s3://$EXPLORER_TEAM_S3_BUCKET/${{ env.WARNINGS_BASELINE_S3_KEY }}" \
399399
--content-type application/json --cache-control no-cache
400400
401+
# Warnings/errors located in files this PR changed — surfaced in the PR comment.
402+
- name: Collect PR-file warnings
403+
if: ${{ !cancelled() && github.event_name == 'pull_request' }}
404+
id: pr-findings
405+
env:
406+
BASE_REF: ${{ github.event.pull_request.base.ref }}
407+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
408+
MAX_FINDINGS: 50 # max rows listed in the PR comment; change here
409+
run: |
410+
set -euo pipefail
411+
echo '[]' > pr-findings.json
412+
echo "total=0" >> "$GITHUB_OUTPUT"
413+
[ -f filtered.json ] || exit 0
414+
415+
base=$(git merge-base "origin/$BASE_REF" "$HEAD_SHA" 2>/dev/null || true)
416+
[ -n "$base" ] || { echo "No merge-base - skipping PR-file findings."; exit 0; }
417+
418+
# repo-relative paths -> project-relative (strip leading 'Explorer/')
419+
git diff --name-only "$base" "$HEAD_SHA" -- '*.cs' \
420+
| sed 's#^Explorer/##' | sort -u > changed-files.txt
421+
422+
jq --rawfile changed changed-files.txt '
423+
($changed | split("\n") | map(select(length > 0))) as $files
424+
| map({
425+
file: (.locations[0].physicalLocation.artifactLocation.uri // ""),
426+
line: (.locations[0].physicalLocation.region.startLine // 0),
427+
rule: (.ruleId // ""),
428+
level: (.level // "warning"),
429+
message: (.message.text // "")
430+
})
431+
| map(select(.file as $f | $files | index($f) != null))
432+
' filtered.json > pr-findings-all.json
433+
434+
total=$(jq length pr-findings-all.json)
435+
jq --argjson max "$MAX_FINDINGS" '.[:$max]' pr-findings-all.json > pr-findings.json # cap comment size
436+
echo "total=$total" >> "$GITHUB_OUTPUT"
437+
echo "PR-file findings: $total (listing up to $MAX_FINDINGS)"
438+
401439
# Hand the numbers to the trusted workflow_run companion that posts the PR comment.
402440
# Runs even when the gate above failed (!cancelled), so a failing run still refreshes the comment
403441
# instead of leaving a stale message.
@@ -416,7 +454,9 @@ jobs:
416454
--argjson count "$COUNT" \
417455
--arg baseline "$BASELINE" \
418456
--argjson allow_equal "$IS_RELEASE_OR_HOTFIX" \
419-
'{pr: $pr, count: $count, baseline: (if $baseline == "" then null else ($baseline | tonumber) end), allow_equal: $allow_equal}' \
457+
--slurpfile findings pr-findings.json \
458+
--argjson findings_total "${{ steps.pr-findings.outputs.total || 0 }}" \
459+
'{pr: $pr, count: $count, baseline: (if $baseline == "" then null else ($baseline | tonumber) end), allow_equal: $allow_equal, pr_findings: ($findings[0] // []), pr_findings_total: $findings_total}' \
420460
> warning-result.json
421461
cat warning-result.json
422462

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ Reviewers have repeatedly identified AI-generated code by these smells. Check yo
131131
* **Wiring pooled/virtualized list items per rebind.** For item pools, wire callbacks once when the item is created, not every time `SetItemData` runs. Prefer an `Action` field (single subscriber, direct assignment) over C# `event` (`+=`/`-=` churn) when there is exactly one subscriber.
132132
* **Reimplementing primitives that already exist.** Before writing manual atlas UV math, check `TMP_Sprite Asset`. Before hand-batching profile lookups, check the batched `GetProfilesAsync(IReadOnlyList<string>, ct)` overload. Before adding a bespoke event pathway, check `ViewEventBus` / `ChatEvents`.
133133
* **Comments that narrate caller/external behavior.** A comment must state only what the annotated code itself does or guarantees ("remove the corrupt file so the next read doesn't hit it"), never what callers or upper layers will do with the result ("so callers treat it as a miss and re-download"). External behavior can change without this code changing, silently turning the comment into a lie.
134+
* **Suppressing `CheckNamespace` with a ReSharper comment.** Never add `// ReSharper disable once CheckNamespace` (or the file-wide variant) — fix the namespace or leave the warning visible. Rationale and full rule: [`docs/code-style-guidelines.md` § Namespaces](docs/code-style-guidelines.md#namespaces).
134135

135136
### Other project-specific rules
136137

Explorer/Assets/AddressableAssetsData/AssetGroups/Essentials.asset

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,11 @@ MonoBehaviour:
380380
m_ReadOnly: 0
381381
m_SerializedLabels: []
382382
FlaggedDuringContentUpdateRestriction: 0
383+
- m_GUID: fe492edbd0cef4457951fba2129d4c0a
384+
m_Address: CreditsPurchaseModal
385+
m_ReadOnly: 0
386+
m_SerializedLabels: []
387+
FlaggedDuringContentUpdateRestriction: 0
383388
m_ReadOnly: 0
384389
m_Settings: {fileID: 11400000, guid: fc8a9d2b539788c47a5b305639fa8b34, type: 2}
385390
m_SchemaSet:

Explorer/Assets/DCL/ApplicationGuards/ApplicationBlocklistGuard/BannedNotificationHandler.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public class BannedNotificationHandler : IDisposable
2020
private readonly IWeb3IdentityCache identityCache;
2121
private readonly ModerationDataProvider moderationDataProvider;
2222
private readonly IMVCManager mvcManager;
23-
private readonly IWebBrowser webBrowser;
23+
private readonly UnityAppWebBrowser webBrowser;
2424

2525
private CancellationTokenSource cts = new ();
2626

@@ -30,7 +30,7 @@ public BannedNotificationHandler(
3030
IWeb3IdentityCache identityCache,
3131
ModerationDataProvider moderationDataProvider,
3232
IMVCManager mvcManager,
33-
IWebBrowser webBrowser)
33+
UnityAppWebBrowser webBrowser)
3434
{
3535
this.webRequestController = webRequestController;
3636
this.urlsSource = urlsSource;
@@ -47,7 +47,7 @@ public void Dispose() =>
4747
cts.SafeCancelAndDispose();
4848

4949
private void OnBanWarningNotificationClicked(object[] parameters) =>
50-
webBrowser.OpenUrl(urlsSource.Url(DecentralandUrl.SupportLink));
50+
webBrowser.OpenUrlMainThreadOnly(urlsSource.Url(DecentralandUrl.SupportLink));
5151

5252
private void OnBannedNotificationClicked(object[] parameters)
5353
{

Explorer/Assets/DCL/ApplicationGuards/ApplicationBlocklistGuard/BlockedScreenController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ public class BlockedScreenController : ControllerBase<BlockedScreenView, Blocked
1414
{
1515
private const string DEFAULT_INFO_TEXT = "Contact Support for more information.";
1616

17-
private readonly IWebBrowser webBrowser;
17+
private readonly UnityAppWebBrowser webBrowser;
1818
private readonly StringBuilder infoTextBuilder = new ();
1919

2020
public override CanvasOrdering.SortingLayer Layer => CanvasOrdering.SortingLayer.OVERLAY;
2121

22-
public BlockedScreenController(ViewFactoryMethod viewFactory, IWebBrowser webBrowser) : base(viewFactory)
22+
public BlockedScreenController(ViewFactoryMethod viewFactory, UnityAppWebBrowser webBrowser) : base(viewFactory)
2323
{
2424
this.webBrowser = webBrowser;
2525
}
@@ -66,7 +66,7 @@ public override void Dispose()
6666

6767
private void OnSupportClicked()
6868
{
69-
webBrowser.OpenUrl(DecentralandUrl.Help);
69+
webBrowser.OpenUrlMainThreadOnly(DecentralandUrl.Help);
7070
}
7171

7272
private static string FormatRemainingBanTime(string expiresAt)

Explorer/Assets/DCL/ApplicationGuards/ApplicationMinimumSpecsGuard/UI/MinimumSpecsScreenController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace DCL.ApplicationGuards
1111
{
1212
public class MinimumSpecsScreenController : ControllerBase<MinimumSpecsScreenView>
1313
{
14-
private readonly IWebBrowser webBrowser;
14+
private readonly UnityAppWebBrowser webBrowser;
1515
private readonly IAnalyticsController analytics;
1616
private readonly IReadOnlyList<SpecResult> specResult;
1717
public override CanvasOrdering.SortingLayer Layer => CanvasOrdering.SortingLayer.OVERLAY;
@@ -20,7 +20,7 @@ public class MinimumSpecsScreenController : ControllerBase<MinimumSpecsScreenVie
2020
private MinimumSpecsTablePresenter specsTablePresenter;
2121

2222
public MinimumSpecsScreenController(ViewFactoryMethod viewFactory,
23-
IWebBrowser webBrowser,
23+
UnityAppWebBrowser webBrowser,
2424
IAnalyticsController analytics,
2525
IReadOnlyList<SpecResult> specResult) : base(viewFactory)
2626
{
@@ -66,7 +66,7 @@ private void OnContinueClicked()
6666

6767
private void OnReadMoreClicked()
6868
{
69-
webBrowser.OpenUrl(DecentralandUrl.MinimumSpecs);
69+
webBrowser.OpenUrlMainThreadOnly(DecentralandUrl.MinimumSpecs);
7070
}
7171

7272
protected override UniTask WaitForCloseIntentAsync(CancellationToken ct) =>

Explorer/Assets/DCL/ApplicationGuards/ApplicationVersionGuard/ApplicationVersionGuard.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ public class ApplicationVersionGuard
3131
private const string DECENTRALAND_LEGACY_LAUNCHER_MAC_X_64_DMG = "Decentraland Outdated-mac-x64.dmg";
3232

3333
private readonly IWebRequestController webRequestController;
34-
private readonly IWebBrowser webBrowser;
34+
private readonly UnityAppWebBrowser webBrowser;
3535

36-
public ApplicationVersionGuard(IWebRequestController webRequestController, IWebBrowser webBrowser)
36+
public ApplicationVersionGuard(IWebRequestController webRequestController, UnityAppWebBrowser webBrowser)
3737
{
3838
this.webRequestController = webRequestController;
3939
this.webBrowser = webBrowser;
@@ -89,7 +89,7 @@ private void DownloadLauncher()
8989
string downloadUrl = $"{GetLauncherDownloadPath()}/{assetName}";
9090

9191
if (!string.IsNullOrEmpty(downloadUrl))
92-
webBrowser.OpenUrl(downloadUrl);
92+
webBrowser.OpenUrlMainThreadOnly(downloadUrl);
9393
else
9494
ReportHub.LogError(ReportCategory.VERSION_CONTROL, "Failed to get launcher download URL.");
9595
}

Explorer/Assets/DCL/AuthenticationScreenFlow/AuthenticationScreenController.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public enum AuthStatus
5252

5353
private readonly ICompositeWeb3Provider web3Authenticator;
5454
private readonly ISelfProfile selfProfile;
55-
private readonly IWebBrowser webBrowser;
55+
private readonly UnityAppWebBrowser webBrowser;
5656
private readonly IWeb3IdentityCache storedIdentityProvider;
5757
private readonly ICharacterPreviewFactory characterPreviewFactory;
5858
private readonly SplashScreen splashScreen;
@@ -99,7 +99,7 @@ public AuthenticationScreenController(
9999
ViewFactoryMethod viewFactory,
100100
ICompositeWeb3Provider web3Authenticator,
101101
ISelfProfile selfProfile,
102-
IWebBrowser webBrowser,
102+
UnityAppWebBrowser webBrowser,
103103
IWeb3IdentityCache storedIdentityProvider,
104104
ICharacterPreviewFactory characterPreviewFactory,
105105
SplashScreen splashScreen,
@@ -165,7 +165,7 @@ protected override void OnViewInstantiated()
165165
new InitAuthState(viewInstance, installSource),
166166
new LoginSelectionAuthState(fsm, viewInstance, this, CurrentState, splashScreen, web3Authenticator, webBrowser, enableEmailOTP),
167167
new ProfileFetchingAuthState(fsm, viewInstance, this, CurrentState, selfProfile, storedIdentityProvider),
168-
new IdentityVerificationDappAuthState(fsm, viewInstance, this, CurrentState, web3Authenticator),
168+
new IdentityVerificationDappDeepLinkAuthState(fsm, viewInstance, this, CurrentState, web3Authenticator),
169169
new LobbyForExistingAccountAuthState(fsm, viewInstance, this, splashScreen, CurrentState, characterPreviewController),
170170
new LobbyForNewAccountAuthState(fsm, viewInstance, this, CurrentState, characterPreviewController, selfProfile, wearablesProvider, webBrowser, webRequestController, decentralandUrlsSource, profileChangesBus)
171171
);
@@ -212,7 +212,7 @@ private async UniTaskVoid TryAutoLoginAndProceedAsync(IWeb3Identity storedIdenti
212212
bool autoLoginSuccess = await web3Authenticator.TryAutoLoginAsync(ct);
213213

214214
if (autoLoginSuccess)
215-
fsm.Enter<ProfileFetchingAuthState, ProfileFetchingPayload>(new (storedIdentity, storedIdentity.Source != IWeb3Identity.Web3IdentitySource.TokenFile, ct));
215+
fsm.Enter<ProfileFetchingAuthState, ProfileFetchingPayload>(new (storedIdentity, storedIdentity.Source != IWeb3Identity.Web3IdentitySource.TOKEN_FILE, ct));
216216
else
217217
{
218218
fsm.Enter<LoginSelectionAuthState, int>(UIAnimationHashes.IN, true);
@@ -289,7 +289,7 @@ async UniTaskVoid ChangeAccountAsync(CancellationToken ct)
289289

290290
private void OpenSupportUrl()
291291
{
292-
webBrowser.OpenUrl(DecentralandUrl.SupportLink);
292+
webBrowser.OpenUrlMainThreadOnly(DecentralandUrl.SupportLink);
293293
DiscordButtonClicked?.Invoke();
294294
}
295295

0 commit comments

Comments
 (0)