Skip to content

Commit

Permalink
Refresh browser for all transitively referencing projects
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed Nov 24, 2024
1 parent ff3f83c commit b635a3a
Show file tree
Hide file tree
Showing 19 changed files with 530 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ private async ValueTask DisplayResultsAsync(WatchHotReloadService.Updates update
switch (updates.Status)
{
case ModuleUpdateStatus.None:
_reporter.Output("No hot reload changes to apply.");
_reporter.Output("No C# changes to apply.");
break;

case ModuleUpdateStatus.Ready:
Expand Down
60 changes: 40 additions & 20 deletions src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,41 +52,61 @@ public async ValueTask HandleFileChangesAsync(IReadOnlyList<ChangedFile> files,
}
}

var logger = reporter.IsVerbose ? new[] { new Build.Logging.ConsoleLogger() } : null;
if (!hasApplicableFiles)
{
return;
}

var logger = reporter.IsVerbose ? new[] { new Build.Logging.ConsoleLogger(LoggerVerbosity.Minimal) } : null;

Check failure on line 60 in src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TemplateEngine: macOS (x64))

src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs#L60

src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs(60,87): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'LoggerVerbosity' does not exist in the current context

Check failure on line 60 in src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs

View check run for this annotation

Azure Pipelines / dotnet-sdk-public-ci (Build TestBuild: macOS (x64))

src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs#L60

src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs(60,87): error CS0103: (NETCORE_ENGINEERING_TELEMETRY=Build) The name 'LoggerVerbosity' does not exist in the current context

var tasks = projectsToRefresh.Select(async projectNode =>
var buildTasks = projectsToRefresh.Select(projectNode => Task.Run(() =>
{
if (!projectNode.ProjectInstance.DeepCopy().Build(BuildTargetName, logger))
try
{
return false;
if (!projectNode.ProjectInstance.DeepCopy().Build(BuildTargetName, logger))
{
return null;
}
}

if (browserConnector.TryGetRefreshServer(projectNode, out var browserRefreshServer))
catch (Exception e)
{
await HandleBrowserRefresh(browserRefreshServer, projectNode.ProjectInstance.FullPath, cancellationToken);
reporter.Error($"[{projectNode.GetDisplayName()}] Target {BuildTargetName} failed to build: {e}");
return null;
}

return true;
});
return projectNode;
}));

var results = await Task.WhenAll(tasks).WaitAsync(cancellationToken);
var buildResults = await Task.WhenAll(buildTasks).WaitAsync(cancellationToken);

if (hasApplicableFiles)
var browserRefreshTasks = buildResults.Where(p => p != null)!.GetTransitivelyReferencingProjects().Select(async projectNode =>
{
var successfulCount = results.Sum(r => r ? 1 : 0);

if (successfulCount == results.Length)
{
reporter.Output("Hot reload of scoped css succeeded.", emoji: "🔥");
}
else if (successfulCount > 0)
if (browserConnector.TryGetRefreshServer(projectNode, out var browserRefreshServer))
{
reporter.Output($"Hot reload of scoped css partially succeeded: {successfulCount} project(s) out of {results.Length} were updated.", emoji: "🔥");
reporter.Verbose($"[{projectNode.GetDisplayName()}] Refreshing browser.");
await HandleBrowserRefresh(browserRefreshServer, projectNode.ProjectInstance.FullPath, cancellationToken);
}
else
{
reporter.Output("Hot reload of scoped css failed.", emoji: "🔥");
reporter.Verbose($"[{projectNode.GetDisplayName()}] No refresh server.");
}
});

await Task.WhenAll(browserRefreshTasks).WaitAsync(cancellationToken);

var successfulCount = buildResults.Sum(r => r != null ? 1 : 0);

