The checks engine, the path and the cards: me-web? 0.1 reads the connection
MeWeb.Core runs seven checks concurrently and reports each as it settles:
online or behind a login page, this connection, the public IPv4 and IPv6
seen from v4./v6.meweb, the provider from a built-in map, the router
(UPnP IGD, NAT-PMP and PCP, read-only), address sharing (router WAN
against the echo, TTL hops only as a hint), and the history kept on the
device. The app draws the path from this device to the internet and lights
it node by node, with a card per check and a sheet listing every host it
contacts.
The provider map is iptoasn's table compressed to 2.1 MB by
tools/knowledge.cs and built before every app release; eleven Italian
provider profiles carry each fact with who said it, the source and the
month. The server gains a download page (en, it) and /download/{platform}
from the latest Gitea release.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
This commit is contained in:
1 parent
16a1cecaae
commit
0dffbc27d6
61 files changed
+3750
-149
No files matched your search
@@ -6,45 +6,224 @@
|
||||
x:DataType="vm:MainViewModel"
|
||||
FlowDirection="{Binding Flow}"
|
||||
Background="{StaticResource GroundBrush}">
|
||||
<DockPanel Margin="24,18">
|
||||
<Grid DockPanel.Dock="Top" ColumnDefinitions="*,Auto">
|
||||
<TextBlock Grid.Column="0" Classes="title" Text="me-web?" VerticalAlignment="Center" />
|
||||
<ComboBox Grid.Column="1" MinWidth="180" VerticalAlignment="Center"
|
||||
AutomationProperties.AutomationId="main-language"
|
||||
AutomationProperties.Name="{s:Tr Language}"
|
||||
ItemsSource="{Binding Languages}"
|
||||
SelectedItem="{Binding SelectedLanguage}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="s:Language">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
|
||||
<StackPanel DockPanel.Dock="Bottom" Spacing="6" HorizontalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Center" IsVisible="{Binding ShowDraftNotice}">
|
||||
<TextBlock Classes="small" Text="{s:Tr DraftNotice}" VerticalAlignment="Center" />
|
||||
<Button Classes="link" Content="{s:Tr SuggestCorrection}"
|
||||
AutomationProperties.AutomationId="main-suggest-correction"
|
||||
Command="{Binding OpenCorrectionsCommand}" />
|
||||
</StackPanel>
|
||||
<TextBlock Classes="small" Text="{Binding VersionFormatted}" HorizontalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="22" VerticalAlignment="Center" HorizontalAlignment="Center" MaxWidth="560">
|
||||
<Grid Width="140" Height="140" HorizontalAlignment="Center">
|
||||
<Ellipse Classes="pulse" Width="140" Height="140" Fill="{StaticResource BrandRedBrush}" IsVisible="{Binding ShowChecking}" />
|
||||
<Ellipse Width="112" Height="112" Fill="{StaticResource SurfaceRaisedBrush}" Stroke="{StaticResource LineBrush}" StrokeThickness="2" />
|
||||
<Ellipse Width="64" Height="64" Fill="{StaticResource GoodBrush}" IsVisible="{Binding ShowOnline}" />
|
||||
<Ellipse Width="64" Height="64" Fill="{StaticResource BadBrush}" IsVisible="{Binding ShowOffline}" />
|
||||
<Ellipse Width="64" Height="64" Fill="{StaticResource TextSoftBrush}" Opacity="0.4" IsVisible="{Binding ShowChecking}" />
|
||||
<Grid>
|
||||
<DockPanel>
|
||||
<Grid DockPanel.Dock="Top" ColumnDefinitions="*,Auto,Auto" Margin="20,14,20,6">
|
||||
<TextBlock Grid.Column="0" Classes="title" Text="me-web?" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" Classes="round" Margin="0,0,10,0" VerticalAlignment="Center"
|
||||
AutomationProperties.AutomationId="main-contacts"
|
||||
AutomationProperties.Name="{s:Tr Contacts}"
|
||||
ToolTip.Tip="{s:Tr Contacts}"
|
||||
Command="{Binding ToggleContactsCommand}">
|
||||
<Path Classes="icon" Data="{StaticResource IconInfo}" />
|
||||
</Button>
|
||||
<ComboBox Grid.Column="2" MinWidth="150" MaxWidth="220" VerticalAlignment="Center"
|
||||
AutomationProperties.AutomationId="main-language"
|
||||
AutomationProperties.Name="{s:Tr Language}"
|
||||
ItemsSource="{Binding Languages}"
|
||||
SelectedItem="{Binding SelectedLanguage}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="s:Language">
|
||||
<TextBlock Text="{Binding Name}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
<TextBlock Classes="status" Text="{Binding StatusFormatted}" />
|
||||
<TextBlock Classes="lead" Text="{s:Tr AppTagline}" />
|
||||
<Button Classes="primary" Content="{s:Tr Check}"
|
||||
AutomationProperties.AutomationId="main-check"
|
||||
Command="{Binding RefreshCommand}" />
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
|
||||
<StackPanel DockPanel.Dock="Bottom" Spacing="4" Margin="16,6,16,10" HorizontalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Center" IsVisible="{Binding ShowDraftNotice}">
|
||||
<TextBlock Classes="small" Text="{s:Tr DraftNotice}" VerticalAlignment="Center" />
|
||||
<Button Classes="link" Content="{s:Tr SuggestCorrection}"
|
||||
AutomationProperties.AutomationId="main-suggest-correction"
|
||||
Command="{Binding OpenCorrectionsCommand}" />
|
||||
</StackPanel>
|
||||
<TextBlock Classes="small" Text="{Binding VersionFormatted}" HorizontalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel Spacing="26" Margin="8,4,8,24">
|
||||
<Border Classes="banner" IsVisible="{Binding ShowUpdate}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<TextBlock Classes="body" Text="{Binding UpdateFormatted}" VerticalAlignment="Center" />
|
||||
<Button Classes="quiet" Content="{s:Tr UpdateOpen}"
|
||||
AutomationProperties.AutomationId="main-update"
|
||||
Command="{Binding OpenDownloadsCommand}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<StackPanel Spacing="16" HorizontalAlignment="Center" MaxWidth="600" Margin="8,6,8,0">
|
||||
<Grid Width="120" Height="120" HorizontalAlignment="Center">
|
||||
<Ellipse Classes="pulse" Width="120" Height="120" IsVisible="{Binding ShowChecking}" />
|
||||
<Ellipse Width="96" Height="96" Fill="{StaticResource SurfaceRaisedBrush}" Stroke="{StaticResource LineBrush}" StrokeThickness="2" />
|
||||
<Ellipse Width="54" Height="54" Fill="{StaticResource GoodBrush}" IsVisible="{Binding ShowOnline}" />
|
||||
<Ellipse Width="54" Height="54" Fill="{StaticResource CautionBrush}" IsVisible="{Binding ShowCaptive}" />
|
||||
<Ellipse Width="54" Height="54" Fill="{StaticResource BadBrush}" IsVisible="{Binding ShowOffline}" />
|
||||
<Ellipse Width="54" Height="54" Fill="{StaticResource TextSoftBrush}" Opacity="0.4" IsVisible="{Binding ShowChecking}" />
|
||||
</Grid>
|
||||
<TextBlock Classes="status" Text="{Binding StatusFormatted}" />
|
||||
<TextBlock Classes="lead" Text="{s:Tr AppTagline}" />
|
||||
<Button Classes="primary" Content="{Binding CheckFormatted}"
|
||||
AutomationProperties.AutomationId="main-check"
|
||||
Command="{Binding CheckCommand}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="14" IsVisible="{Binding HasResults}">
|
||||
<TextBlock Classes="section" Text="{s:Tr PathTitle}" HorizontalAlignment="Center" />
|
||||
<ItemsControl ItemsSource="{Binding Path}" IsVisible="{Binding IsWide}" HorizontalAlignment="Center">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:PathNodeViewModel">
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
|
||||
<Grid Width="56" Height="64" VerticalAlignment="Top" IsVisible="{Binding ShowConnector}">
|
||||
<TextBlock Classes="linkLabel" Text="{Binding LinkLabel}" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,6,0,0" />
|
||||
<Line StartPoint="4,32" EndPoint="52,32" Classes="connector" Classes.flowing="{Binding IsRunning}" Classes.lit="{Binding IsLit}" />
|
||||
</Grid>
|
||||
<StackPanel Width="124" Spacing="6" Classes="node" Classes.lit="{Binding IsLit}"
|
||||
AutomationProperties.AutomationId="{Binding AutomationId}">
|
||||
<Grid Width="64" Height="64" HorizontalAlignment="Center">
|
||||
<Ellipse Classes="pulse" Width="64" Height="64" IsVisible="{Binding IsRunning}" />
|
||||
<Ellipse Classes="disc" Width="64" Height="64"
|
||||
Classes.good="{Binding IsGood}" Classes.caution="{Binding IsCaution}"
|
||||
Classes.bad="{Binding IsBad}" Classes.unknown="{Binding IsUnknown}" />
|
||||
<Viewbox Width="28" Height="28">
|
||||
<Path Classes="icon" Data="{Binding Icon}" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
<TextBlock Classes="nodeTitle" Text="{Binding Title}" TextAlignment="Center" />
|
||||
<TextBlock Classes="nodeSubtitle" Text="{Binding Subtitle}" TextAlignment="Center" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<ItemsControl ItemsSource="{Binding Path}" IsVisible="{Binding IsNarrow}" HorizontalAlignment="Center" MinWidth="280" Margin="16,0">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:PathNodeViewModel">
|
||||
<StackPanel>
|
||||
<Grid Height="36" ColumnDefinitions="64,*" IsVisible="{Binding ShowConnector}">
|
||||
<Line Grid.Column="0" StartPoint="32,2" EndPoint="32,34" Classes="connector" Classes.flowing="{Binding IsRunning}" Classes.lit="{Binding IsLit}" />
|
||||
<TextBlock Grid.Column="1" Classes="linkLabel" Text="{Binding LinkLabel}" VerticalAlignment="Center" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Grid ColumnDefinitions="64,*" Classes="node" Classes.lit="{Binding IsLit}"
|
||||
AutomationProperties.AutomationId="{Binding AutomationId}">
|
||||
<Grid Grid.Column="0" Width="56" Height="56">
|
||||
<Ellipse Classes="pulse" Width="56" Height="56" IsVisible="{Binding IsRunning}" />
|
||||
<Ellipse Classes="disc" Width="56" Height="56"
|
||||
Classes.good="{Binding IsGood}" Classes.caution="{Binding IsCaution}"
|
||||
Classes.bad="{Binding IsBad}" Classes.unknown="{Binding IsUnknown}" />
|
||||
<Viewbox Width="24" Height="24">
|
||||
<Path Classes="icon" Data="{Binding Icon}" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="12,0,0,0" Spacing="2">
|
||||
<TextBlock Classes="nodeTitle" Text="{Binding Title}" />
|
||||
<TextBlock Classes="nodeSubtitle" Text="{Binding Subtitle}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Spacing="8" IsVisible="{Binding HasResults}">
|
||||
<TextBlock Classes="section" Text="{s:Tr ResultsTitle}" HorizontalAlignment="Center" />
|
||||
<ItemsControl ItemsSource="{Binding Cards}" HorizontalAlignment="Center">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel ItemWidth="{Binding CardWidth}" HorizontalAlignment="Center" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:CardViewModel">
|
||||
<Border Classes="card"
|
||||
Classes.good="{Binding IsGood}" Classes.caution="{Binding IsCaution}"
|
||||
Classes.bad="{Binding IsBad}" Classes.unknown="{Binding IsUnknown}" Classes.info="{Binding IsInfo}">
|
||||
<StackPanel Spacing="10">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<Path Grid.Column="0" Classes="icon" Data="{Binding Icon}" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Classes="cardTitle" Text="{Binding Title}" />
|
||||
<Border Grid.Column="2" Classes="chip">
|
||||
<TextBlock Text="{Binding OutcomeFormatted}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
<ProgressBar Classes="thin" IsIndeterminate="True" IsVisible="{Binding ShowRunning}" />
|
||||
<TextBlock Classes="summary" Text="{Binding Summary}" IsVisible="{Binding ShowSettled}" />
|
||||
<ItemsControl ItemsSource="{Binding Facts}" IsVisible="{Binding ShowSettled}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:FactViewModel">
|
||||
<Grid ColumnDefinitions="2*,3*" Margin="0,3">
|
||||
<TextBlock Grid.Column="0" Classes="factLabel" Text="{Binding Label}" />
|
||||
<StackPanel Grid.Column="1">
|
||||
<SelectableTextBlock Classes="factValue" Text="{Binding Value}" IsVisible="{Binding ShowValue}" />
|
||||
<Button Classes="link" Content="{Binding Source}" IsVisible="{Binding ShowSource}"
|
||||
AutomationProperties.AutomationId="{Binding AutomationId}"
|
||||
Command="{Binding OpenCommand}" />
|
||||
<Button Classes="link" Content="{Binding Value}" IsVisible="{Binding ShowPlainLink}"
|
||||
AutomationProperties.AutomationId="{Binding AutomationId}"
|
||||
Command="{Binding OpenCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Expander Classes="explain" Header="{s:Tr WhatIsThis}" IsExpanded="{Binding IsExpanded}"
|
||||
AutomationProperties.AutomationId="{Binding ExplainAutomationId}">
|
||||
<TextBlock Classes="body" FontSize="14" Text="{Binding Explain}" />
|
||||
</Expander>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
|
||||
<Border Classes="scrim" IsVisible="{Binding ShowContacts}">
|
||||
<Border Classes="sheet">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel Spacing="14">
|
||||
<Grid ColumnDefinitions="*,Auto">
|
||||
<TextBlock Classes="section" Margin="0" Text="{s:Tr Contacts}" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" Classes="quiet" Content="{s:Tr Close}"
|
||||
AutomationProperties.AutomationId="contacts-close"
|
||||
Command="{Binding ToggleContactsCommand}" />
|
||||
</Grid>
|
||||
<TextBlock Classes="body" Text="{s:Tr ContactsIntro}" />
|
||||
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||
<Path Grid.Row="0" Classes="icon" Data="{StaticResource IconServer}" VerticalAlignment="Top" Margin="0,0,12,12" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Classes="body" Text="{s:Tr ContactServer}" Margin="0,0,0,12" />
|
||||
<Path Grid.Row="1" Classes="icon" Data="{StaticResource IconRouter}" VerticalAlignment="Top" Margin="0,0,12,12" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Classes="body" Text="{s:Tr ContactRouter}" Margin="0,0,0,12" />
|
||||
<Path Grid.Row="2" Classes="icon" Data="{StaticResource IconRoute}" VerticalAlignment="Top" Margin="0,0,12,12" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Classes="body" Text="{s:Tr ContactRoute}" Margin="0,0,0,12" />
|
||||
<Path Grid.Row="3" Classes="icon" Data="{StaticResource IconGlobe}" VerticalAlignment="Top" Margin="0,0,12,12" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Classes="body" Text="{s:Tr ContactDns}" Margin="0,0,0,12" />
|
||||
<Path Grid.Row="4" Classes="icon" Data="{StaticResource IconArrowUpRight}" VerticalAlignment="Top" Margin="0,0,12,0" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Classes="body" Text="{s:Tr ContactLinks}" />
|
||||
</Grid>
|
||||
<TextBlock Classes="body" Text="{s:Tr PrivacyLine}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Button Classes="quiet" Content="{s:Tr ClearHistory}"
|
||||
AutomationProperties.AutomationId="contacts-clear-history"
|
||||
Command="{Binding ClearHistoryCommand}" />
|
||||
<TextBlock Classes="small" Text="{s:Tr HistoryCleared}" VerticalAlignment="Center" IsVisible="{Binding HistoryCleared}" />
|
||||
</StackPanel>
|
||||
<TextBlock Classes="small" Text="{s:Tr AboutLine}" />
|
||||
<Button Classes="link" Content="{s:Tr SourceCode}"
|
||||
AutomationProperties.AutomationId="contacts-source"
|
||||
Command="{Binding OpenSourceCommand}" />
|
||||
<TextBlock Classes="small" Text="{Binding MapFormatted}" />
|
||||
<TextBlock Classes="small" Text="{s:Tr IconsCredit}" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -1,3 +1,4 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
@@ -12,10 +13,15 @@ public partial class MainView : UserControl
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
if (DataContext is MainViewModel model)
|
||||
{
|
||||
model.Launcher = TopLevel.GetTopLevel(this)?.Launcher;
|
||||
model.RefreshCommand.Execute(null);
|
||||
}
|
||||
if (DataContext is not MainViewModel model) return;
|
||||
model.Launcher = TopLevel.GetTopLevel(this)?.Launcher;
|
||||
model.AvailableWidth = Bounds.Width;
|
||||
model.StartCommand.Execute(null);
|
||||
}
|
||||
|
||||
protected override void OnSizeChanged(SizeChangedEventArgs e)
|
||||
{
|
||||
base.OnSizeChanged(e);
|
||||
if (DataContext is MainViewModel model) model.AvailableWidth = e.NewSize.Width;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user