Skip to content

Commit 6ef6db8

Browse files
committed
Fixes
1 parent 6ffefde commit 6ef6db8

14 files changed

Lines changed: 359 additions & 202 deletions

File tree

samples/Sample.Maui/AppShell.xaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,19 @@
1111
FlyoutBehavior="Disabled"
1212
Title="Shiny HTTP Server">
1313

14+
<!-- The icons are SVGs under Resources/Images, referenced by the .png the build produces from
15+
them. Single-colour on purpose: Shell tints a tab icon with TabBarForegroundColor and
16+
TabBarUnselectedColor, so the glyph follows the theme instead of fighting it. -->
1417
<TabBar>
1518
<ShellContent Title="Server"
1619
Route="Server"
20+
Icon="server.png"
1721
ContentTemplate="{DataTemplate pages:ServerPage}" />
1822

1923
<ShellContent Title="Traffic"
2024
Route="Traffic"
25+
Icon="traffic.png"
2126
ContentTemplate="{DataTemplate pages:TrafficPage}" />
22-
23-
<ShellContent Title="Access"
24-
Route="Access"
25-
ContentTemplate="{DataTemplate pages:AccessPage}" />
2627
</TabBar>
2728

2829
</shiny:ShinyShell>

samples/Sample.Maui/MauiProgram.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public static MauiApp CreateMauiApp()
5050
builder.Services.AddSingleton<TrafficBadge>();
5151
builder.Services.AddSingleton<IMauiInitializeService>(sp => sp.GetRequiredService<TrafficBadge>());
5252

53-
// The accounts live in the app's own storage and change from the settings screen, so the
53+
// The accounts live in the app's own storage and change from the Server screen, so the
5454
// validator is a service rather than a list handed over at startup.
5555
builder.Services.AddAuthentication().AddBasic<CredentialStore>(o => o.Realm = "Shiny device");
5656

samples/Sample.Maui/Pages/AccessPage.xaml

Lines changed: 0 additions & 65 deletions
This file was deleted.

samples/Sample.Maui/Pages/AccessPage.xaml.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.

samples/Sample.Maui/Pages/ServerPage.xaml

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,65 @@
3737
IsVisible="{Binding HasError}" />
3838

3939
<!-- The public link. Bound, never captured once: a free tunnel hands out a new
40-
address on every reconnect, and a phone reconnects whenever the network does. -->
40+
address on every reconnect, and a phone reconnects whenever the network does.
41+
Tappable, like every address below it: it opens in the system browser, which
42+
is the one Handoff advertises — so the page carries over to the Mac. -->
4143
<Label Text="Public link" TextColor="Gray" Margin="0,6,0,0" />
4244
<Label Text="{Binding PublicUrl, TargetNullValue='Not shared yet'}"
43-
LineBreakMode="CharacterWrap" />
45+
TextColor="{StaticResource Primary}"
46+
TextDecorations="Underline"
47+
LineBreakMode="CharacterWrap">
48+
<Label.GestureRecognizers>
49+
<TapGestureRecognizer Command="{Binding OpenUrlCommand}"
50+
CommandParameter="{Binding PublicUrl}" />
51+
</Label.GestureRecognizers>
52+
</Label>
4453

4554
<Label Text="On this network" TextColor="Gray" Margin="0,6,0,0" />
4655
<Label Text="{Binding LocalUrl, TargetNullValue='Server not started'}"
47-
LineBreakMode="CharacterWrap" />
56+
TextColor="{StaticResource Primary}"
57+
TextDecorations="Underline"
58+
LineBreakMode="CharacterWrap">
59+
<Label.GestureRecognizers>
60+
<TapGestureRecognizer Command="{Binding OpenUrlCommand}"
61+
CommandParameter="{Binding LocalUrl}" />
62+
</Label.GestureRecognizers>
63+
</Label>
4864

4965
<!-- The MCP endpoint, for pasting into an AI client. Same server, same password. -->
5066
<Label Text="MCP endpoint" TextColor="Gray" Margin="0,6,0,0" />
5167
<Label Text="{Binding McpUrl, TargetNullValue='Server not started'}"
5268
LineBreakMode="CharacterWrap" />
5369

54-
<!-- The WebDAV mount. Finder: Go → Connect to Server. Explorer: Map network
55-
drive. Same server, same password — the app's storage as a drive. -->
56-
<Label Text="WebDAV mount" TextColor="Gray" Margin="0,6,0,0" />
57-
<Label Text="{Binding WebDavUrl, TargetNullValue='Server not started'}"
58-
LineBreakMode="CharacterWrap" />
70+
<!-- The WebDAV mount, both ways to reach it. Finder: Go → Connect to Server.
71+
Explorer: Map network drive. Same server, same password — the app's storage
72+
as a drive. Tapping either one browses the mount here instead: GET on a
73+
collection returns an HTML listing whose links walk the whole tree. -->
74+
<Label Text="WebDAV mount — on this network" TextColor="Gray" Margin="0,6,0,0" />
75+
<Label Text="{Binding LocalWebDavUrl, TargetNullValue='Server not started'}"
76+
TextColor="{StaticResource Primary}"
77+
TextDecorations="Underline"
78+
LineBreakMode="CharacterWrap">
79+
<Label.GestureRecognizers>
80+
<TapGestureRecognizer Command="{Binding OpenUrlCommand}"
81+
CommandParameter="{Binding LocalWebDavUrl}" />
82+
</Label.GestureRecognizers>
83+
</Label>
84+
85+
<Label Text="WebDAV mount — public" TextColor="Gray" Margin="0,6,0,0" />
86+
<Label Text="{Binding PublicWebDavUrl, TargetNullValue='Not shared yet'}"
87+
TextColor="{StaticResource Primary}"
88+
TextDecorations="Underline"
89+
LineBreakMode="CharacterWrap">
90+
<Label.GestureRecognizers>
91+
<TapGestureRecognizer Command="{Binding OpenUrlCommand}"
92+
CommandParameter="{Binding PublicWebDavUrl}" />
93+
</Label.GestureRecognizers>
94+
</Label>
95+
96+
<Label Text="Tap any link to open it here — the browser asks for the same account, and Handoff carries the page to your Mac."
97+
TextColor="Gray"
98+
FontSize="12" />
5999