if (successfulCount == buildResults.Length)
{
reporter.Output("Hot reload of scoped css succeeded.", emoji: "🔥");
}
else if (successfulCount > 0)
{
reporter.Output($"Hot reload of scoped css partially succeeded: {successfulCount} project(s) out of {buildResults.Length} were updated.", emoji: "🔥");
}
else
{
reporter.Output("Hot reload of scoped css failed.", emoji: "🔥");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,28 @@ public static bool IsNetCoreApp(this ProjectGraphNode projectNode, Version minVe

public static IEnumerable<string> GetCapabilities(this ProjectGraphNode projectNode)
=> projectNode.ProjectInstance.GetItems("ProjectCapability").Select(item => item.EvaluatedInclude);

public static IEnumerable<ProjectGraphNode> GetTransitivelyReferencingProjects(this IEnumerable<ProjectGraphNode> projects)
{
var visited = new HashSet<ProjectGraphNode>();
var queue = new Queue<ProjectGraphNode>();
foreach (var project in projects)
{
queue.Enqueue(project);
}

while (queue.Count > 0)
{
var project = queue.Dequeue();
if (visited.Add(project))
{
foreach (var referencingProject in project.ReferencingProjects)
{
queue.Enqueue(referencingProject);
}
}
}

return visited;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<base href="/"/>

<link rel="stylesheet" href="@Assets["lib/bootstrap/dist/css/bootstrap.min.css"]"/>
<link rel="stylesheet" href="@Assets["app.css"]"/>
<link rel="stylesheet" href="@Assets["RazorApp.styles.css"]"/>
<ImportMap/>

@*
<link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="app.css"/>
<link rel="stylesheet" href="RazorApp.styles.css"/>
*@

<link rel="icon" type="image/png" href="favicon.png"/>
<HeadOutlet @rendermode="InteractiveServer"/>
</head>

<body>
<Routes @rendermode="InteractiveServer"/>
<script src="_framework/blazor.web.js"></script>
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
@inherits LayoutComponentBase

<div class="page">
<div class="sidebar">
<NavMenu/>
</div>

<main>
<div class="top-row px-4">
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>

<article class="content px-4">
@Body
</article>
</main>
</div>

<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}

main {
flex: 1;
}

.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}

.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}

.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}

.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}

.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}

@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}

.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}

@media (min-width: 641px) {
.page {
flex-direction: row;
}

.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}

.top-row {
position: sticky;
top: 0;
z-index: 1;
}

.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}

.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}

#blazor-error-ui {
color-scheme: light only;
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}

#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">RazorApp</a>
</div>
</div>

<input type="checkbox" title="Navigation menu" class="navbar-toggler"/>

<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="nav flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
</nav>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
.navbar-toggler {
appearance: none;
cursor: pointer;
width: 3.5rem;
height: 2.5rem;
color: white;
position: absolute;
top: 0.5rem;
right: 1rem;
border: 1px solid rgba(255, 255, 255, 0.1);
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}

.navbar-toggler:checked {
background-color: rgba(255, 255, 255, 0.5);
}

.top-row {
min-height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}

.navbar-brand {
font-size: 1.1rem;
}

.bi {
display: inline-block;
position: relative;
width: 1.25rem;
height: 1.25rem;
margin-right: 0.75rem;
top: -1px;
background-size: cover;
}

.bi-house-door-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}

.bi-plus-square-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}

.bi-list-nested-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}

.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}

.nav-item:first-of-type {
padding-top: 1rem;
}

.nav-item:last-of-type {
padding-bottom: 1rem;
}

.nav-item ::deep .nav-link {
color: #d7d7d7;
background: none;
border: none;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
width: 100%;
}

.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.37);
color: white;
}

.nav-item ::deep .nav-link:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}

.nav-scrollable {
display: none;
}

.navbar-toggler:checked ~ .nav-scrollable {
display: block;
}

@media (min-width: 641px) {
.navbar-toggler {
display: none;
}

.nav-scrollable {
/* Never collapse the sidebar for wide screens */
display: block;

/* Allow sidebar to scroll for tall menus */
height: calc(100vh - 3.5rem);
overflow-y: auto;
}
}
Loading

0 comments on commit b635a3a

Please sign in to comment.