Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e42892a
WIP settings page
redstonekasi Nov 26, 2024
3b8113c
Fix settings page, WIP exit node, UI polishing pass
xirreal Feb 7, 2025
5dd7fc3
Working exit nodes with suggested exit node
xirreal Feb 7, 2025
0287c79
Fix account switching crash
xirreal Feb 7, 2025
1f0b027
Fix random crashing when switching from a profile that does not suppo…
xirreal Feb 7, 2025
da556e0
Small fix to installer failing to cleanup if a previous install faile…
xirreal Feb 7, 2025
6164e0e
Switch to unpackaged build
xirreal May 12, 2025
c8d4e35
Autoupdater, icon changes
xirreal May 12, 2025
299f065
Clone with history in CI to calculate correct version
xirreal May 12, 2025
4c319e6
Bump version to 1.4
xirreal May 12, 2025
ff1b654
WIP settings page
redstonekasi Nov 26, 2024
05172ab
Fix settings page, WIP exit node, UI polishing pass
xirreal Feb 7, 2025
4edecf3
Working exit nodes with suggested exit node
xirreal Feb 7, 2025
a540ae2
Fix account switching crash
xirreal Feb 7, 2025
be4ba2f
Fix random crashing when switching from a profile that does not suppo…
xirreal Feb 7, 2025
7333550
Small fix to installer failing to cleanup if a previous install faile…
xirreal Feb 7, 2025
bada9f2
Switch to unpackaged build
xirreal May 12, 2025
c81ad0e
Autoupdater, icon changes
xirreal May 12, 2025
f171563
Clone with history in CI to calculate correct version
xirreal May 12, 2025
ad56e72
Bump version to 1.4
xirreal May 12, 2025
8f5dee8
Merge branch 'wip-settings' of https://github.com/uwu/tailscale-clien…
xirreal May 12, 2025
1d54138
Allow startup on failed update: needs to be finished later.
xirreal May 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions .github/workflows/build-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ jobs:
runs-on: windows-latest

steps:
- name: Check out repository
- name: Check out repository, with full history
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up .NET
uses: actions/setup-dotnet@v4
Expand All @@ -33,22 +35,11 @@ jobs:
run: |
Add-Content $env:GITHUB_PATH "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64"

- name: Install code signing certificate
env:
base64Pfx: ${{ secrets.PFX_B64 }}
password: ${{ secrets.PFX_PASS }}
run: |
$securePassword = ConvertTo-SecureString -String $env:password -AsPlainText -Force
$pfxBytes = [System.Convert]::FromBase64String($env:base64Pfx)
$tempPfxPath = [System.IO.Path]::GetTempFileName()
[System.IO.File]::WriteAllBytes($tempPfxPath, $pfxBytes)
Import-PfxCertificate -FilePath $tempPfxPath -CertStoreLocation Cert:\CurrentUser\My -Password $securePassword

- name: Run package script
shell: pwsh
- name: Build x64 and ARM64
run: |
./package.ps1
mkdir -Force dist
dotnet restore
dotnet msbuild TailscaleClient.csproj -t:Rebuild -p:Platform=x64 -p:Configuration=Release -p:OutDir="./dist/x64/"
dotnet msbuild TailscaleClient.csproj -t:Rebuild -p:Platform=arm64 -p:Configuration=Release -p:OutDir="./dist/arm64/"

- name: Upload build artifacts
uses: actions/upload-artifact@v4
Expand All @@ -58,7 +49,7 @@ jobs:

release:
name: Release Package
runs-on: ubuntu-latest
runs-on: windows-latest
needs: build
if: startsWith(github.ref, 'refs/tags/v')

Expand All @@ -68,14 +59,31 @@ jobs:
with:
name: dist

- name: "Upload to R2"
- name: Install packaging tools
run: |
dotnet tool install -g nbgv
dotnet tool install -g vpk

- name: Sync vpk to current version
run: |
vpk download http --url https://tsc.xirreal.dev/

- name: Package x64
run: |
vpk pack --packId TailscaleClient --packVersion $(nbgv get-version -v SimpleVersion) --packDir ./x64 --channel win-x64 --framework net8.0-x64-runtime

- name: Package arm64
run: |
vpk pack --packId TailscaleClient --packVersion $(nbgv get-version -v SimpleVersion) --packDir ./arm64 --channel win-arm64 --framework net8.0-arm64-runtime

- name: Upload to R2
env:
AWS_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
AWS_ENDPOINT_URL: ${{ secrets.S3_ENDPOINT_URL }}
run: |
aws s3 sync ./ s3://tsc/
aws s3 sync ./Releases s3://tsc/

- name: Create a new release
uses: softprops/action-gh-release@v2
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -363,4 +363,5 @@ MigrationBackup/
FodyWeavers.xsd

# Custom dist folder
dist/
dist/
codegen/
23 changes: 22 additions & 1 deletion App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.UI.Xaml;
using System;
using Microsoft.UI.Xaml;
using Velopack;

namespace TailscaleClient;

Expand All @@ -10,7 +12,26 @@

