Skip to content
Merged

3.0.3 #147

Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ This project exists to serve the users who were left behind by the march of tech
- Portable (Single executable file)
- Right-to-left language support and bidirectional text
- Use of S.O.L.I.D. principles in object-oriented programming (limited due to the legacy .NET 4.0 framework)
- Use of Windows native methods for memory management
- Use of Windows API methods for memory management
- Windows retro-compatibility (Windows XP, Server 2003, and later)

### 💭 Where does the app save the settings?
Expand Down Expand Up @@ -261,12 +261,12 @@ When new versions require translation updates, we may use AI tools to provide a
| Language | Contributor(s) | Language | Contributor(s) |
|:---|:---|:---|:---|
| 🇦🇱 Albanian | [Omer Rustemi](https://github.com/omerrustemicode) | 🇯🇵 Japanese | [dai](https://github.com/dai) |
| 🇸🇦 Arabic | [Abdulmajeed Al-Rajhi](https://github.com/Abdulmajeed-Alrajhi) | 🇰🇷 Korean | [VenusGirl](https://github.com/VenusGirl) |
| 🇸🇦 Arabic | [Abderraouf FELLAHI](https://github.com/flh-raouf), [Abdulmajeed Al-Rajhi](https://github.com/Abdulmajeed-Alrajhi) | 🇰🇷 Korean | [VenusGirl](https://github.com/VenusGirl) |
| 🇧🇬 Bulgarian | [Konstantin](https://github.com/constantinejc) | 🇲🇰 Macedonian | [Dimitrij Gjorgji](https://github.com/Cathadox) |
| 🇨🇳 Chinese (Simplified) | [KaiHuaDou](https://github.com/KaiHuaDou), [Kun Zhao](https://github.com/kzhdev), [Rayden](https://github.com/raydenake22) | 🇳🇴 Norwegian | [Dan](https://github.com/danorse) |
| 🇨🇳 Chinese (Traditional) | [Rayden](https://github.com/raydenake22), [rtyrtyrtyqw](https://github.com/rtyrtyrtyqw) | 🇮🇷 Persian | [Kavian](https://github.com/KavianK) |
| 🇳🇱 Dutch | [Jesse](https://github.com/dragonhuntermc), [hax4dazy](https://github.com/hax4dazy) | 🇵🇱 Polish | [Patryk](https://github.com/Fresta56) |
| 🇫🇷 French | [William VINCENT](https://github.com/wixaw) | 🇧🇷 Portuguese | [Igor Mundstein](https://github.com/IgorMundstein) |
| 🇫🇷 French | [William VINCENT](https://github.com/wixaw) | 🇵🇹 Portuguese (PT) | AI |
| 🇩🇪 German | [Calvin](https://github.com/Slluxx), [Niklas Englmeier](https://github.com/iamniklas), [Steve](https://github.com/uDEV2019) | 🇷🇺 Russian | [Ruslan](https://github.com/ruslooob) |
| 🇬🇷 Greek | [Theodoros Katsageorgis](https://github.com/tkatsageorgis) | 🇷🇸 Serbian | [Dragoš Milošević](https://github.com/DragorMilos) |
| 🇮🇱 Hebrew | [Eliezer Bloy](https://github.com/eliezerbloy) | 🇸🇮 Slovenian | [Jadran Rudec](https://github.com/JadranR) |
Expand Down
354 changes: 114 additions & 240 deletions src/App.xaml

Large diffs are not rendered by default.

450 changes: 263 additions & 187 deletions src/App.xaml.cs

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions src/Converters/PercentageToWidthConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace WinMemoryCleaner
{
/// <summary>
/// Percentage To Width Converter
/// Converts a percentage value (0-100) and container width to the actual pixel width
/// </summary>
/// <seealso cref="IMultiValueConverter" />
public class PercentageToWidthConverter : IMultiValueConverter
{
/// <summary>
/// Converts a percentage and container width to pixel width.
/// </summary>
/// <param name="values">The array of values: [0] = container width, [1] = percentage (0-100)</param>
/// <param name="targetType">The type of the binding target property.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>The calculated width in pixels</returns>
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
try
{
if (values == null || values.Length < 2)
return 0.0;

if (values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue)
return 0.0;

var containerWidth = System.Convert.ToDouble(values[0], culture);
var percentage = System.Convert.ToDouble(values[1], culture);

if (containerWidth <= 0 || percentage < 0)
return 0.0;

// Clamp percentage to 0-100
if (percentage > 100)
percentage = 100;

return containerWidth * (percentage / 100.0);
}
catch
{
return 0.0;
}
}

/// <summary>
/// Converts a width back to percentage (not supported).
/// </summary>
/// <param name="value">The value that the binding target produces.</param>
/// <param name="targetTypes">The array of types to convert to.</param>
/// <param name="parameter">The converter parameter to use.</param>
/// <param name="culture">The culture to use in the converter.</param>
/// <returns>Not supported</returns>
/// <exception cref="NotSupportedException"></exception>
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
3 changes: 2 additions & 1 deletion src/Core/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public static class Test
public static class CommandLineArgument
{
public const string Install = "Install";
public const string Package = "Package";
public const string Service = "Service";
public const string Uninstall = "Uninstall";
}
Expand Down Expand Up @@ -145,6 +144,8 @@ public static class Locale
public static class Name
{
public const string English = "en";
public const string PortugueseBrazil = "pt-BR";
public const string PortuguesePortugal = "pt-PT";
public const string SimplifiedChinese = "zh-Hans";
public const string TraditionalChinese = "zh-Hant";
}
Expand Down
177 changes: 149 additions & 28 deletions src/Core/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Web.Script.Serialization;

namespace WinMemoryCleaner
Expand All @@ -13,53 +14,133 @@ namespace WinMemoryCleaner
public static class Helper
{
/// <summary>
/// Determines if the current Windows version supports updates via GitHub TLS/SNI.
/// Returns false for legacy Windows versions (XP/2003) that cannot reach GitHub.
/// Appends indentation to the StringBuilder based on the current nesting level.
/// </summary>
/// <returns>True if updates are supported; otherwise, false.</returns>
public static bool IsAutoUpdateSupported
/// <param name="sb">The StringBuilder to append to.</param>
/// <param name="level">The current indentation level.</param>
/// <param name="indent">The string to use for each indentation level.</param>
private static void AppendIndent(StringBuilder sb, int level, string indent)
{
get
{
try
{
var os = Environment.OSVersion;

if (os.Version != null && os.Version.Major < 6)
return false; // Windows XP/2003 and earlier
}
catch
{
}
for (var i = 0; i < level; i++)
sb.Append(indent);
}

return true;
/// <summary>
/// Creates a directory exists. Ignores failures.
/// </summary>
public static void CreateDirectory(string path)
{
try
{
if (!string.IsNullOrEmpty(path) && !Directory.Exists(path))
Directory.CreateDirectory(path);
}
catch
{
}
}

/// <summary>
/// Converts the specified JSON string to an object of type T
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="input">The input.</param>
/// <param name="obj">The object.</param>
/// <returns></returns>
public static T Deserialize<T>(string input)
public static T Deserialize<T>(string obj)
{
return new JavaScriptSerializer().Deserialize<T>(input);
return new JavaScriptSerializer().Deserialize<T>(obj);
}

/// <summary>
/// Creates a directory exists. Ignores failures.
/// Formats a minified JSON string into a pretty-printed format with proper indentation and line breaks.
/// </summary>
public static void CreateDirectory(string path)
/// <param name="json">The minified JSON string to format.</param>
/// <returns>A formatted JSON string with indentation and line breaks.</returns>
private static string FormatJson(string json)
{
try
{
if (!string.IsNullOrEmpty(path) && !Directory.Exists(path))
Directory.CreateDirectory(path);
}
catch
if (string.IsNullOrEmpty(json))
return string.Empty;

var sb = new StringBuilder(json.Length * 2);
var indent = " ";
var level = 0;
var inString = false;
var escapeNext = false;

for (var i = 0; i < json.Length; i++)
{
var c = json[i];

if (escapeNext)
{
sb.Append(c);
escapeNext = false;
continue;
}

if (c == '\\')
{
sb.Append(c);
escapeNext = true;
continue;
}

if (c == '"')
{
sb.Append(c);
inString = !inString;
continue;
}

if (inString)
{
sb.Append(c);
continue;
}

switch (c)
{
case '{':
case '[':
sb.Append(c);
sb.Append(Environment.NewLine);
level++;
AppendIndent(sb, level, indent);
break;

case '}':
case ']':
sb.Append(Environment.NewLine);
level--;
AppendIndent(sb, level, indent);
sb.Append(c);
break;

case ',':
sb.Append(c);
sb.Append(Environment.NewLine);
AppendIndent(sb, level, indent);
break;

case ':':
sb.Append(c);
sb.Append(' ');
break;

case ' ':
case '\t':
case '\r':
case '\n':
// Skip whitespace outside strings
break;

default:
sb.Append(c);
break;
}
}

return sb.ToString();
}

/// <summary>
Expand Down Expand Up @@ -103,6 +184,30 @@ public static string GetExecutablePath()
}
}

/// <summary>
/// Determines if the current Windows version supports updates via GitHub TLS/SNI.
/// Returns false for legacy Windows versions (XP/2003) that cannot reach GitHub.
/// </summary>
/// <returns>True if updates are supported; otherwise, false.</returns>
public static bool IsAutoUpdateSupported
{
get
{
try
{
var os = Environment.OSVersion;

if (os.Version != null && os.Version.Major < 6)
return false; // Windows XP/2003 and earlier
}
catch
{
}

return true;
}
}

/// <summary>
/// Gets the string name of a property or field.
/// </summary>
Expand Down Expand Up @@ -136,6 +241,22 @@ public static T ReadEmbeddedResource<T>(string name)
}
}

/// <summary>
/// Converts the specified object to a JSON string
/// </summary>
/// <param name="obj">The object to serialize.</param>
/// <param name="minified">If true, produces compact JSON without formatting; otherwise, formats with indentation for readability. Default is false.</param>
/// <returns>A JSON string representation of the object.</returns>
public static string Serialize(IJsonSerializable obj, bool minified = false)
{
if (obj == null)
throw new ArgumentNullException("obj");

var json = new JavaScriptSerializer().Serialize(obj.ToJson());

return minified ? json : FormatJson(json);
}

/// <summary>
/// Converts to hexcode.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public static void Log(Log log)
if (log == null)
throw new ArgumentNullException("log");

Log(log.Level, log.ToString());
Log(log.Level, Helper.Serialize(log));
}
catch (Exception e)
{
Expand Down
28 changes: 28 additions & 0 deletions src/Core/Migrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public static void Run()
MigrateSettingsFromCurrentUserToLocalMachine();
RemoveStartupRegistry();
}
// 3.0+
if (App.Version >= new Version(3, 0))
{
RemoveRegistryPath();
}
}

#region Classes
Expand Down Expand Up @@ -152,6 +157,29 @@ private static void MigrateSettingsFromCurrentUserToLocalMachine()
}
}

/// <summary>
/// Removes the registry path.
/// </summary>
private static void RemoveRegistryPath()
{
try
{
using (var key = Registry.LocalMachine.OpenSubKey(Constants.App.Registry.Key.Settings, true))
{
if (key != null && key.GetValue(V30.Registry.Path, null) != null)
{
key.DeleteValue(V30.Registry.Path, false);

Logger.Information("Migration version update: Removed path registry entry.");
}
}
}
catch (Exception e)
{
Logger.Error(e);
}
}

/// <summary>
/// Removes the startup registry to avoid UAC warnings. Use a scheduled task instead to run at startup.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Core/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace WinMemoryCleaner
{
/// <summary>
/// Windows Native Methods
/// Windows API
/// </summary>
internal static class NativeMethods
{
Expand Down
Loading