Compare commits

..

29 Commits

Author SHA1 Message Date
266c6ee507 finalize the screenshots 2026-02-15 17:19:38 +00:00
2954cb8678 Incremented to version v0.1.17
All checks were successful
Release / release (push) Successful in 1m16s
2026-02-15 17:07:50 +00:00
4b75381cb9 make dropdown menus uniform between linux and windows 2026-02-15 17:07:11 +00:00
90ce361ea5 windows screenshot for readme 2026-02-15 16:47:53 +00:00
508a1c48e3 Incremented to version v0.1.16
All checks were successful
Release / release (push) Successful in 1m21s
2026-02-15 15:33:45 +00:00
f98471e4f4 fix broken word wrapping 2026-02-15 15:32:44 +00:00
209ede7a1a Incremented to version v0.1.15
All checks were successful
Release / release (push) Successful in 1m18s
2026-02-15 14:22:21 +00:00
245a56d270 one final. last. dead end. attempt 2026-02-15 14:22:06 +00:00
89f4b0aeba Incremented to version v0.1.14
All checks were successful
Release / release (push) Successful in 1m15s
2026-02-15 14:15:47 +00:00
962e3632bb one final. last. dead end. attempt 2026-02-15 14:15:23 +00:00
98264b2a3c Incremented to version v0.1.13
All checks were successful
Release / release (push) Successful in 1m17s
2026-02-15 14:09:08 +00:00
b832ba5f8f annotation message. not commit message 2026-02-15 14:08:31 +00:00
43281e047d Incremented to version v0.1.12
All checks were successful
Release / release (push) Successful in 1m14s
2026-02-15 13:59:41 +00:00
21c3a7c7c0 debugging the runner again 2026-02-15 13:58:50 +00:00
b0e2eda4bb Incremented to version v0.1.11
All checks were successful
Release / release (push) Successful in 1m19s
2026-02-15 13:54:17 +00:00
d652ec7c04 last ditch effort to fix the yaml 2026-02-15 13:53:36 +00:00
63bb7f7316 Incremented to version v0.1.10
All checks were successful
Release / release (push) Successful in 1m14s
2026-02-15 13:47:47 +00:00
12c615b62c fix gitea workflow bug 2026-02-15 13:46:20 +00:00
99c20fa8de Incremented to version v0.1.9
All checks were successful
Release / release (push) Successful in 1m18s
2026-02-15 13:37:03 +00:00
e519d87193 make sure release message is included in release notes 2026-02-15 13:36:22 +00:00
7601f829bc Incremented to version v0.1.8
All checks were successful
Release / release (push) Successful in 1m13s
2026-02-15 13:25:06 +00:00
84448f7d46 include monospace font fallback for linux 2026-02-15 13:24:29 +00:00
7f056036d0 Incremented to version v0.1.7
All checks were successful
Release / release (push) Successful in 1m16s
2026-02-15 13:00:24 +00:00
c8e70f41bc add command-line filename argument, so open-with works 2026-02-15 12:59:43 +00:00
a52468f03b Incremented to version v0.1.6
All checks were successful
Release / release (push) Successful in 1m18s
2026-02-15 12:15:40 +00:00
d0a66ae6b4 Incremented to version --help 2026-02-15 12:13:54 +00:00
c1e2993e70 fix selection focus bug 2026-02-15 12:11:50 +00:00
95f07d93a9 add release script 2026-02-14 22:39:12 +00:00
b82312d26f add dynamic versioning to build/release scripts;add fixed versioning to csproj file
All checks were successful
Release / release (push) Successful in 1m15s
2026-02-14 22:24:29 +00:00
12 changed files with 256 additions and 28 deletions

View File