public App()
{
VelopackApp.Build().Run();
InitializeComponent();

var mgr = new UpdateManager("https://tsc.xirreal.dev");

try
{
var newVersion = mgr.CheckForUpdates();
if (newVersion == null)
{
return;
}

mgr.DownloadUpdates(newVersion);
mgr.ApplyUpdatesAndRestart(newVersion);
} catch (Exception e)

Check warning on line 30 in App.xaml.cs

View workflow job for this annotation

GitHub Actions / Build Package

The variable 'e' is declared but never used

Check warning on line 30 in App.xaml.cs

View workflow job for this annotation

GitHub Actions / Build Package

The variable 'e' is declared but never used

Check warning on line 30 in App.xaml.cs

View workflow job for this annotation

GitHub Actions / Build Package

The variable 'e' is declared but never used

Check warning on line 30 in App.xaml.cs

View workflow job for this annotation

GitHub Actions / Build Package

The variable 'e' is declared but never used
{
// TODO: Show failed update bar, possibly a badge on settings?
return;
}
}

protected override void OnLaunched(LaunchActivatedEventArgs args)
Expand Down
4 changes: 2 additions & 2 deletions Assets/AccountCard.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
<TextBlock Text="{x:Bind UserName, Mode=OneWay}" FontSize="16" FontWeight="Bold" VerticalAlignment="Center"/>
<TextBlock Text="{x:Bind Tailnet, Mode=OneWay}" FontSize="13" VerticalAlignment="Center"/>
<TextBlock Text="{x:Bind UserName, Mode=OneWay}" Style="{StaticResource BodyStrongTextBlockStyle}" VerticalAlignment="Center"/>
<TextBlock Foreground="{StaticResource TextFillColorSecondary}" Text="{x:Bind Tailnet, Mode=OneWay}" Style="{StaticResource CaptionTextBlockStyle}" VerticalAlignment="Center"/>
</StackPanel>
<Ellipse Height="36" Width="36" HorizontalAlignment="Right" Grid.Column="1">
<Ellipse.Fill>
Expand Down
2 changes: 1 addition & 1 deletion Assets/DeviceCard.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<BitmapIcon Grid.Column="0" Width="12" Height="12" UriSource="{x:Bind OSIcon, Mode=OneTime}" Foreground="{ThemeResource TextFillColorPrimary}"/>
<TextBlock Grid.Column="1" x:Name ="hostnameTextBlock" Text="{x:Bind Hostname, Mode=OneTime}" Margin="6,0,0,4" ToolTipService.ToolTip="Click to copy" PointerReleased="CopyToClipboard" PointerEntered="HoverStart" PointerExited="HoverEnd"/>
<TextBlock Grid.Column="1" x:Name ="hostnameTextBlock" Style="{StaticResource BodyStrongTextBlockStyle}" Text="{x:Bind Hostname, Mode=OneTime}" Margin="6,0,0,4" ToolTipService.ToolTip="Click to copy" PointerReleased="CopyToClipboard" PointerEntered="HoverStart" PointerExited="HoverEnd"/>
<Ellipse Height="24" Width="24" Margin="0,0,-2,0" HorizontalAlignment="Right" Grid.Column="2" ToolTipService.ToolTip="{x:Bind OwnedByString, Mode=OneTime}" Visibility="{x:Bind IsOwnedByCurrentUser, Mode=OneTime}">
<Ellipse.Fill>
<ImageBrush>
Expand Down
9 changes: 3 additions & 6 deletions Assets/DeviceCard.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,17 @@ private static string FormatDaysUntilExpiry(int daysUntilExpiry)

return daysUntilExpiry switch
{
<
0 => "Expired",
<0 => "Expired",
0 => "Key expiring today",
_ => $"Expiring in {daysUntilExpiry} {daysText}"

};
}

