Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 266c6ee507 | |||
| 2954cb8678 | |||
| 4b75381cb9 | |||
| 90ce361ea5 | |||
| 508a1c48e3 | |||
| f98471e4f4 | |||
| 209ede7a1a | |||
| 245a56d270 | |||
| 89f4b0aeba | |||
| 962e3632bb | |||
| 98264b2a3c | |||
| b832ba5f8f | |||
| 43281e047d | |||
| 21c3a7c7c0 | |||
| b0e2eda4bb | |||
| d652ec7c04 | |||
| 63bb7f7316 | |||
| 12c615b62c | |||
| 99c20fa8de | |||
| e519d87193 | |||
| 7601f829bc | |||
| 84448f7d46 | |||
| 7f056036d0 | |||
| c8e70f41bc | |||
| a52468f03b | |||
| d0a66ae6b4 | |||
| c1e2993e70 | |||
| 95f07d93a9 | |||
| b82312d26f | |||
| afd13c660e | |||
| b0a0b353cc | |||
| cb96663152 | |||
| 5ed3433d13 | |||
| d26aa15a7f | |||
| 65b57fc0b7 | |||
| 13d4ea33f3 | |||
| 128f54d42e | |||
| 120af6f29d |
@ -15,6 +15,9 @@ jobs:
|
|||||||
run: echo "${LOCIP} gitea.comnenos" >> /etc/hosts
|
run: echo "${LOCIP} gitea.comnenos" >> /etc/hosts
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
- name: Install Build Dependencies
|
- name: Install Build Dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -25,7 +28,8 @@ jobs:
|
|||||||
fuse \
|
fuse \
|
||||||
libfuse2 \
|
libfuse2 \
|
||||||
python3 \
|
python3 \
|
||||||
python3-pip
|
python3-pip \
|
||||||
|
zip
|
||||||
|
|
||||||
- name: Install .NET SDK
|
- name: Install .NET SDK
|
||||||
run: |
|
run: |
|
||||||
@ -34,34 +38,55 @@ jobs:
|
|||||||
./dotnet-install.sh --channel 8.0 --install-dir /usr/local/dotnet
|
./dotnet-install.sh --channel 8.0 --install-dir /usr/local/dotnet
|
||||||
ln -sf /usr/local/dotnet/dotnet /usr/bin/dotnet
|
ln -sf /usr/local/dotnet/dotnet /usr/bin/dotnet
|
||||||
|
|
||||||
- name: Install AppImageTool
|
- name: Setup FUSE and AppImageTool
|
||||||
run: |
|
run: |
|
||||||
|
# Install and load FUSE
|
||||||
|
modprobe fuse || echo "Warning: Could not load fuse module"
|
||||||
|
|
||||||
|
# Download and extract appimagetool without FUSE (using --appimage-extract)
|
||||||
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage \
|
wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage \
|
||||||
-O /usr/local/bin/appimagetool
|
-O appimagetool.AppImage
|
||||||
|
chmod +x appimagetool.AppImage
|
||||||
|
./appimagetool.AppImage --appimage-extract
|
||||||
|
|
||||||
|
# Create wrapper script that uses extracted version
|
||||||
|
echo '#!/bin/bash' > /usr/local/bin/appimagetool
|
||||||
|
echo '/workspace/gmgauthier/notepad/squashfs-root/AppRun "$@"' >> /usr/local/bin/appimagetool
|
||||||
chmod +x /usr/local/bin/appimagetool
|
chmod +x /usr/local/bin/appimagetool
|
||||||
|
|
||||||
- name: Build Linux Packages
|
- name: Build Packages
|
||||||
run: |
|
run: |
|
||||||
cd NotePad
|
cd NotePad
|
||||||
python3 publish.py linux both
|
python3 publish.py both
|
||||||
|
|
||||||
- name: Create Release Archive
|
- name: Create Release Archive
|
||||||
run: |
|
run: |
|
||||||
VERSION=${GITHUB_REF#refs/tags/}
|
VERSION=${GITHUB_REF#refs/tags/}
|
||||||
|
VERSION_NUM=${VERSION#v} # Remove 'v' prefix (e.g., v0.1.4 -> 0.1.4)
|
||||||
mkdir -p release
|
mkdir -p release
|
||||||
|
|
||||||
# Copy AppImage
|
# Copy AppImage (if it exists) - use version from build
|
||||||
cp publish/appimage/NotePad-0.1.0-x86_64.AppImage \
|
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
|
release/NotePad-${VERSION}-x86_64.AppImage
|
||||||
|
fi
|
||||||
|
|
||||||
# Copy Tarball
|
# 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
|
release/notepad-${VERSION}-linux-x64.tar.gz
|
||||||
|
|
||||||
|
# Create Windows zip
|
||||||
|
cd publish/win-x64
|
||||||
|
zip -r ../../release/notepad-${VERSION}-win-x64.zip .
|
||||||
|
cd ../..
|
||||||
|
|
||||||
# Generate checksums
|
# Generate checksums
|
||||||
cd release
|
cd release
|
||||||
|
if [ -f NotePad-${VERSION}-x86_64.AppImage ]; then
|
||||||
sha256sum NotePad-${VERSION}-x86_64.AppImage > NotePad-${VERSION}-x86_64.AppImage.sha256
|
sha256sum NotePad-${VERSION}-x86_64.AppImage > NotePad-${VERSION}-x86_64.AppImage.sha256
|
||||||
|
fi
|
||||||
sha256sum notepad-${VERSION}-linux-x64.tar.gz > notepad-${VERSION}-linux-x64.tar.gz.sha256
|
sha256sum notepad-${VERSION}-linux-x64.tar.gz > notepad-${VERSION}-linux-x64.tar.gz.sha256
|
||||||
|
sha256sum notepad-${VERSION}-win-x64.zip > notepad-${VERSION}-win-x64.zip.sha256
|
||||||
ls -lh # For debugging
|
ls -lh # For debugging
|
||||||
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
@ -70,6 +95,21 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
VERSION=${GITHUB_REF#refs/tags/}
|
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
|
# Create release
|
||||||
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases" \
|
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases" \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
@ -77,31 +117,42 @@ jobs:
|
|||||||
-d "{
|
-d "{
|
||||||
\"tag_name\": \"${VERSION}\",
|
\"tag_name\": \"${VERSION}\",
|
||||||
\"name\": \"NotePad ${VERSION}\",
|
\"name\": \"NotePad ${VERSION}\",
|
||||||
\"body\": \"Release ${VERSION}\n\n## Linux Downloads\n- **AppImage**: Portable, single-file executable (no installation needed)\n- **Tarball**: Traditional installation with \`sudo ./install.sh\`\"
|
\"body\": \"${RELEASE_BODY_JSON}\"
|
||||||
}" > release_response.json
|
}" > release_response.json
|
||||||
|
|
||||||
RELEASE_ID=$(cat release_response.json | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
|
RELEASE_ID=$(cat release_response.json | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2)
|
||||||
|
|
||||||
# Upload AppImage
|
# Upload AppImage if it exists
|
||||||
|
if [ -f release/NotePad-${VERSION}-x86_64.AppImage ]; then
|
||||||
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=NotePad-${VERSION}-x86_64.AppImage" \
|
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=NotePad-${VERSION}-x86_64.AppImage" \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
-H "Content-Type: application/octet-stream" \
|
-H "Content-Type: application/octet-stream" \
|
||||||
--data-binary @release/NotePad-${VERSION}-x86_64.AppImage
|
--data-binary @release/NotePad-${VERSION}-x86_64.AppImage
|
||||||
|
|
||||||
# Upload AppImage checksum
|
|
||||||
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=NotePad-${VERSION}-x86_64.AppImage.sha256" \
|
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=NotePad-${VERSION}-x86_64.AppImage.sha256" \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
-H "Content-Type: text/plain" \
|
-H "Content-Type: text/plain" \
|
||||||
--data-binary @release/NotePad-${VERSION}-x86_64.AppImage.sha256
|
--data-binary @release/NotePad-${VERSION}-x86_64.AppImage.sha256
|
||||||
|
fi
|
||||||
|
|
||||||
# Upload tarball
|
# Upload Linux tarball
|
||||||
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=notepad-${VERSION}-linux-x64.tar.gz" \
|
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=notepad-${VERSION}-linux-x64.tar.gz" \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
-H "Content-Type: application/gzip" \
|
-H "Content-Type: application/gzip" \
|
||||||
--data-binary @release/notepad-${VERSION}-linux-x64.tar.gz
|
--data-binary @release/notepad-${VERSION}-linux-x64.tar.gz
|
||||||
|
|
||||||
# Upload tarball checksum
|
|
||||||
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=notepad-${VERSION}-linux-x64.tar.gz.sha256" \
|
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=notepad-${VERSION}-linux-x64.tar.gz.sha256" \
|
||||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
-H "Content-Type: text/plain" \
|
-H "Content-Type: text/plain" \
|
||||||
--data-binary @release/notepad-${VERSION}-linux-x64.tar.gz.sha256
|
--data-binary @release/notepad-${VERSION}-linux-x64.tar.gz.sha256
|
||||||
|
|
||||||
|
# Upload Windows zip
|
||||||
|
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=notepad-${VERSION}-win-x64.zip" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/zip" \
|
||||||
|
--data-binary @release/notepad-${VERSION}-win-x64.zip
|
||||||
|
|
||||||
|
curl -X POST "https://repos.gmgauthier.com/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=notepad-${VERSION}-win-x64.zip.sha256" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: text/plain" \
|
||||||
|
--data-binary @release/notepad-${VERSION}-win-x64.zip.sha256
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,3 +6,6 @@ publish/
|
|||||||
riderModule.iml
|
riderModule.iml
|
||||||
/_ReSharper.Caches/
|
/_ReSharper.Caches/
|
||||||
poetry.lock
|
poetry.lock
|
||||||
|
|
||||||
|
# ImageMagick artifacts
|
||||||
|
!_*
|
||||||
|
|||||||
@ -15,7 +15,12 @@ public partial class App : Application
|
|||||||
{
|
{
|
||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
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();
|
base.OnFrameworkInitializationCompleted();
|
||||||
|
|||||||
@ -4,6 +4,27 @@
|
|||||||
Title="Untitled - Notepad"
|
Title="Untitled - Notepad"
|
||||||
Width="600" Height="400">
|
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>
|
<DockPanel>
|
||||||
<!-- Menu Bar -->
|
<!-- Menu Bar -->
|
||||||
<Menu DockPanel.Dock="Top">
|
<Menu DockPanel.Dock="Top">
|
||||||
@ -15,7 +36,7 @@
|
|||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="E_xit" Click="OnExitClick"/>
|
<MenuItem Header="E_xit" Click="OnExitClick"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_Edit">
|
<MenuItem Header="_Edit" x:Name="EditMenuItem">
|
||||||
<MenuItem Header="_Undo" Click="OnUndoClick" InputGesture="Ctrl+Z"/>
|
<MenuItem Header="_Undo" Click="OnUndoClick" InputGesture="Ctrl+Z"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="Cu_t" Click="OnCutClick" InputGesture="Ctrl+X"/>
|
<MenuItem Header="Cu_t" Click="OnCutClick" InputGesture="Ctrl+X"/>
|
||||||
@ -29,7 +50,7 @@
|
|||||||
<MenuItem Header="F_ormat">
|
<MenuItem Header="F_ormat">
|
||||||
<MenuItem Header="_Word Wrap" x:Name="WordWrapMenuItem" Click="OnWordWrapToggle">
|
<MenuItem Header="_Word Wrap" x:Name="WordWrapMenuItem" Click="OnWordWrapToggle">
|
||||||
<MenuItem.Icon>
|
<MenuItem.Icon>
|
||||||
<CheckBox x:Name="WordWrapCheckBox" IsChecked="True" IsHitTestVisible="False"/>
|
<CheckBox x:Name="WordWrapCheckBox" IsChecked="False" IsHitTestVisible="False"/>
|
||||||
</MenuItem.Icon>
|
</MenuItem.Icon>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -43,7 +64,7 @@
|
|||||||
<TextBox x:Name="EditorTextBox"
|
<TextBox x:Name="EditorTextBox"
|
||||||
AcceptsReturn="True"
|
AcceptsReturn="True"
|
||||||
AcceptsTab="True"
|
AcceptsTab="True"
|
||||||
TextWrapping="Wrap"
|
TextWrapping="NoWrap"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
@ -52,8 +73,9 @@
|
|||||||
Background="White"
|
Background="White"
|
||||||
Foreground="Black"
|
Foreground="Black"
|
||||||
CaretBrush="Black"
|
CaretBrush="Black"
|
||||||
FontFamily="Consolas,Courier New,monospace"
|
FontFamily="Courier New,Liberation Mono,Courier,monospace"
|
||||||
FontSize="12">
|
FontSize="13"
|
||||||
|
ClearSelectionOnLostFocus="False">
|
||||||
<TextBox.Styles>
|
<TextBox.Styles>
|
||||||
<Style Selector="TextBox">
|
<Style Selector="TextBox">
|
||||||
<Setter Property="Background" Value="White"/>
|
<Setter Property="Background" Value="White"/>
|
||||||
|
|||||||
@ -17,7 +17,11 @@ namespace NotePad
|
|||||||
private bool _isModified;
|
private bool _isModified;
|
||||||
private string? _originalText;
|
private string? _originalText;
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow() : this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainWindow(string? fileToOpen)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
UpdateTitle();
|
UpdateTitle();
|
||||||
@ -26,6 +30,30 @@ namespace NotePad
|
|||||||
textBox.TextChanged += OnTextChanged;
|
textBox.TextChanged += OnTextChanged;
|
||||||
|
|
||||||
Closing += OnWindowClosing;
|
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()
|
private void UpdateTitle()
|
||||||
@ -266,7 +294,17 @@ namespace NotePad
|
|||||||
var textBox = this.FindControl<TextBox>("EditorTextBox")!;
|
var textBox = this.FindControl<TextBox>("EditorTextBox")!;
|
||||||
|
|
||||||
checkBox.IsChecked = !checkBox.IsChecked;
|
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
|
// Edit Menu
|
||||||
|
|||||||
@ -1,18 +1,21 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||||
|
<ApplicationIcon>img\notepad-icon.ico</ApplicationIcon>
|
||||||
|
<Version>0.1.17</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.3.12"/>
|
<PackageReference Include="Avalonia" Version="11.3.12" />
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.3.12"/>
|
<PackageReference Include="Avalonia.Desktop" Version="11.3.12" />
|
||||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.12"/>
|
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.12" />
|
||||||
<PackageReference Include="Avalonia.Fonts.Inter" 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">
|
<PackageReference Include="Avalonia.Diagnostics" Version="11.3.12">
|
||||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
|
|||||||
@ -5,13 +5,14 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
APP_NAME="NotePad"
|
APP_NAME="NotePad"
|
||||||
VERSION="0.1.0"
|
VERSION="${1:-0.1.0}" # Use first argument or default to 0.1.0
|
||||||
ARCH="x86_64"
|
ARCH="x86_64"
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
PUBLISH_DIR="../publish/linux-x64"
|
PUBLISH_DIR="../publish/linux-x64"
|
||||||
APPDIR="NotePad.AppDir"
|
APPDIR="NotePad.AppDir"
|
||||||
OUTPUT_DIR="../publish/appimage"
|
OUTPUT_DIR="../publish/appimage"
|
||||||
|
ICON_SOURCE="img/notepad-icon.svg"
|
||||||
|
|
||||||
echo "============================================================"
|
echo "============================================================"
|
||||||
echo "Building AppImage for $APP_NAME v$VERSION"
|
echo "Building AppImage for $APP_NAME v$VERSION"
|
||||||
@ -47,15 +48,14 @@ Categories=Utility;TextEditor;
|
|||||||
Terminal=false
|
Terminal=false
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Create a simple icon (using text as placeholder - replace with actual icon)
|
# Copy application icon
|
||||||
echo "Creating icon placeholder..."
|
echo "Copying application icon..."
|
||||||
# This creates a simple SVG icon - you should replace with an actual icon
|
if [ ! -f "$ICON_SOURCE" ]; then
|
||||||
cat > "$APPDIR/usr/share/icons/hicolor/256x256/apps/notepad.svg" << EOF
|
echo "❌ ERROR: Icon not found at $ICON_SOURCE"
|
||||||
<svg width="256" height="256" xmlns="http://www.w3.org/2000/svg">
|
exit 1
|
||||||
<rect width="256" height="256" fill="#4a90e2"/>
|
fi
|
||||||
<text x="128" y="140" font-size="120" fill="white" text-anchor="middle" font-family="sans-serif">N</text>
|
mkdir -p "$APPDIR/usr/share/icons/hicolor/scalable/apps"
|
||||||
</svg>
|
cp "$ICON_SOURCE" "$APPDIR/usr/share/icons/hicolor/scalable/apps/notepad.svg"
|
||||||
EOF
|
|
||||||
|
|
||||||
# Create AppRun script
|
# Create AppRun script
|
||||||
echo "Creating AppRun script..."
|
echo "Creating AppRun script..."
|
||||||
@ -71,7 +71,7 @@ chmod +x "$APPDIR/AppRun"
|
|||||||
|
|
||||||
# Copy desktop file and icon to root of AppDir
|
# Copy desktop file and icon to root of AppDir
|
||||||
cp "$APPDIR/usr/share/applications/notepad.desktop" "$APPDIR/"
|
cp "$APPDIR/usr/share/applications/notepad.desktop" "$APPDIR/"
|
||||||
cp "$APPDIR/usr/share/icons/hicolor/256x256/apps/notepad.svg" "$APPDIR/notepad.svg"
|
cp "$APPDIR/usr/share/icons/hicolor/scalable/apps/notepad.svg" "$APPDIR/notepad.svg"
|
||||||
|
|
||||||
# Check for appimagetool
|
# Check for appimagetool
|
||||||
if ! command -v appimagetool &> /dev/null; then
|
if ! command -v appimagetool &> /dev/null; then
|
||||||
|
|||||||
BIN
NotePad/img/notepad-icon.ico
Normal file
BIN
NotePad/img/notepad-icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 294 KiB |
213
NotePad/img/notepad-icon.svg
Normal file
213
NotePad/img/notepad-icon.svg
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
version="1.1"
|
||||||
|
width="72pt"
|
||||||
|
height="72pt"
|
||||||
|
id="svg604">
|
||||||
|
<metadata
|
||||||
|
id="metadata45">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs606">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient612">
|
||||||
|
<stop
|
||||||
|
id="stop613"
|
||||||
|
style="stop-color:#7fa8e3;stop-opacity:0.74117601"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop614"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
x1="50.643887"
|
||||||
|
y1="5.3679295"
|
||||||
|
x2="35.752094"
|
||||||
|
y2="68.044357"
|
||||||
|
id="linearGradient615"
|
||||||
|
xlink:href="#linearGradient612"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
spreadMethod="pad" />
|
||||||
|
</defs>
|
||||||
|
<path
|
||||||
|
d="M 12.8163,74.753 C 10.3856,73.6481 7.07107,70.1126 8.83884,65.2512 L 78.6656,20.8361 c 1.9888,1.7678 3.5356,3.2041 1.9888,7.0711 -1.1048,1.9887 -14.2527,46.6248 -14.4736,49.4975 -0.8839,3.0936 -3.425,6.8501 -7.6235,6.6291 -4.1984,-0.221 -42.6474,-8.6179 -45.741,-9.2808 z"
|
||||||
|
transform="matrix(1.114903,0,0,1.114903,-5.305332,-3.889256)"
|
||||||
|
id="path794"
|
||||||
|
style="fill-opacity:0.30147125;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="M 12.8163,74.753 C 10.3856,73.6481 7.07107,70.1126 8.83884,65.2512 9.72267,59.948 25.6326,13.1021 29.1682,10.8924 31.3778,8.90368 34.582,8.13026 39.1119,9.34561 c 3.7565,0.88389 37.565,9.72279 39.5537,11.49049 1.9888,1.7678 3.5356,3.2041 1.9888,7.0711 -1.1048,1.9887 -14.2527,46.6248 -14.4736,49.4975 -0.8839,3.0936 -3.425,6.8501 -7.6235,6.6291 -4.1984,-0.221 -42.6474,-8.6179 -45.741,-9.2808 z"
|
||||||
|
transform="matrix(1.114903,0,0,1.114903,-8.162471,-8.460684)"
|
||||||
|
id="path609"
|
||||||
|
style="fill:#3d4e67;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="M 17.8987,70.9965 C 15.3576,70.3336 11.7114,69.6706 13.0373,65.6932 15.468,55.9705 27.8424,18.6264 33.1456,13.986 c 1.2154,-1.1049 5.3033,-1.5468 13.0373,0.8839 8.8389,2.6516 26.7375,8.6178 28.5053,9.5017 1.7677,0.8839 2.4307,0.8839 1.1048,4.8614 -1.9887,3.9775 -10.8275,38.007 -13.0373,43.7522 -1.5467,4.088 -1.8782,5.9662 -4.5299,5.9662"
|
||||||
|
transform="matrix(1.114903,0,0,1.114903,-8.162471,-8.460684)"
|
||||||
|
id="path608"
|
||||||
|
style="fill:#ffffff;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 28.75,13.75 c 0,0 3.125,-6.25005 10.9375,-4.37505 C 47.5,11.25 78.125,19.375 77.8125,21.875 77.5,24.375 71.875,39.0625 71.5625,40.3125 71.25,41.5625 42.5,40.9375 31.5625,47.5 20.625,54.0625 12.5,59.6875 12.5,59.6875 c 0,0 11.25,-35 16.25,-45.9375 z"
|
||||||
|
transform="matrix(0.94678,0,0,0.94678,-0.480566,0.409517)"
|
||||||
|
id="path636"
|
||||||
|
style="fill:url(#linearGradient615);fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="M 29.2429,15.8991 69.8423,26.6877"
|
||||||
|
transform="translate(1.135645,0.851736)"
|
||||||
|
id="path671"
|
||||||
|
style="fill:none;stroke:#42667e;stroke-width:1pt" />
|
||||||
|
<path
|
||||||
|
d="M 27.8233,19.306 67.8549,30.9464"
|
||||||
|
transform="matrix(0.999855,-0.01703691,0.01703691,0.999855,-0.705041,5.077353)"
|
||||||
|
id="path672"
|
||||||
|
style="fill:none;stroke:#42667e;stroke-width:1pt" />
|
||||||
|
<path
|
||||||
|
d="M 29.2429,15.8991 69.8423,26.6877"
|
||||||
|
transform="translate(-5.394323,17.0347)"
|
||||||
|
id="path673"
|
||||||
|
style="fill:none;stroke:#42667e;stroke-width:1pt" />
|
||||||
|
<path
|
||||||
|
d="M 29.2429,15.8991 69.8423,26.6877"
|
||||||
|
transform="translate(-11.35647,34.0694)"
|
||||||
|
id="path675"
|
||||||
|
style="fill:none;stroke:#42667e;stroke-width:1pt" />
|
||||||
|
<path
|
||||||
|
d="M 27.8233,19.306 67.8549,30.9464"
|
||||||
|
transform="matrix(0.999855,-0.01703691,0.01703691,0.999855,-13.19715,38.29502)"
|
||||||
|
id="path676"
|
||||||
|
style="fill:none;stroke:#42667e;stroke-width:1pt" />
|
||||||
|
<path
|
||||||
|
d="M 27.8233,19.306 67.8549,30.9464"
|
||||||
|
transform="matrix(0.999855,-0.01703691,0.01703691,0.999855,-7.235008,21.26032)"
|
||||||
|
id="path674"
|
||||||
|
style="fill:none;stroke:#42667e;stroke-width:1pt" />
|
||||||
|
<g
|
||||||
|
id="g666">
|
||||||
|
<path
|
||||||
|
d="m 44.8581,15.0473 c -3.4478,0 -5.1105,-2.5484 -5.1105,-6.38799 0,-3.83962 2.7983,-6.95584 6.2461,-6.95584 3.4478,0 4.5425,1.12884 4.5425,4.96845"
|
||||||
|
transform="matrix(0.948718,0,0,1,4.011168,0.567827)"
|
||||||
|
id="path667"
|
||||||
|
style="fill:none;stroke:#4f4f4f;stroke-width:2.875;stroke-linecap:round" />
|
||||||
|
<path
|
||||||
|
d="m 44.8581,14.7634 c -3.4478,0 -5.3944,-2.2645 -5.3944,-6.10409 0,-3.83962 2.7983,-7.807574 6.2461,-7.807574 3.4478,0 4.8264,1.980574 4.8264,5.820184"
|
||||||
|
transform="matrix(0.948718,0,0,1,4.011168,0.567827)"
|
||||||
|
id="path668"
|
||||||
|
style="fill:none;stroke:#c2c2c2;stroke-width:0.625;stroke-linecap:round" />
|
||||||
|
</g>
|
||||||
|
<use
|
||||||
|
transform="translate(10.788642,1.987381)"
|
||||||
|
id="use669"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="90"
|
||||||
|
height="90"
|
||||||
|
xlink:href="#g666" />
|
||||||
|
<g
|
||||||
|
transform="matrix(0.69841,0,0,0.69841,31.4038,0.671206)"
|
||||||
|
id="g677">
|
||||||
|
<defs
|
||||||
|
id="defs611">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient626">
|
||||||
|
<stop
|
||||||
|
id="stop627"
|
||||||
|
style="stop-color:#b5772d;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop628"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient619">
|
||||||
|
<stop
|
||||||
|
id="stop620"
|
||||||
|
style="stop-color:#770000;stop-opacity:1"
|
||||||
|
offset="0" />
|
||||||
|
<stop
|
||||||
|
id="stop621"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0"
|
||||||
|
offset="1" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
x1="66.331696"
|
||||||
|
y1="23.212469"
|
||||||
|
x2="63.465496"
|
||||||
|
y2="20.962799"
|
||||||
|
id="linearGradient622"
|
||||||
|
xlink:href="#linearGradient619"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="scale(1.004516,0.995504)"
|
||||||
|
spreadMethod="pad" />
|
||||||
|
<linearGradient
|
||||||
|
x1="56.327614"
|
||||||
|
y1="43.377247"
|
||||||
|
x2="51.654526"
|
||||||
|
y2="39.762909"
|
||||||
|
id="linearGradient625"
|
||||||
|
xlink:href="#linearGradient626"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="scale(0.912664,1.095694)"
|
||||||
|
spreadMethod="pad" />
|
||||||
|
</defs>
|
||||||
|
<path
|
||||||
|
d="M 9.33685,82.1156 C 17.9129,79.7641 30.9112,77.5637 40.1097,71.8924 56.9851,62.0714 66.0118,41.6332 76.4551,25.5877 77.285,12.3086 64.1128,5.96872 59.1331,8.87345 46.4766,25.4722 37.5548,43.5235 23.4458,55.9725 19.0886,66.5542 9.12934,82.738 9.33685,82.1156 z"
|
||||||
|
transform="translate(3.814559,2.934275)"
|
||||||
|
id="path632"
|
||||||
|
style="fill-opacity:0.28318601;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="M 9.33685,82.1156 C 17.9129,79.7641 28.5638,74.9228 37.7623,69.2516 54.6377,59.4306 64.2512,38.4055 74.6945,22.36 75.5244,9.08092 64.1128,5.96872 59.1331,8.87345 46.4766,25.4722 37.5548,43.5235 23.4458,55.9725 19.0886,66.5542 9.12934,82.738 9.33685,82.1156 z"
|
||||||
|
id="path617"
|
||||||
|
style="fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 71.9972,20.9076 c -1.729,2.4898 -3.4581,4.9796 -5.1871,7.4694 -2.2823,-5.3946 -4.9796,-8.0919 -11.8266,-8.7143 2.2132,-2.6973 4.4263,-5.3946 6.6395,-8.0919 5.5329,-0.6225 9.8209,4.1497 10.3742,9.3368 z"
|
||||||
|
id="path613"
|
||||||
|
style="fill:#be6d6d;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 54.776,20.9076 c 5.3946,-0.3458 9.1293,3.6656 11.2041,8.2994 -8.4377,13.6248 -15.423,27.0422 -29.6703,37.7622 0,0 -3.5272,-10.1668 -8.7143,-8.9218 6.432,-7.262 21.3709,-28.0104 27.1805,-37.1398 z"
|
||||||
|
id="path614"
|
||||||
|
style="fill:#ffbc24;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 27.0767,58.6698 c 4.6684,-0.2421 8.6106,5.3255 7.5732,8.7144 -2.0057,1.5215 -5.2562,3.0431 -7.2619,4.5646 -0.3458,-2.7664 -2.144,-4.9104 -6.0171,-4.5646 1.729,-2.974 3.9768,-5.7404 5.7058,-8.7144 z"
|
||||||
|
id="path615"
|
||||||
|
style="fill:#e9dbb9;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 21.7859,66.9692 c 3.5618,-0.8299 5.0488,2.6973 5.8096,4.7722 l -13.2791,6.017 7.4695,-10.7892 z"
|
||||||
|
id="path616"
|
||||||
|
style="fill:#586f93;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 71.9972,20.9076 c -1.729,2.4898 -3.4581,4.9796 -5.1871,7.4694 -2.2823,-5.3946 -4.9796,-8.0919 -11.8266,-8.7143 2.2132,-2.6973 4.4263,-5.3946 6.6395,-8.0919 5.5329,-0.6225 9.8209,4.1497 10.3742,9.3368 z"
|
||||||
|
id="path618"
|
||||||
|
style="fill:url(#linearGradient622);fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 62.8679,12.1932 -5.3946,6.847 2.9048,1.0374 5.3946,-6.432 -2.9048,-1.4524 z"
|
||||||
|
id="path623"
|
||||||
|
style="fill:#ffffff;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 54.776,20.9076 c 5.3946,-0.3458 9.1293,3.6656 11.2041,8.2994 -8.4377,13.6248 -15.423,27.0422 -29.6703,37.7622 0,0 -3.5272,-10.1668 -8.7143,-8.9218 6.432,-7.262 21.3709,-28.0104 27.1805,-37.1398 z"
|
||||||
|
id="path624"
|
||||||
|
style="fill:url(#linearGradient625);fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 29.6703,56.18 c 1.2449,0.7608 2.4898,1.5215 3.7347,2.2823 C 42.5344,47.6039 46.6841,36.5381 58.9257,24.6423 57.7499,23.8815 56.5742,23.1208 55.3984,22.36 48.0673,35.0857 39.6987,47.3965 29.6703,56.18 z"
|
||||||
|
id="path630"
|
||||||
|
style="fill:#ffffff;fill-rule:evenodd" />
|
||||||
|
<path
|
||||||
|
d="m 34.7538,67.2805 c 0.2074,-2.1786 -0.3113,-3.7348 -1.4525,-5.4984 -1.5215,3.3889 -3.873,5.8441 -7.1582,6.6395 -0.7262,0.6224 1.2449,1.9711 1.4524,3.216 1.8674,-1.1412 7.1583,-3.7347 7.1583,-4.3571 z"
|
||||||
|
id="path631"
|
||||||
|
style="fill:#9c7850;fill-rule:evenodd" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 9.5 KiB |
BIN
NotePad/img/notepad-screenshot-linux.png
Normal file
BIN
NotePad/img/notepad-screenshot-linux.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
NotePad/img/notepad-screenshot-win11.png
Normal file
BIN
NotePad/img/notepad-screenshot-win11.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@ -8,6 +8,8 @@ APP_NAME="NotePad"
|
|||||||
INSTALL_DIR="/opt/notepad"
|
INSTALL_DIR="/opt/notepad"
|
||||||
BIN_LINK="/usr/local/bin/notepad"
|
BIN_LINK="/usr/local/bin/notepad"
|
||||||
DESKTOP_FILE="/usr/share/applications/notepad.desktop"
|
DESKTOP_FILE="/usr/share/applications/notepad.desktop"
|
||||||
|
ICON_DIR="/usr/share/icons/hicolor/scalable/apps"
|
||||||
|
ICON_FILE="$ICON_DIR/notepad.svg"
|
||||||
|
|
||||||
echo "============================================================"
|
echo "============================================================"
|
||||||
echo "$APP_NAME Installer"
|
echo "$APP_NAME Installer"
|
||||||
@ -41,6 +43,11 @@ chmod +x "$INSTALL_DIR/NotePad"
|
|||||||
echo "→ Creating symlink: $BIN_LINK"
|
echo "→ Creating symlink: $BIN_LINK"
|
||||||
ln -sf "$INSTALL_DIR/NotePad" "$BIN_LINK"
|
ln -sf "$INSTALL_DIR/NotePad" "$BIN_LINK"
|
||||||
|
|
||||||
|
# Install icon
|
||||||
|
echo "→ Installing application icon..."
|
||||||
|
mkdir -p "$ICON_DIR"
|
||||||
|
cp "$SCRIPT_DIR/img/notepad-icon.svg" "$ICON_FILE"
|
||||||
|
|
||||||
# Create desktop entry
|
# Create desktop entry
|
||||||
echo "→ Creating desktop entry..."
|
echo "→ Creating desktop entry..."
|
||||||
cat > "$DESKTOP_FILE" << EOF
|
cat > "$DESKTOP_FILE" << EOF
|
||||||
@ -48,13 +55,19 @@ cat > "$DESKTOP_FILE" << EOF
|
|||||||
Name=NotePad
|
Name=NotePad
|
||||||
Comment=Simple text editor
|
Comment=Simple text editor
|
||||||
Exec=notepad %F
|
Exec=notepad %F
|
||||||
Icon=text-editor
|
Icon=notepad
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Utility;TextEditor;
|
Categories=Utility;TextEditor;
|
||||||
Terminal=false
|
Terminal=false
|
||||||
MimeType=text/plain;
|
MimeType=text/plain;
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Update icon cache if available
|
||||||
|
if command -v gtk-update-icon-cache &> /dev/null; then
|
||||||
|
echo "→ Updating icon cache..."
|
||||||
|
gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
# Update desktop database if available
|
# Update desktop database if available
|
||||||
if command -v update-desktop-database &> /dev/null; then
|
if command -v update-desktop-database &> /dev/null; then
|
||||||
echo "→ Updating desktop database..."
|
echo "→ Updating desktop database..."
|
||||||
|
|||||||
@ -9,9 +9,30 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tarfile
|
import tarfile
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
from pathlib import Path
|
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):
|
def run_command(cmd, description):
|
||||||
"""Run a shell command and print status"""
|
"""Run a shell command and print status"""
|
||||||
print(f"\n{'=' * 60}")
|
print(f"\n{'=' * 60}")
|
||||||
@ -69,7 +90,7 @@ def build_windows_installer():
|
|||||||
print(f"\n⚠️ WARNING: Failed to create installer: {e}")
|
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"""
|
"""Create tar.gz archive with install script"""
|
||||||
print(f"\n{'=' * 60}")
|
print(f"\n{'=' * 60}")
|
||||||
print("Creating Linux tar.gz archive")
|
print("Creating Linux tar.gz archive")
|
||||||
@ -100,8 +121,13 @@ def build_linux_tarball():
|
|||||||
shutil.copy(script_path, temp_dir / "notepad" / script)
|
shutil.copy(script_path, temp_dir / "notepad" / script)
|
||||||
os.chmod(temp_dir / "notepad" / script, 0o755)
|
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
|
# 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:
|
with tarfile.open(tarball_path, "w:gz") as tar:
|
||||||
tar.add(temp_dir / "notepad", arcname="notepad")
|
tar.add(temp_dir / "notepad", arcname="notepad")
|
||||||
|
|
||||||
@ -116,7 +142,7 @@ def build_linux_tarball():
|
|||||||
print(f" sudo ./install.sh")
|
print(f" sudo ./install.sh")
|
||||||
|
|
||||||
|
|
||||||
def build_linux_appimage():
|
def build_linux_appimage(version):
|
||||||
"""Build Linux AppImage"""
|
"""Build Linux AppImage"""
|
||||||
build_script = Path("build-appimage.sh")
|
build_script = Path("build-appimage.sh")
|
||||||
if not build_script.exists():
|
if not build_script.exists():
|
||||||
@ -125,7 +151,7 @@ def build_linux_appimage():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["bash", str(build_script)],
|
["bash", str(build_script), version],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True
|
text=True
|
||||||
)
|
)
|
||||||
@ -190,10 +216,11 @@ def publish_platform(platform, linux_package='both'):
|
|||||||
|
|
||||||
# Build Linux packages
|
# Build Linux packages
|
||||||
if platform == 'linux':
|
if platform == 'linux':
|
||||||
|
version = get_version()
|
||||||
if linux_package in ['appimage', 'both']:
|
if linux_package in ['appimage', 'both']:
|
||||||
build_linux_appimage()
|
build_linux_appimage(version)
|
||||||
if linux_package in ['tarball', 'both']:
|
if linux_package in ['tarball', 'both']:
|
||||||
build_linux_tarball()
|
build_linux_tarball(version)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
137
README.md
Normal file
137
README.md
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
# NotePad
|
||||||
|
|
||||||
|
A simple cross-platform text editor built with Avalonia UI and .NET 8.
|
||||||
|
|
||||||
|
| Windows | Linux |
|
||||||
|
|-----------------------------------------------------------------| ----- |
|
||||||
|
|  |  |
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
Download the latest release from the [releases page](https://repos.gmgauthier.com/gmgauthier/notepad/releases).
|
||||||
|
|
||||||
|
#### Option 1: AppImage (Recommended)
|
||||||
|
|
||||||
|
The AppImage is a portable, single-file executable that requires no installation.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download the AppImage
|
||||||
|
wget https://repos.gmgauthier.com/gmgauthier/notepad/releases/download/v0.1.3/NotePad-v0.1.3-x86_64.AppImage
|
||||||
|
|
||||||
|
# Make it executable
|
||||||
|
chmod +x NotePad-v0.1.3-x86_64.AppImage
|
||||||
|
|
||||||
|
# Run it
|
||||||
|
./NotePad-v0.1.3-x86_64.AppImage
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 2: System Installation (Tarball)
|
||||||
|
|
||||||
|
For a traditional system-wide installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download and extract
|
||||||
|
wget https://repos.gmgauthier.com/gmgauthier/notepad/releases/download/v0.1.3/notepad-v0.1.3-linux-x64.tar.gz
|
||||||
|
tar -xzf notepad-v0.1.3-linux-x64.tar.gz
|
||||||
|
cd notepad
|
||||||
|
|
||||||
|
# Install (requires sudo)
|
||||||
|
sudo ./install.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This installs NotePad to `/opt/notepad` and creates:
|
||||||
|
- Command-line shortcut: `notepad`
|
||||||
|
- Desktop menu entry
|
||||||
|
|
||||||
|
To uninstall:
|
||||||
|
```bash
|
||||||
|
sudo /opt/notepad/uninstall.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
Download the latest release from the [releases page](https://repos.gmgauthier.com/gmgauthier/notepad/releases).
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# Download the zip file
|
||||||
|
# Extract notepad-v0.1.3-win-x64.zip
|
||||||
|
|
||||||
|
# Run NotePad.exe from the extracted folder
|
||||||
|
```
|
||||||
|
|
||||||
|
No installation required - just extract and run!
|
||||||
|
|
||||||
|
## Building from Source
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)
|
||||||
|
- Python 3.12+
|
||||||
|
- (Linux only) `appimagetool` for AppImage builds
|
||||||
|
|
||||||
|
### Build Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd NotePad
|
||||||
|
|
||||||
|
# Build for Linux only
|
||||||
|
python3 publish.py linux
|
||||||
|
|
||||||
|
# Build for Windows only
|
||||||
|
python3 publish.py windows
|
||||||
|
|
||||||
|
# Build for both platforms
|
||||||
|
python3 publish.py both
|
||||||
|
|
||||||
|
# Linux-specific package options
|
||||||
|
python3 publish.py linux appimage # AppImage only
|
||||||
|
python3 publish.py linux tarball # Tarball only
|
||||||
|
python3 publish.py linux both # Both packages
|
||||||
|
```
|
||||||
|
|
||||||
|
Build outputs are located in `../publish/`:
|
||||||
|
- Linux AppImage: `publish/appimage/`
|
||||||
|
- Linux Tarball: `publish/tarball/`
|
||||||
|
- Windows: `publish/win-x64/`
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
NotePad/
|
||||||
|
├── NotePad/ # Main application
|
||||||
|
│ ├── App.axaml # Application XAML
|
||||||
|
│ ├── MainWindow.axaml # Main window UI
|
||||||
|
│ ├── Program.cs # Entry point
|
||||||
|
│ └── publish.py # Build script
|
||||||
|
├── .gitea/
|
||||||
|
│ └── workflows/
|
||||||
|
│ └── release.yaml # CI/CD workflow
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running in Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd NotePad/NotePad
|
||||||
|
dotnet run
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
|
||||||
|
|
||||||
|
For more information, please refer to <https://unlicense.org>
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
Greg Gauthier
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
Okay, I'll admit it. This application was build with the assisance of Grok, and the Claude agent built into Jetbrains Rider.
|
||||||
24
UNLICENSE
Normal file
24
UNLICENSE
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
For more information, please refer to <https://unlicense.org>
|
||||||
113
make-release.py
Executable file
113
make-release.py
Executable 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()
|
||||||
Loading…
Reference in New Issue
Block a user