Skip to content

Commit f9e6f1c

Browse files
authored
Merge pull request LykosAI#1601 from LykosAI/main
2 parents 2feb162 + 730d1c2 commit f9e6f1c

Some content is hidden

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

47 files changed

+3292
-279
lines changed

CHANGELOG.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,45 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
77

88
## v2.15.7
9+
### Added
10+
- Added single-instance window activation signaling so reopening the app restores and focuses the existing desktop window instead of launching a duplicate instance
11+
- Added notification system with localizable banner and markdown detail dialog UI
12+
- Added warning in data directory selector when an OneDrive folder is selected
13+
- Added support in the Checkpoints page to distinguish standard updates from Early Access-only updates - thanks to @x0x0b!
14+
- Added torch index for Strix/Gorgon Point Ryzen AI APUs on Windows - thanks to @NeuralFault!
15+
- Added retry button to failed downloads - thanks to @NeuralFault!
16+
- Added new Membership support in Account Settings with Patreon migration prompt
917
### Changed
1018
- Settings file saves are now atomic to prevent corruption from interrupted writes
11-
### Fixed
19+
- Updated torch indexes for A1111, ComfyUI, InvokeAI, and Forge-based UIs to rocm7.2 / cu128 depending on GPU - thanks to @NeuralFault!
20+
- Replaced the "Become a Patron" footer button with "Support Us", linking to the new direct Lykos support page at lykos.ai/membership
21+
- Updated the prompt dialog shown when enabling features like Accelerated Model Discovery to use Lykos accounts instead of Patreon linking
22+
- Moved the Patreon connection in Account Settings to a new "Legacy Connections" section, only shown for users with an existing Patreon link
23+
- Localized previously hardcoded strings on the Account Settings page (menu items, descriptions, section headers) and added Japanese, Korean, German, and French translations
24+
### Fixed
25+
- Fixed an issue where `Align Your Steps` scheduler and Unet Loader workflows ignored Regional Prompting (and other addon) conditioning modifiers.
26+
- Fixed the Package Manager "Add Package" teaching tip opening inopportunely while packages were still loading or after opening the add-package dialog
27+
- Fixed bold text not rendering in markdown dialogs on Windows 11 due to Avalonia 11.3.x variable font regression with Segoe UI Variable Text
28+
- Fixed Japanese text appearing compressed/squished in markdown dialogs by ensuring the bundled NotoSansJP font is used for CTextBlock rendering
29+
- Fixed ContentDialog title and buttons not using the correct font for Japanese locale (NotoSansJP) when shown as overlay
30+
- Added missing `CBold` and `CItalic` inline styles to the markdown style sheet
31+
- Fixed downloads failing with "The request message was already sent" when the server doesn't return Content-Length on the first attempt, caused by reusing a consumed HttpRequestMessage in the retry loop
32+
- Fixed downloads from sources that redirect to CivitAI/HuggingFace (e.g. CivArchive) failing with Unauthorized by resolving the redirect target URL and applying auth headers for the correct domain
33+
- Fixed dropdown menu overlayed in Inference UI Model Cards not being scrollable on Linux - thanks to @NeuralFault!
34+
- Fixed model downloads failing on VPN connections - thanks to @NeuralFault!
35+
- Fixed [#1598](https://github.com/LykosAI/StabilityMatrix/issues/1598) - download progress bar showing 100% immediately for fresh downloads due to missing Content-Length fallback when Content-Range header is absent
36+
- Fixed [#1597](https://github.com/LykosAI/StabilityMatrix/issues/1597) - reForge launch failing due to setuptools version
37+
- Fixed [#1596](https://github.com/LykosAI/StabilityMatrix/issues/1596) - package installs and managed embedded Python startup being poisoned by inherited shell Python activation variables such as `PYTHONHOME`, `PYTHONPATH`, `VIRTUAL_ENV`, and Conda environment variables
1238
- Fixed [#1590](https://github.com/LykosAI/StabilityMatrix/issues/1590) - Startup crash when settings file is corrupted. Settings files are now self-healing with automatic recovery from null bytes, truncated JSON, and missing brackets
39+
- Potentially fixed [#1578](https://github.com/LykosAI/StabilityMatrix/issues/1578) - `SocketException: Address already in use` on Linux startup by cleaning stale interprocess socket files and reactivating the existing window
40+
- Fixed [#1397](https://github.com/LykosAI/StabilityMatrix/issues/1397), [#610](https://github.com/LykosAI/StabilityMatrix/issues/610) - duplicate pip package entries in results - thanks to @e-nord!
41+
### Supporters
42+
#### 🌟 Visionaries
43+
Lifting up our legendary Visionaries: **Waterclouds**, **JungleDragon**, **bluepopsicle**, **Bob S**, and **whudunit**. Through every release, every milestone, and every twist of this wild journey, your support has been our north star. A huge welcome to our newest Visionaries **Droolguy** and **snotty** (leveling up from the Pioneer crew!), a warm welcome back to longtime Visionary **Ibixat**, and an equally huge welcome to **LG** and **MrMxyzptlk12836**, making their Stability Matrix debut straight at the Visionary tier - so glad to have you all on board! We cannot thank you enough for standing behind Stability Matrix!
44+
#### 🚀 Pioneers
45+
And to our mighty Pioneer crew - the folks who keep the engine humming - thank you for everything! Massive shoutout to: **Szir777**, **Noah M**, **[USA]TechDude**, **Thom**, **SeraphOfSalem**, **Desert Viber**, **Adam**, **ACTUALLY_the_Real_Willem_Dafoe**, **takyamtom**, **robek**, **Ghislain G**, **Phil R**, **Tundra Everquill**, **Andrew B**, **SinthCore**, and **Ahmed S**. And a very warm welcome to our newest Pioneers **Commissar Lord Death**, **Firelight**, and **jweg**, plus a heartfelt shoutout to one more new Pioneer who joined us quietly through the Stripe migration - you know who you are, and we're so glad to have you!
46+
47+
And one more heartfelt thank you to everyone now supporting us directly through our new platform - this next chapter wouldn't be possible without your trust, and we're so grateful you've come along for the ride!
1348

1449
## v2.15.6
1550
### Added

StabilityMatrix.Avalonia/App.axaml.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,13 @@ internal static void ConfigurePageViewModels(IServiceCollection services)
376376
provider.GetRequiredService<IModelIndexService>(),
377377
provider.GetRequiredService<Lazy<IModelDownloadLinkHandler>>(),
378378
provider.GetRequiredService<INotificationService>(),
379+
provider.GetRequiredService<IAppNotificationService>(),
379380
provider.GetRequiredService<IAnalyticsHelper>(),
380381
provider.GetRequiredService<IUpdateHelper>(),
381382
provider.GetRequiredService<ISecretsManager>(),
382383
provider.GetRequiredService<INavigationService<MainWindowViewModel>>(),
383-
provider.GetRequiredService<INavigationService<SettingsViewModel>>()
384+
provider.GetRequiredService<INavigationService<SettingsViewModel>>(),
385+
provider.GetRequiredService<IDistributedSubscriber<string, Uri>>()
384386
)
385387
{
386388
Pages =
@@ -451,6 +453,14 @@ internal static IServiceCollection ConfigureServices(bool disableMessagePipeInte
451453
// Named pipe interprocess communication on Windows and Linux for uri handling
452454
if (!disableMessagePipeInterprocess && (Compat.IsWindows || Compat.IsLinux))
453455
{
456+
// On Linux, named pipes use Unix domain sockets which leave stale socket files
457+
// if the app crashes or exits without cleanup. Delete the stale file if no other
458+
// instance is running, so the new instance can bind successfully.
459+
if (Compat.IsLinux)
460+
{
461+
CleanupStaleUnixSocket("StabilityMatrix");
462+
}
463+
454464
services.AddMessagePipe().AddNamedPipeInterprocess("StabilityMatrix");
455465
}
456466
else
@@ -973,6 +983,47 @@ private void OnExit(object? sender, EventArgs _)
973983
}
974984
}
975985

986+
/// <summary>
987+
/// On Linux, .NET named pipes use Unix domain sockets. If the app exits without cleanup,
988+
/// the socket file remains and prevents the next instance from binding.
989+
/// This deletes the stale socket file if no other instance holds it.
990+
/// </summary>
991+
private static void CleanupStaleUnixSocket(string pipeName)
992+
{
993+
try
994+
{
995+
var tempPath = Path.GetTempPath();
996+
var socketPath = Path.Combine(tempPath, $"CoreFxPipe_{pipeName}");
997+
998+
if (!File.Exists(socketPath))
999+
return;
1000+
1001+
// Try connecting to see if another instance is actually listening
1002+
using var socket = new System.Net.Sockets.Socket(
1003+
System.Net.Sockets.AddressFamily.Unix,
1004+
System.Net.Sockets.SocketType.Stream,
1005+
System.Net.Sockets.ProtocolType.Unspecified
1006+
);
1007+
1008+
try
1009+
{
1010+
socket.Connect(new System.Net.Sockets.UnixDomainSocketEndPoint(socketPath));
1011+
// Connected successfully - another instance is running, don't delete
1012+
}
1013+
catch (System.Net.Sockets.SocketException ex)
1014+
when (ex.SocketErrorCode == System.Net.Sockets.SocketError.ConnectionRefused)
1015+
{
1016+
// A refused connection means the socket file exists but nothing is listening anymore.
1017+
File.Delete(socketPath);
1018+
Logger.Info("Deleted stale Unix domain socket: {SocketPath}", socketPath);
1019+
}
1020+
}
1021+
catch (Exception e)
1022+
{
1023+
Logger.Warn(e, "Failed to clean up stale Unix domain socket");
1024+
}
1025+
}
1026+
9761027
private static void OnServiceProviderDisposing(ServiceProvider serviceProvider)
9771028
{
9781029
// Force materialize SharedFolders so its DisposeAsync is called

StabilityMatrix.Avalonia/Assets.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ internal static class Assets
155155

156156
public static Uri PatreonUrl { get; } = new("https://patreon.com/StabilityMatrix");
157157

158+
public static Uri MembershipUrl { get; } = new("https://lykos.ai/membership?ref=a1");
159+
160+
public static Uri PatreonBlogPostUrl { get; } = new("https://lykos.ai/blog/patreon-update");
161+
158162
public static Uri CivitAIUrl { get; } = new("https://civitai.com");
159163

160164
public static Uri LykosForgotPasswordUrl { get; } = new("https://lykos.ai/forgot-password");

StabilityMatrix.Avalonia/Controls/BetterContentDialog.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,14 @@ public bool CloseOnClickOutside
196196

197197
public BetterContentDialog()
198198
{
199+
// Ensure the dialog uses the correct platform font (e.g. NotoSansJP for Japanese).
200+
// ContentDialog is shown as an overlay and its template elements (title, buttons)
201+
// don't inherit ContentControlThemeFontFamily from the app resources.
202+
if (App.Current is { } app)
203+
{
204+
FontFamily = app.GetPlatformDefaultFontFamily();
205+
}
206+
199207
AddHandler(LoadedEvent, OnLoaded);
200208
}
201209

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<UserControl
2+
x:Class="StabilityMatrix.Avalonia.Controls.NotificationBanner"
3+
xmlns="https://github.com/avaloniaui"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:designData="clr-namespace:StabilityMatrix.Avalonia.DesignData"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
xmlns:ui="using:FluentAvalonia.UI.Controls"
9+
xmlns:vm="using:StabilityMatrix.Avalonia.ViewModels"
10+
d:DataContext="{x:Static designData:DesignData.NotificationBannerViewModel}"
11+
d:DesignHeight="150"
12+
d:DesignWidth="1100"
13+
x:DataType="vm:NotificationBannerViewModel"
14+
IsVisible="{Binding IsVisible}"
15+
mc:Ignorable="d">
16+
17+
<ui:InfoBar
18+
Margin="12,8,12,4"
19+
CloseButtonCommand="{Binding DismissClickedCommand}"
20+
FontSize="14"
21+
FontWeight="SemiBold"
22+
IsClosable="{Binding IsDismissible}"
23+
IsOpen="True"
24+
Message="{Binding Message}"
25+
Severity="{Binding Severity}">
26+
<ui:InfoBar.ActionButton>
27+
<Button
28+
Command="{Binding ActionClickedCommand}"
29+
Content="{Binding ActionLabel}"
30+
IsVisible="{Binding HasAction}" />
31+
</ui:InfoBar.ActionButton>
32+
</ui:InfoBar>
33+
</UserControl>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Avalonia.Controls;
2+
using Injectio.Attributes;
3+
4+
namespace StabilityMatrix.Avalonia.Controls;
5+
6+
[RegisterTransient<NotificationBanner>]
7+
public partial class NotificationBanner : UserControlBase
8+
{
9+
public NotificationBanner()
10+
{
11+
InitializeComponent();
12+
}
13+
}

StabilityMatrix.Avalonia/DesignData/DesignData.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Collections.ObjectModel;
44
using System.ComponentModel;
@@ -475,6 +475,27 @@ public static void Initialize()
475475
public static FirstLaunchSetupViewModel FirstLaunchSetupViewModel =>
476476
Services.GetRequiredService<FirstLaunchSetupViewModel>();
477477

478+
public static NotificationBannerViewModel NotificationBannerViewModel =>
479+
DialogFactory.Get<NotificationBannerViewModel>(vm =>
480+
{
481+
vm.Show(
482+
new Core.Models.Notifications.AppNotification
483+
{
484+
Id = "test",
485+
Type = Core.Models.Notifications.AppNotificationType.Banner,
486+
Priority = Core.Models.Notifications.AppNotificationPriority.Normal,
487+
Message = new Dictionary<string, string> { { "en", "This is a test notification." } },
488+
Style = new Core.Models.Notifications.AppNotificationStyle { Variant = "info" },
489+
Action = new Core.Models.Notifications.AppNotificationAction
490+
{
491+
Type = Core.Models.Notifications.AppNotificationActionType.Url,
492+
Label = new Dictionary<string, string> { { "en", "Learn More" } },
493+
Url = "https://example.com",
494+
},
495+
}
496+
);
497+
});
498+
478499
public static LaunchPageViewModel LaunchPageViewModel =>
479500
Services.GetRequiredService<LaunchPageViewModel>();
480501

0 commit comments

Comments
 (0)