@ -15,6 +15,9 @@ jobs:
run: echo "${LOCIP} gitea.comnenos" >> /etc/hosts
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Install Build Dependencies
run: |
@ -59,16 +62,17 @@ jobs:
- name: Create Release Archive
run: |
VERSION=${GITHUB_REF#refs/tags/}
VERSION_NUM=${VERSION#v} # Remove 'v' prefix (e.g., v0.1.4 -> 0.1.4)
mkdir -p release
# Copy AppImage (if it exists)
if [ -f publish/appimage/NotePad-0.1.0-x86_64.AppImage ]; then
cp publish/appimage/NotePad-0.1.0-x86_64.AppImage \
# Copy AppImage (if it exists) - use version from build
if [ -f publish/appimage/NotePad-${VERSION_NUM}-x86_64.AppImage ]; then
cp publish/appimage/NotePad-${VERSION_NUM}-x86_64.AppImage \
release/NotePad-${VERSION}-x86_64.AppImage
fi
# Copy Linux Tarball
cp publish/tarball/notepad-0.1.0-linux-x64.tar.gz \
cp publish/tarball/notepad-${VERSION_NUM}-linux-x64.tar.gz \
release/notepad-${VERSION}-linux-x64.tar.gz
# Create Windows zip
@ -91,6 +95,21 @@ jobs:
run: |
VERSION=${GITHUB_REF#refs/tags/}
# Explicitly fetch the tag with annotation
echo "Fetching tag ${VERSION} with annotation..."
git fetch origin tag ${VERSION} --force
# Get the tag annotation message (not the commit message)
echo "Extracting tag annotation..."
TAG_MESSAGE=$(git cat-file tag ${VERSION} | sed '1,/^$/d')
echo "Tag annotation: ${TAG_MESSAGE}"
# Create release body
RELEASE_BODY=$(printf "%s\n\n## Downloads\n\n### Linux\n- **AppImage**: Portable, single-file executable (no installation needed)\n- **Tarball**: Extract and run \`sudo ./install.sh\` to install\n\n### Windows\n- **Zip**: Extract and run \`NotePad.exe\`" "$TAG_MESSAGE")
# Escape the full body for JSON
RELEASE_BODY_JSON=$(printf '%s' "$RELEASE_BODY" | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
# Create release
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases" \
-H "Authorization: token ${GITEA_TOKEN}" \
@ -98,7 +117,7 @@ jobs:
-d "{
\"tag_name\": \"${VERSION}\",
\"name\": \"NotePad ${VERSION}\",
\"body\": \"Release ${VERSION}\n\n## Downloads\n\n### Linux\n- **AppImage**: Portable, single-file executable (no installation needed)\n- **Tarball**: Extract and run \`sudo ./install.sh\` to install\n\n### Windows\n- **Zip**: Extract and run \`NotePad.exe\`\"
\"body\": \"${RELEASE_BODY_JSON}\"
}" > release_response.json
RELEASE_ID=$(cat release_response.json | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)

View File

@ -15,7 +15,12 @@ public partial class App : Application
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
string? fileToOpen = null;
if (desktop.Args?.Length > 0)
{
fileToOpen = desktop.Args[0];
}
desktop.MainWindow = new MainWindow(fileToOpen);
}
base.OnFrameworkInitializationCompleted();

View File

@ -4,6 +4,27 @@
Title="Untitled - Notepad"
Width="600" Height="400">
<Window.Styles>
<Style Selector="Menu">
<Setter Property="Background" Value="#D3D3D3"/>
</Style>
<Style Selector="MenuItem">
<Setter Property="Background" Value="#D3D3D3"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
<Style Selector="MenuItem:pointerover /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="#A9A9A9"/>
</Style>
<Style Selector="MenuItem:open /template/ Popup#PART_Popup > Border">
<Setter Property="Background" Value="#D3D3D3"/>
<Setter Property="BorderBrush" Value="#A9A9A9"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
<Style Selector="Separator">
<Setter Property="Background" Value="#A9A9A9"/>
</Style>
</Window.Styles>
<DockPanel>
<!-- Menu Bar -->
<Menu DockPanel.Dock="Top">
@ -15,7 +36,7 @@
<Separator/>
<MenuItem Header="E_xit" Click="OnExitClick"/>
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem Header="_Edit" x:Name="EditMenuItem">
<MenuItem Header="_Undo" Click="OnUndoClick" InputGesture="Ctrl+Z"/>
<Separator/>
<MenuItem Header="Cu_t" Click="OnCutClick" InputGesture="Ctrl+X"/>
@ -29,7 +50,7 @@
<MenuItem Header="F_ormat">
<MenuItem Header="_Word Wrap" x:Name="WordWrapMenuItem" Click="OnWordWrapToggle">
<MenuItem.Icon>
<CheckBox x:Name="WordWrapCheckBox" IsChecked="True" IsHitTestVisible="False"/>
<CheckBox x:Name="WordWrapCheckBox" IsChecked="False" IsHitTestVisible="False"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
@ -43,7 +64,7 @@
<TextBox x:Name="EditorTextBox"
AcceptsReturn="True"
AcceptsTab="True"
TextWrapping="Wrap"
TextWrapping="NoWrap"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
ScrollViewer.VerticalScrollBarVisibility="Auto"
@ -52,8 +73,9 @@
Background="White"
Foreground="Black"
CaretBrush="Black"
FontFamily="Consolas,Courier New,monospace"
FontSize="12">
FontFamily="Courier New,Liberation Mono,Courier,monospace"
FontSize="13"
ClearSelectionOnLostFocus="False">
<TextBox.Styles>
<Style Selector="TextBox">
<Setter Property="Background" Value="White"/>

View File

@ -17,7 +17,11 @@ namespace NotePad
private bool _isModified;
private string? _originalText;
public MainWindow()
public MainWindow() : this(null)
{
}
public MainWindow(string? fileToOpen)
{
InitializeComponent();
UpdateTitle();
@ -26,6 +30,30 @@ namespace NotePad
textBox.TextChanged += OnTextChanged;
Closing += OnWindowClosing;
if (!string.IsNullOrEmpty(fileToOpen) && File.Exists(fileToOpen))
{
_ = LoadFileAsync(fileToOpen);
}
}
private async Task LoadFileAsync(string filePath)
{
try
{
var text = await File.ReadAllTextAsync(filePath);
_currentFilePath = filePath;
_currentFileName = Path.GetFileName(filePath);
this.FindControl<TextBox>("EditorTextBox")!.Text = text;
_originalText = text;
_isModified = false;
UpdateTitle();
}
catch (Exception)
{
// Silently ignore file loading errors on startup
}
}
private void UpdateTitle()
@ -266,7 +294,17 @@ namespace NotePad
var textBox = this.FindControl<TextBox>("EditorTextBox")!;
checkBox.IsChecked = !checkBox.IsChecked;
textBox.TextWrapping = checkBox.IsChecked == true ? TextWrapping.Wrap : TextWrapping.NoWrap;
if (checkBox.IsChecked == true)
{
textBox.TextWrapping = TextWrapping.Wrap;
ScrollViewer.SetHorizontalScrollBarVisibility(textBox, Avalonia.Controls.Primitives.ScrollBarVisibility.Disabled);
}
else
{
textBox.TextWrapping = TextWrapping.NoWrap;
ScrollViewer.SetHorizontalScrollBarVisibility(textBox, Avalonia.Controls.Primitives.ScrollBarVisibility.Auto);
}
}
// Edit Menu

View File

@ -1,4 +1,5 @@
<Project Sdk="Microsoft.NET.Sdk">
<?xml version='1.0' encoding='utf-8'?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
@ -6,6 +7,7 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<ApplicationIcon>img\notepad-icon.ico</ApplicationIcon>
<Version>0.1.17</Version>
</PropertyGroup>
<ItemGroup>
@ -13,7 +15,7 @@
<PackageReference Include="Avalonia.Desktop" Version="11.3.12" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.12" />
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.3.12" />
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.12">
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>

View File

@ -5,7 +5,7 @@
set -e
APP_NAME="NotePad"
VERSION="0.1.0"
VERSION="${1:-0.1.0}" # Use first argument or default to 0.1.0
ARCH="x86_64"
# Directories

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -9,9 +9,30 @@ import sys
import os
import shutil
import tarfile
import xml.etree.ElementTree as ET
from pathlib import Path
def get_version():
"""Extract version from .csproj file"""
csproj_path = Path("NotePad.csproj")
if not csproj_path.exists():
print("⚠️ WARNING: NotePad.csproj not found. Using default version 0.1.0")
return "0.1.0"
try:
tree = ET.parse(csproj_path)
root = tree.getroot()
version_elem = root.find(".//Version")
if version_elem is not None and version_elem.text:
return version_elem.text
print("⚠️ WARNING: Version not found in .csproj. Using default version 0.1.0")
return "0.1.0"
except Exception as e:
print(f"⚠️ WARNING: Failed to parse .csproj: {e}. Using default version 0.1.0")
return "0.1.0"
def run_command(cmd, description):
"""Run a shell command and print status"""
print(f"\n{'=' * 60}")
@ -69,7 +90,7 @@ def build_windows_installer():
print(f"\n⚠️ WARNING: Failed to create installer: {e}")
def build_linux_tarball():
def build_linux_tarball(version):
"""Create tar.gz archive with install script"""
print(f"\n{'=' * 60}")
print("Creating Linux tar.gz archive")
@ -100,8 +121,13 @@ def build_linux_tarball():
shutil.copy(script_path, temp_dir / "notepad" / script)
os.chmod(temp_dir / "notepad" / script, 0o755)
# Copy img directory (contains icon)
img_dir = Path("img")
if img_dir.exists():
shutil.copytree(img_dir, temp_dir / "notepad" / "img")
# Create tar.gz
tarball_path = tarball_dir / "notepad-0.1.0-linux-x64.tar.gz"
tarball_path = tarball_dir / f"notepad-{version}-linux-x64.tar.gz"
with tarfile.open(tarball_path, "w:gz") as tar:
tar.add(temp_dir / "notepad", arcname="notepad")
@ -116,7 +142,7 @@ def build_linux_tarball():
print(f" sudo ./install.sh")
def build_linux_appimage():
def build_linux_appimage(version):
"""Build Linux AppImage"""
build_script = Path("build-appimage.sh")
if not build_script.exists():
@ -125,7 +151,7 @@ def build_linux_appimage():
try:
result = subprocess.run(
["bash", str(build_script)],
["bash", str(build_script), version],
capture_output=True,
text=True
)
@ -190,10 +216,11 @@ def publish_platform(platform, linux_package='both'):
# Build Linux packages
if platform == 'linux':
version = get_version()
if linux_package in ['appimage', 'both']:
build_linux_appimage()
build_linux_appimage(version)
if linux_package in ['tarball', 'both']:
build_linux_tarball()
build_linux_tarball(version)
def main():

View File

@ -2,7 +2,9 @@
A simple cross-platform text editor built with Avalonia UI and .NET 8.
![Screenshot](NotePad/img/notepad-screenshot.png)
| Windows | Linux |
|-----------------------------------------------------------------| ----- |
| ![Windows Screenshot](NotePad/img/notepad-screenshot-win11.png) | ![Linux Screenshot](NotePad/img/notepad-screenshot-linux.png) |
## Installation

113
make-release.py Executable file
View File

@ -0,0 +1,113 @@
#!/usr/bin/env python3
"""
Release script for NotePad
Automates version bumping, committing, tagging, and pushing
"""
import sys
import subprocess
import xml.etree.ElementTree as ET
from pathlib import Path
def run_command(cmd, description):
"""Run a command and handle errors"""
print(f"\n{description}...")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"❌ ERROR: {description} failed!")
print(f" {result.stderr}")
sys.exit(1)
if result.stdout.strip():
print(f" {result.stdout.strip()}")
return result
def update_version_in_csproj(version):
"""Update the version in NotePad.csproj"""
csproj_path = Path("NotePad/NotePad.csproj")
if not csproj_path.exists():
print(f"❌ ERROR: {csproj_path} not found!")
sys.exit(1)
print(f"\n→ Updating version to {version} in {csproj_path}...")
try:
tree = ET.parse(csproj_path)
root = tree.getroot()
version_elem = root.find(".//Version")
if version_elem is not None:
version_elem.text = version
else:
# Add Version element if it doesn't exist
property_group = root.find(".//PropertyGroup")
if property_group is not None:
version_elem = ET.SubElement(property_group, "Version")
version_elem.text = version
else:
print("❌ ERROR: Could not find PropertyGroup in .csproj")
sys.exit(1)
tree.write(csproj_path, encoding='utf-8', xml_declaration=True)
print(f" ✅ Version updated to {version}")
except Exception as e:
print(f"❌ ERROR: Failed to update .csproj: {e}")
sys.exit(1)
def main():
if len(sys.argv) < 2:
print("Usage: python3 make-release.py <version> [tag message]")
print("")
print("Examples:")
print(" python3 make-release.py v0.1.6")
print(" python3 make-release.py v0.1.6 'Added fireworks to launch animations'")
sys.exit(1)
version_tag = sys.argv[1]
# Remove 'v' prefix for .csproj version
version_num = version_tag.lstrip('v')
# Get tag message from remaining arguments
tag_message = ' '.join(sys.argv[2:]) if len(sys.argv) > 2 else f"Release {version_tag}"
print("=" * 60)
print(f"NotePad Release Script")
print("=" * 60)
print(f"Version: {version_tag}")
print(f"Tag message: {tag_message}")
print("=" * 60)
# Step 1: Update version in .csproj
update_version_in_csproj(version_num)
# Step 2: Commit the version update
commit_message = f"Incremented to version {version_tag}"
run_command(["git", "add", "NotePad/NotePad.csproj"], "Staging .csproj")
run_command(["git", "commit", "-m", commit_message], "Committing version update")
# Step 3: Push to origin master
run_command(["git", "push", "origin", "master"], "Pushing to origin master")
# Step 4: Create git tag
run_command(["git", "tag", "-a", version_tag, "-m", tag_message], f"Creating tag {version_tag}")
# Step 5: Push tag to origin
run_command(["git", "push", "origin", version_tag], f"Pushing tag {version_tag}")
print("\n" + "=" * 60)
print("✅ Release completed successfully!")
print("=" * 60)
print(f"\nThe CI/CD workflow should now build and publish {version_tag}")
print(f"Check your Gitea repository for the release.")
if __name__ == "__main__":
main()