Skip to content

Commit

Permalink
Gif background functionality (#29)
Browse files Browse the repository at this point in the history
* Merge dev and master btanches (#28)

* Update host URL in ResourceKeysDictionary

The host URL used in the ResourceKeysDictionary file has been updated from a local address to a production address. Additionally, a minor formatting change was made in the OverviewPageViewModel file.

* Replace submodule update with git clone in scripts

The git submodule update command in both the 'load-repositories.sh' and 'load-repositories.bat' scripts has been replaced with git clone. This allows for repositories 'GamerVII.Notification.Avalonia' and 'Gml.Client' to be cloned directly instead of being updated through submodules.

* Update system service, resources, and application UI

The system service has been updated to asynchronously load system data. Additional resource keys and corresponding translations have been added to the localization service. Several changes have been made to the application user interface including a new splash screen, application icon, and version number.

* Update submodule link Gml.Client

* Add error tracking to AsyncStreamToImageLoader

The update wraps the core logic of the OnSourceChanged method inside a try-catch block. In case of any exceptions during execution, they are captured and sent to Sentry for error tracking and troubleshooting. This ensures smoother runtime and easier debugging.

* Update host URL and clean up code

The host URL in the ResourceKeysDictionary file was changed from a local IP address to an external URL "https://gmlb.recloud.tech".

* Add error tracking to AsyncStreamToImageLoader

The update wraps the core logic of the OnSourceChanged method inside a try-catch block. In case of any exceptions during execution, they are captured and sent to Sentry for error tracking and troubleshooting. This ensures smoother runtime and easier debugging.

* Update host URL and clean up code

The host URL in the ResourceKeysDictionary file was changed from a local IP address to an external URL "https://gmlb.recloud.tech".

---------

Co-authored-by: GamerVII-NET <gamervii.phone@gmail.com>

* Add GIF decoding functionality

Introduced several new classes to handle the decoding of GIF files. This includes reading the data stream and processing headers, frames, color tables, and extensions. Functionality for rendering frames and handling exceptions has also been implemented.

* Refactor code and optimize exceptions in gif decoder

Code for gif decoding has been refactored for improved readability and efficiency. The exception handling has been optimized for specific errors, such as LzwDecompressionException, contributing to better error reporting and debugging. Unnecessary comments and code have also been removed.

* Remove unnecessary whitespace in AsyncStreamToImageLoader

This commit eliminates a redundant line in the AsyncStreamToImageLoader class file. The change helps to maintain the cleanliness and readability of the code.

---------

Co-authored-by: GamerVII-NET <111225722+GamerVII-NET@users.noreply.github.com>
Co-authored-by: GamerVII-NET <gamervii.phone@gmail.com>
Co-authored-by: s.bryzglov <s.bryzgalov@icvr.io>
Co-authored-by: Anton Terentev <gamervii@icloud.com>
  • Loading branch information
5 people authored Jun 6, 2024
1 parent 19237dc commit 57be648
Show file tree
Hide file tree
Showing 24 changed files with 1,422 additions and 8 deletions.
7 changes: 7 additions & 0 deletions Gml.Launcher.sln
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gml.Web.Api.Domains", "src\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Gml.Core.Interfaces", "src\Gml.Client\src\Gml.Core.Interfaces\Gml.Core.Interfaces.csproj", "{AE697645-C3EB-4FC8-AAA6-932B9751D348}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "L1.Avalonia.Gif", "src\L1.Avalonia.Gif\L1.Avalonia.Gif.csproj", "{19B15268-CF4D-4571-8DF3-6EBC586BB856}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -65,6 +67,10 @@ Global
{AE697645-C3EB-4FC8-AAA6-932B9751D348}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE697645-C3EB-4FC8-AAA6-932B9751D348}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE697645-C3EB-4FC8-AAA6-932B9751D348}.Release|Any CPU.Build.0 = Release|Any CPU
{19B15268-CF4D-4571-8DF3-6EBC586BB856}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19B15268-CF4D-4571-8DF3-6EBC586BB856}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19B15268-CF4D-4571-8DF3-6EBC586BB856}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19B15268-CF4D-4571-8DF3-6EBC586BB856}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -80,5 +86,6 @@ Global
{20707D1F-FF51-4E7B-BF99-2B87065AFDC7} = {662268E9-BD01-43C7-924B-F4F285C8D391}
{88B821C7-B895-4CB0-832A-5B66138B6AF2} = {662268E9-BD01-43C7-924B-F4F285C8D391}
{AE697645-C3EB-4FC8-AAA6-932B9751D348} = {662268E9-BD01-43C7-924B-F4F285C8D391}
{19B15268-CF4D-4571-8DF3-6EBC586BB856} = {662268E9-BD01-43C7-924B-F4F285C8D391}
EndGlobalSection
EndGlobal
19 changes: 17 additions & 2 deletions src/Gml.Launcher/Core/Converters/AsyncStreamToImageLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Avalonia;
using Avalonia.Media.Imaging;
using Gml.Launcher.Views.Components;
using L1.Avalonia.Gif.Decoding;
using Sentry;

namespace Gml.Launcher.Core.Converters;
Expand Down Expand Up @@ -51,7 +52,21 @@ private static async void OnSourceChanged(BackgroundComponent sender, AvaloniaPr
await ConvertStreamToFile(stream, fileName);
}

sender.Source = new Bitmap(File.OpenRead(fileName));

var fileStream = File.OpenRead(fileName);