60100
<HorizontalStackLayout Spacing="8" Margin="0,6,0,0">
61101
<Label Text="Requests served:" />
@@ -66,6 +106,55 @@
66106
</VerticalStackLayout>
67107
</Border>
68108

109+
<!-- The account, read and written on the same screen as the links that ask for it.
110+
A change takes effect on the very next request — the validator reads these values
111+
rather than a copy taken at startup, so nothing restarts. -->
112+
<Border Stroke="{AppThemeBinding Light=#E5E5EA, Dark=#2C2C32}"
113+
StrokeThickness="1"
114+
Padding="16"
115+
StrokeShape="RoundRectangle 12">
116+
<VerticalStackLayout Spacing="10">
117+
118+
<Label Text="Sign in with" FontAttributes="Bold" />
119+
120+
<Entry Placeholder="Username"
121+
Text="{Binding Username}"
122+
IsSpellCheckEnabled="False"
123+
IsTextPredictionEnabled="False" />
124+
125+
<!-- Deliberately not masked: on a device you are handing a link to, someone has
126+
to read this out. A product with real accounts would not show it. -->
127+
<Entry Placeholder="Password"
128+
Text="{Binding Password}"
129+
IsSpellCheckEnabled="False"
130+
IsTextPredictionEnabled="False" />
131+
132+
<Grid ColumnDefinitions="*,*" ColumnSpacing="10">
133+
<Button Grid.Column="0"
134+
Text="Save"
135+
Command="{Binding SaveAccountCommand}"
136+
IsEnabled="{Binding NotBusy}" />
137+
<Button Grid.Column="1"
138+
Text="New password"
139+
Command="{Binding RegeneratePasswordCommand}"
140+
IsEnabled="{Binding NotBusy}" />
141+
</Grid>
142+
143+
<Button Text="Copy password"
144+
Command="{Binding CopyValueCommand}"
145+
CommandParameter="{Binding Password}" />
146+
147+
<Label Text="{Binding StorageStatus}"
148+
TextColor="Gray"
149+
FontSize="12" />
150+
151+
<Label Text="The password is generated on first run and kept in the device keychain. A new one takes effect on the next request and locks out anyone holding the old one. Failed attempts still show up on the Traffic tab — the log sits in front of authentication."
152+
TextColor="Gray"
153+
FontSize="12" />
154+
155+
</VerticalStackLayout>
156+
</Border>
157+
69158
<!-- Actions -->
70159
<VerticalStackLayout Spacing="10">
71160
<Button Text="Share publicly"
@@ -95,7 +184,7 @@
95184
IsEnabled="{Binding CanStopSharing}" />
96185
</VerticalStackLayout>
97186

98-
<Label Text="Endpoints: / · /api/device · /api/notes · /files (browse app storage) · /mcp (4 tools, for an AI client) — all behind the password. /ping is open."
187+
<Label Text="Endpoints: / · /api/device · /api/notes · /files (browse app storage) · /dav (the same storage as a drive, or a browsable listing) · /mcp (4 tools, for an AI client) — all behind the password. /ping is open."
99188
TextColor="Gray"
100189
FontSize="12" />
101190

Lines changed: 6 additions & 0 deletions
Loading
Lines changed: 6 additions & 0 deletions
Loading

samples/Sample.Maui/Server/CredentialStore.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace Sample.Maui.Server;
77

88
/// <summary>
9-
/// The one account this device accepts, changeable from the settings screen.
9+
/// The one account this device accepts, changeable from the Server screen.
1010
/// <para>
1111
/// This is what <see cref="IBasicCredentialValidator"/> is for: the accounts are not in
1212
/// configuration, they are in whatever the app already uses to remember things — so the validator
@@ -33,7 +33,7 @@ public sealed class CredentialStore : IBasicCredentialValidator
3333
public string Username => this.username;
3434

3535
/// <summary>
36-
/// The current password, so the settings screen can show what visitors need to be told. A real
36+
/// The current password, so the Server screen can show what visitors need to be told. A real
3737
/// product would not display it; a device you are handing a link to is exactly the case where
3838
/// someone has to read it out.
3939
/// </summary>

samples/Sample.Maui/ViewModels/AccessViewModel.cs

Lines changed: 0 additions & 105 deletions
This file was deleted.

0 commit comments

Comments
 (0)