Skip to content

Commit

Permalink
Avalonia (MacOS, Linux) port (#85)
Browse files Browse the repository at this point in the history
* First alpha commit

* MacOS native AppTitle

* Fallback background control (Potato quality)

* Titlebar input fix with ImageEx

* Disable screensaver page when Potato quality

* Fix background overlay brush not working

* Add translation string Distance

* Depth background creation using ml

- Replaced StorageFile in screensaver and depth viewmodels.
- Common service impl moved to shared project.
- Some refactoring.

* SystemInfoProvider handles SystemUtil fns

* File launcher service

* String resource loader abstraction

- Some refactoring.

* Refactored ShaderUtil and disabled Clouds shader in avalonia..

* Refactored UWP to match Avalonia

* Refactored weather unit listbox style..

* Removed unused converter

* App update checker

* Update notification

* Localized update available

* Fixed ml model not being loaded in linux

* Startup tasks and unhandled exception logging

* Updater store last checked status

* Indicate Avalonia is running under quality perf setting

* Updated accessibility icon

* Close depth dialog if no image selected and patches

* NLog custom directory factory

* Moved common service impl to shared project

* Onnx logging and error presentation

* Language selector

* Refactored uwp file structure to match avalonia

* Location selector refactor

* Style fix IsExtendedIntoWindowDecorations

* Searchbox fix

* Updated translations

* MacOS native menu impl

* MacOS help nativemenu

* Update checking

* Fixed duplicate update event

* Welcome message

* Turned off snapshot antialias for perf

* Delete duplicate gitignore

* Updated Avalonia package version and removed unused buildprop

* Updated avalonia dependencies

* Fixed shadermodel copy constructor not updating shaderuri

* ShaderModel default uniforms are made in base class

* Refactored computesharp runners to use shaderuniform dictionary

* Restore IsRandomN14 back to private

* Fixed cloud day/night not working (uwp)

* Adjust shadow and margins to match uwp

* Fixed top-margin when content not extended to titlebar

* Adjust header and clock shadow

* Platform specific update manifest

* Linux build script

* Linux build enhancements

- vender string added.
- tar.gz package added.
- Switched from gz to xz compression (better.)
- Switched to 4 digit version string (same as app.)

* Removed duplicate FluentTheme

* Changed avalonia title Beta to Preview

* Update .fpm

* Updated translations

* Update hero.mp4

* Shader cross-fade (Avalonia) and control refactor

* New customise ui (avalonia)

* Autosize customise menu (Avalonia)

* Weather customise and selection moved to single flyout (uwp)..

.. and refactoring

* Adjusted Eye lottie animation color
  • Loading branch information
rocksdanister authored Oct 26, 2024
1 parent 030e606 commit 9575d0d
Show file tree
Hide file tree
Showing 522 changed files with 37,492 additions and 5,304 deletions.
13 changes: 13 additions & 0 deletions build/linux/.fpm
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-s dir -C package
--name livelyweather
--description "Weather app powered by gpu shader animations."
--url "https://www.rocksdanister.com/weather"
--maintainer "Rocksdanister <awoo.git@gmail.com>"
--vendor "Rocksdanister"
--license "MIT"
--version 2.0.0.0
--architecture amd64
--deb-no-default-config-files
--deb-compression xz
--rpm-compression xz
.
21 changes: 21 additions & 0 deletions build/linux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Using [fpm](https://github.com/jordansissel/fpm) to create installer packages (deb, rpm.)

Make the build script executable `chmod +x build_packages.sh` and run `./build_packages.sh`

The script will create a `package` directory using the application files directory `build` and `resources` as follows:
```
package/
├── usr/
│ ├── bin/
│ │ └── livelyweather (symlink to ../lib/livelyweather/Drizzle.UI.Avalonia.Desktop)
│ └── lib/
│ └── livelyweather/
│ ├── Drizzle.UI.Avalonia.Desktop
│ ├── (other application files)
├── usr/share/
│ ├── applications/
│ │ └── com.rocksdanister.LivelyWeather.desktop
│ └── icons/hicolor/256x256/apps/
│ └── com.rocksdanister.LivelyWeather.png
```
Then create packages using the .fpm configuration file.
28 changes: 28 additions & 0 deletions build/linux/build_packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

# Clean previous package directory
rm -rf package/
mkdir -p package/usr/bin
mkdir -p package/usr/lib/livelyweather
mkdir -p package/usr/share/applications
mkdir -p package/usr/share/icons/hicolor/256x256/apps

# Copy application files
cp -r build/* package/usr/lib/livelyweather/

# Create symlink
ln -s ../lib/livelyweather/Drizzle.UI.Avalonia.Desktop package/usr/bin/livelyweather

# Copy desktop file and icon
cp resources/com.rocksdanister.LivelyWeather.desktop package/usr/share/applications/
cp resources/com.rocksdanister.LivelyWeather.png package/usr/share/icons/hicolor/256x256/apps/

# Ensure executables have correct permissions
chmod +x package/usr/lib/livelyweather/Drizzle.UI.Avalonia.Desktop

# Build package
fpm -t deb
fpm -t rpm
# tar -> tar.gz
fpm -t tar
gzip livelyweather.tar
9 changes: 9 additions & 0 deletions build/linux/resources/com.rocksdanister.LivelyWeather.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Desktop Entry]
Name=Lively Weather
Comment=Weather app powered by gpu shader animations.
Exec=livelyweather
Icon=com.rocksdanister.LivelyWeather
Terminal=false
Type=Application
Categories=Utility;Science;Geography;X-Weather;
StartupNotify=true
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified resources/hero.mp4
Binary file not shown.
8 changes: 7 additions & 1 deletion src/Drizzle.Common/Constants/UserSettingsConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public static class UserSettingsConstants

public const string SelectedWeatherProvider = "SelectedWeatherProvider";

public const string SelectedLanguageCode = "SelectedLanguageCode";

public const string UseSystemDefaultLanguage = "UseSystemDefaultLanguage";

// Custom user selected units.

public const string SelectedTemperatureUnit = "SelectedTemperatureUnit";
Expand Down Expand Up @@ -80,6 +84,8 @@ public static class UserSettingsConstants
{ SelectedVisibilityUnit, VisibilityUnits.km },
{ SelectedPressureUnit, PressureUnits.hPa_mb },
{ SelectedMainGraphType, GraphType.temperature },
{ SelectedPrecipitationUnit, PrecipitationUnits.mm }
{ SelectedPrecipitationUnit, PrecipitationUnits.mm },
{ SelectedLanguageCode, string.Empty }, //en-US, zh-CN
{ UseSystemDefaultLanguage, true } // Ignores "SelectedLanguageCode"
};
}
24 changes: 12 additions & 12 deletions src/Drizzle.Common/Extensions/TaskExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ namespace Drizzle.Common.Extensions;
//ref: https://www.youtube.com/watch?v=O1Tx-k4Vao0
public static class TaskExtensions
{
//public async static void Await<T>(this Task<T> task, Action<T> completedCallBack, Action<Exception> errorCallBack)
//{
// try
// {
// T result = await task;
// completedCallBack?.Invoke(result);
// }
// catch (Exception ex)
// {
// errorCallBack?.Invoke(ex);
// }
//}
public async static void Await<T>(this Task<T> task, Action<T> completedCallBack, Action<Exception> errorCallBack)
{
try
{
T result = await task;
completedCallBack?.Invoke(result);
}
catch (Exception ex)
{
errorCallBack?.Invoke(ex);
}
}

public async static void Await(this Task task, Action completedCallBack, Action<Exception> errorCallBack)
{
Expand Down
14 changes: 14 additions & 0 deletions src/Drizzle.Common/Helpers/BuildInfoUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Drizzle.Common.Helpers;

public static class BuildInfoUtil
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S3400:Methods should not return constants", Justification = "Value changes based on build setting.")]
public static bool IsDebugBuild()
{
#if DEBUG
return true;
#else
return false;
#endif
}
}
44 changes: 0 additions & 44 deletions src/Drizzle.Common/Helpers/IDownloadUtil.cs

This file was deleted.

12 changes: 10 additions & 2 deletions src/Drizzle.Common/Helpers/JsonUtil.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Drizzle.Common.Helpers
{
Expand All @@ -21,6 +19,16 @@ public static T Load<T>(string filePath)
return tmp != null ? tmp : throw new InvalidOperationException("json null/corrupt");
}

public static T Load<T>(Stream stream)
{
using var reader = new StreamReader(stream);
using var jsonReader = new JsonTextReader(reader);
var serializer = new JsonSerializer();
var tmp = serializer.Deserialize<T>(jsonReader);

return tmp != null ? tmp : throw new InvalidOperationException("json null/corrupt");
}

public static void Save<T>(string filePath, T data)
{
JsonSerializer serializer = new JsonSerializer
Expand Down
39 changes: 39 additions & 0 deletions src/Drizzle.Common/Helpers/MathUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;

namespace Drizzle.Common.Helpers
{
public static class MathUtil
{
public static float Lerp(float start, float target, float by) => start * (1 - by) + target * by;

public static double RangePercentage(double number, double rangeMin, double rangeMax)
{
var percentage = ((number - rangeMin) * 100) / (rangeMax - rangeMin);
if (percentage > 100)
percentage = 100;
else if (percentage < 0)
percentage = 0;

return percentage;
}

public static double DegreeToRadians(double degree) => degree * Math.PI / 180;

public static float NormalizeAngle(float degree) => degree < 0 ? 360 + degree : degree;

public static float ConvertToRange(float oldStart, float oldEnd, float newStart, float newEnd, float value)
{
var scale = (newEnd - newStart) / (oldEnd - oldStart);
return newStart + ((value - oldStart) * scale);
}

// Credit: https://gist.github.com/adrianstevens/8163205
public static string DegreeToCardinalString(float degree)
{
var cardinals = new string[] { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" };
var value = NormalizeAngle(degree);
var index = (int)Math.Round(value % 360 / 45);
return cardinals[index];
}
}
}
22 changes: 15 additions & 7 deletions src/Drizzle.Common/Services/IAppUpdaterService.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
using System;
using System.Collections.Generic;
using System.Text;
using Drizzle.Models.Enums;
using System;
using System.Threading.Tasks;

namespace Drizzle.Common.Services
namespace Drizzle.Common.Services;

public interface IAppUpdaterService
{
public interface IAppUpdaterService
{
}
/// <summary>
/// Utc time since last update checked succesfully.
/// </summary>
DateTime LastCheckedTime { get; }
AppUpdateStatus LastCheckedStatus { get; }
Task<AppUpdateStatus> CheckUpdateAsync();
void Start();

event EventHandler<AppUpdateStatus> UpdateChecked;
}
19 changes: 19 additions & 0 deletions src/Drizzle.Common/Services/IDownloadService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Drizzle.Common.Services;

public interface IDownloadService
{
/// <summary>
/// Downloads a file from the specified URL to the given file path.
/// </summary>
/// <param name="url">The file download uri.</param>
/// <param name="filePath">The destination file path.</param>
/// <param name="progress">Reports progress.
/// The first parameter is the downloaded size in MB, and the second is the total size in MB.</param>
/// <param name="cancellationToken">A token to cancel the download operation.</param>
/// <returns>A Task that completes when the download is finished, or throws an exception on failure.</returns>
Task DownloadFile(Uri url, string filePath, IProgress<(double downloaded, double total)> progress, CancellationToken cancellationToken);
}
15 changes: 15 additions & 0 deletions src/Drizzle.Common/Services/IFileService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.IO;
using System.Runtime.InteropServices.ComTypes;
using System.Threading.Tasks;

namespace Drizzle.Common.Services;

public interface IFileService
{
string LocalFolderPath { get; }
string TempFolderPath { get; }
string LogFolderPath { get; }
string CachePath { get; }
Task<(Stream stream, string fileName)> OpenFileAsync();
Task<(Stream stream, string fileName)> OpenImageFileAsync();
}
12 changes: 12 additions & 0 deletions src/Drizzle.Common/Services/ILauncherService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Threading.Tasks;

namespace Drizzle.Common.Services
{
public interface ILauncherService
{
public Task<bool> OpenBrowserAsync(Uri uri);
public Task<bool> OpenBrowserAsync(string url);
public Task<bool> OpenFileAsync(string filePath);
}
}
8 changes: 8 additions & 0 deletions src/Drizzle.Common/Services/IResourceService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Drizzle.Common.Services;

public interface IResourceService
{
string GetString(string resource);
void SetCulture(string name);
void SetSystemDefaultCulture();
}
16 changes: 14 additions & 2 deletions src/Drizzle.Common/Services/ISystemInfoProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,26 @@ public interface ISystemInfoProvider
/// <summary>
/// Returns true is the current device is a Desktop.
/// </summary>
bool IsDesktop();
bool IsDesktop { get; }

/// <summary>
/// Returns true is the current
/// device is Xbox or other device
/// optimized for a 10-foot viewing
/// distance.
/// </summary>
bool IsTenFoot();
bool IsTenFoot { get; }

bool IsHardwareAccelerated { get; }

public bool IsFirstRun { get; }

public bool IsAppUpdated { get; }

public string AppName { get; }

public Version AppVersion { get; }

public string GpuName { get; }
}
}
10 changes: 10 additions & 0 deletions src/Drizzle.Common/Services/IUserSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ public interface IUserSettings
/// <returns>The desired value or returns the default.</returns>
T? GetAndDeserialize<T>(string settingKey);

/// <summary>
/// Retrieves the value for the desired settings key
/// and performs json deserialization on the stored value.
/// </summary>
/// <typeparam name="T">Type of the value.</typeparam>
/// <param name="settingKey">The settings key, generally found in <see cref="UserSettingsConstants"/>.</param>
/// <param name="defaultOverride">The default override to use if the setting has no value.</param>
/// <returns>The desired value or returns the default.</returns>
T? GetAndDeserialize<T>(string settingKey, T defaultOverride);

/// <summary>
/// Saves settings into persistent local storage
/// after serializing the object.
Expand Down
7 changes: 7 additions & 0 deletions src/Drizzle.Common/Services/IWindowService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Drizzle.Common.Services;

public interface IWindowService
{
void ShowAboutWindow();
void ShowHelpWindow();
}
Loading

0 comments on commit 9575d0d

Please sign in to comment.