sender.Classes.Clear();
if (GifDecoder.IsGifStream(fileStream))
{
sender.Classes.Add("Gif");
sender.SourceStream = fileStream;
}
else
{
sender.Classes.Add("Image");
sender.Source = new Bitmap(fileStream);
}

}
catch (Exception exception)
{
Expand All @@ -78,7 +93,7 @@ private static bool ValidateUrl(string url)
{
return Uri.TryCreate(url, UriKind.Absolute, out var uriResult)
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)
&& Path.GetFileName(url) is {} fileName && Guid.TryParse(fileName, out _);
&& Path.GetFileName(url) is { } fileName && Guid.TryParse(fileName, out _);
}

public static void SetSource(BackgroundComponent obj, string value) => obj.SetValue(SourceProperty, value);
Expand Down
1 change: 1 addition & 0 deletions src/Gml.Launcher/Gml.Launcher.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<ProjectReference Include="..\GamerVII.Notification.Avalonia\GamerVII.Notification.Avalonia\GamerVII.Notification.Avalonia.csproj" />
<ProjectReference Include="..\Gml.Client\src\Gml.Client\Gml.Client.csproj" />
<ProjectReference Include="..\Gml.Client\src\Gml.Web.Api.Domains\Gml.Web.Api.Domains.csproj" />
<ProjectReference Include="..\L1.Avalonia.Gif\L1.Avalonia.Gif.csproj" />
</ItemGroup>


Expand Down
13 changes: 11 additions & 2 deletions src/Gml.Launcher/Views/Components/BackgroundComponent.axaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Gml.Launcher.Views.Components">
xmlns:controls="using:Gml.Launcher.Views.Components"
xmlns:gif="clr-namespace:L1.Avalonia.Gif;assembly=L1.Avalonia.Gif">
<Design.PreviewWith>
<controls:BackgroundComponent Width="1920"
Height="1080" />
</Design.PreviewWith>

<Style Selector="controls|BackgroundComponent">
<Style Selector="controls|BackgroundComponent.Image">
<Setter Property="Template">
<ControlTemplate>
<Image Stretch="UniformToFill"
Source="{TemplateBinding Source}" />
</ControlTemplate>
</Setter>
</Style>
<Style Selector="controls|BackgroundComponent.Gif">
<Setter Property="Template">
<ControlTemplate>
<gif:GifImage Stretch="UniformToFill"
SourceStream="{TemplateBinding SourceStream}"/>
</ControlTemplate>
</Setter>
</Style>
</Styles>

14 changes: 10 additions & 4 deletions src/Gml.Launcher/Views/Components/BackgroundComponent.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using System.IO;
using Avalonia;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
using Avalonia.Media.Imaging;

namespace Gml.Launcher.Views.Components;

Expand All @@ -12,11 +11,18 @@ public class BackgroundComponent : TemplatedControl
public static readonly StyledProperty<IImage?> SourceProperty = AvaloniaProperty.Register<BackgroundComponent, IImage?>(
nameof(Source));

public static readonly StyledProperty<Stream?> SourceStreamProperty = AvaloniaProperty.Register<BackgroundComponent, Stream?>(
nameof(SourceStream));

public IImage? Source
{
get => GetValue(SourceProperty);
set => SetValue(SourceProperty, value);
}

public Stream? SourceStream
{
get => GetValue(SourceStreamProperty);
set => SetValue(SourceStreamProperty, value);
}
}

16 changes: 16 additions & 0 deletions src/L1.Avalonia.Gif/AvaloniaGif.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>11</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="L1.Avalonia.Gif.Test" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.0" />
<PackageReference Include="System.Reactive" Version="6.0.0" />
</ItemGroup>

</Project>
9 changes: 9 additions & 0 deletions src/L1.Avalonia.Gif/BgWorkerCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace L1.Avalonia.Gif;

internal enum BgWorkerCommand
{
Null,
Play,
Pause,
Dispose
}
11 changes: 11 additions & 0 deletions src/L1.Avalonia.Gif/BgWorkerState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace L1.Avalonia.Gif;

internal enum BgWorkerState
{
Null,
Start,
Running,
Paused,
Complete,
Dispose
}
9 changes: 9 additions & 0 deletions src/L1.Avalonia.Gif/Decoding/BlockTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace L1.Avalonia.Gif.Decoding;

internal enum BlockTypes
{
EMPTY = 0,
EXTENSION = 0x21,
IMAGE_DESCRIPTOR = 0x2C,
TRAILER = 0x3B
}
7 changes: 7 additions & 0 deletions src/L1.Avalonia.Gif/Decoding/ExtensionType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace L1.Avalonia.Gif.Decoding;

internal enum ExtensionType
{
GRAPHICS_CONTROL = 0xF9,
APPLICATION = 0xFF
}
9 changes: 9 additions & 0 deletions src/L1.Avalonia.Gif/Decoding/FrameDisposal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace L1.Avalonia.Gif.Decoding;

public enum FrameDisposal
{
Unknown = 0,
Leave = 1,
Background = 2,
Restore = 3
}
31 changes: 31 additions & 0 deletions src/L1.Avalonia.Gif/Decoding/GifColor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Runtime.InteropServices;

namespace L1.Avalonia.Gif.Decoding;

[StructLayout(LayoutKind.Explicit)]
public readonly struct GifColor
{
[FieldOffset(3)] public readonly byte A;

[FieldOffset(2)] public readonly byte R;

[FieldOffset(1)] public readonly byte G;

[FieldOffset(0)] public readonly byte B;

/// <summary>
/// A struct that represents a ARGB color and is aligned as
/// a BGRA bytefield in memory.
/// </summary>
/// <param name="r">Red</param>
/// <param name="g">Green</param>
/// <param name="b">Blue</param>
/// <param name="a">Alpha</param>
public GifColor(byte r, byte g, byte b, byte a = byte.MaxValue)
{
A = a;
R = r;
G = g;
B = b;
}
}
Loading

0 comments on commit 57be648

Please sign in to comment.