private static Windows.UI.Color FormatColorForExpiry(int daysUntilExpiry)
{
return daysUntilExpiry switch
{
<=
0 => Windows.UI.Color.FromArgb(255, 255, 0, 0),
<=0 => Windows.UI.Color.FromArgb(255, 255, 0, 0),
_ => Windows.UI.Color.FromArgb(255, 255, 150, 0),
};
}
Expand Down Expand Up @@ -157,7 +154,7 @@ public DeviceCard(Core.Types.PeerInfo device, Dictionary<string, Core.Types.User
var days = (device.KeyExpiry - DateTime.Now).TotalDays;
if (days <= 14)
{
var roundedDays = (int)Math.Floor(days);
var roundedDays = (int)Math.Ceiling(days);
var expiryTag = new FeatureTag(FormatDaysUntilExpiry(roundedDays),
"To refresh the key, reauthenticate on the device.",
FormatColorForExpiry(roundedDays));
Expand Down
16 changes: 16 additions & 0 deletions Assets/FlippedSwitch.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="TailscaleClient.Assets.FlippedSwitch"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TailscaleClient.Assets"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="using:TailscaleClient.Views"
mc:Ignorable="d">

<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock x:Name="StatusText" Text="{x:Bind Status, Mode=OneWay}" VerticalAlignment="Center" Margin="0,0,10,0"/>
<ToggleSwitch x:Name="ToggleSwitch" IsOn="{x:Bind IsOn, Mode=TwoWay}" Toggled="ToggleSwitch_Toggled" OnContent="" OffContent="" MinWidth="0" />
</StackPanel>
</UserControl>
64 changes: 64 additions & 0 deletions Assets/FlippedSwitch.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace TailscaleClient.Assets;

public sealed partial class FlippedSwitch : UserControl, INotifyPropertyChanged
{
public FlippedSwitch()
{
InitializeComponent();
}

public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public static readonly DependencyProperty IsOnProperty =
DependencyProperty.Register(
nameof(IsOn),
typeof(bool),
typeof(FlippedSwitch),
new PropertyMetadata(false, OnIsOnChanged));

public bool IsOn
{
get => (bool)GetValue(IsOnProperty);
set => SetValue(IsOnProperty, value);
}

private static void OnIsOnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (FlippedSwitch)d;
control.UpdateStatusText();
}

public event RoutedEventHandler Toggled;

private void ToggleSwitch_Toggled(object sender, RoutedEventArgs e)
{
Toggled?.Invoke(sender, e);
UpdateStatusText();
}

private string _status = "Off";
public string Status
{
get => _status;
set
{
_status = value;
OnPropertyChanged();
}
}

private void UpdateStatusText()
{
Status = ToggleSwitch.IsOn ? "On" : "Off";
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.altform-unplated_targetsize-16.png
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.scale-100.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.scale-125.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.scale-150.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.scale-200.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.scale-400.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.targetsize-16.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.targetsize-24.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.targetsize-256.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.targetsize-32.png
Binary file not shown.
Binary file removed Assets/Icons/AppIcon.targetsize-48.png
Binary file not shown.
Binary file modified Assets/Icons/AppIconBase-Dark.ico
Binary file not shown.
Binary file modified Assets/Icons/AppIconBase-Light.ico
Binary file not shown.
27 changes: 15 additions & 12 deletions Core/API.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ public static bool Init()
{
BaseAddress = new Uri("http://local-tailscaled.sock"),
DefaultRequestHeaders = { { "User-Agent", "Go-http-client/1.1" },
{ "Tailscale-Cap", "95" }, // TODO: Get the real value i just
// copied it from tailscale-ipn packets
{ "Tailscale-Cap", "113" }, // Latest (as of 2025/02/07) from https://github.com/tailscale/tailscale/blob/main/tailcfg/tailcfg.go
{ "Accept-Encoding", "gzip" } },
Timeout = TimeSpan.FromSeconds(2)
};
Expand Down Expand Up @@ -182,9 +181,9 @@ public static Types.Profile GetCurrentUser()
return GET<List<Types.Profile>>("/localapi/v0/profiles/");
}

public static Types.Prefs GetPrefs()
public static Types.MaskedPrefs GetPrefs()
{
return GET<Types.Prefs>("/localapi/v0/prefs");
return GET<Types.MaskedPrefs>("/localapi/v0/prefs");
}

public static void SwitchEmptyProfile()
Expand All @@ -202,19 +201,19 @@ public static void DeleteProfile(string userId)
DELETE<object, object>($"localapi/v0/profiles/{userId}", new { });
}

public static void Start(Types.Prefs prefs)
public static void Start(Types.MaskedPrefs prefs)
{
POST<object, object>("/localapi/v0/start", new { UpdatePrefs = prefs });
}

public static Types.Prefs UpdatePrefs(Types.Prefs prefs)
public static Types.MaskedPrefs UpdatePrefs(Types.MaskedPrefs prefs)
{
return PATCH<Types.Prefs, Types.Prefs>("/localapi/v0/prefs", prefs);
return PATCH<Types.MaskedPrefs, Types.MaskedPrefs>("/localapi/v0/prefs", prefs);
}

public static void CheckPrefs(Types.Prefs prefs)
public static string CheckPrefs(Types.MaskedPrefs prefs)
{
POST<string, Types.Prefs>("/localapi/v0/check-prefs", prefs);
return POST<string, Types.MaskedPrefs>("/localapi/v0/check-prefs", prefs);
}

public static void Logout()
Expand All @@ -227,7 +226,7 @@ public static void Login(string controlUrl)
SwitchEmptyProfile();

var prefs =
new Types.Prefs() { WantRunning = true, ControlURL = controlUrl };
new Types.MaskedPrefs() { WantRunning = true, ControlURL = controlUrl };
Start(prefs);
POST<object, object>("/localapi/v0/login-interactive", new { });
}
Expand All @@ -241,11 +240,15 @@ public static void Connect()
{
var currentPrefs = GetPrefs();
currentPrefs.WantRunning = true;
currentPrefs.WantRunningSet = true;
UpdatePrefs(currentPrefs);
}
public static void Disconnect()
{
UpdatePrefs(new Types.Prefs { WantRunning = false, WantRunningSet = true });
UpdatePrefs(new Types.MaskedPrefs { WantRunning = false });
}

public static Types.SuggestedExitNode GetSuggestedExitNode()
{
return GET<Types.SuggestedExitNode>("/localapi/v0/suggest-exit-node");
}
}
Loading