From e51f906302995c8defc550a0ca8cd95ebe08cd39 Mon Sep 17 00:00:00 2001 From: Maciej Zagozda Date: Mon, 27 Jul 2026 21:52:31 +0200 Subject: [PATCH 01/11] Initial version --- .gitignore | 2 + NoteManager.sln | 30 +- README.md | 108 ++--- global.json | 2 +- installer/README.md | 28 +- installer/build-installer.ps1 | 4 +- installer/build-macos.sh | 58 +++ installer/macos/Info.plist | 29 ++ spikes/AvaloniaPdfSpike/App.axaml | 10 + spikes/AvaloniaPdfSpike/App.axaml.cs | 23 + .../AvaloniaPdfSpike/AvaloniaPdfSpike.csproj | 27 ++ spikes/AvaloniaPdfSpike/MainWindow.axaml | 64 +++ spikes/AvaloniaPdfSpike/MainWindow.axaml.cs | 59 +++ spikes/AvaloniaPdfSpike/Program.cs | 24 ++ spikes/AvaloniaPdfSpike/README.md | 44 ++ spikes/AvaloniaPdfSpike/app.manifest | 18 + .../Infrastructure/ApplicationOptions.cs | 6 +- .../Services/UiAutomationServer.cs | 2 +- .../ViewModels/MainViewModel.cs | 38 +- src/NoteManager.Core/NoteManager.Core.csproj | 31 ++ src/NoteManager.Desktop/App.axaml | 29 ++ src/NoteManager.Desktop/App.axaml.cs | 22 + .../Controls/PdfViewer.axaml | 27 ++ .../Controls/PdfViewer.axaml.cs | 61 +++ src/NoteManager.Desktop/Converters.cs | 21 + .../Dialogs/AssignTagsDialog.axaml | 55 +++ .../Dialogs/AssignTagsDialog.axaml.cs | 78 ++++ .../Dialogs/ConfirmDialog.axaml | 27 ++ .../Dialogs/ConfirmDialog.axaml.cs | 23 + src/NoteManager.Desktop/MainWindow.axaml | 296 +++++++++++++ src/NoteManager.Desktop/MainWindow.axaml.cs | 396 ++++++++++++++++++ .../NoteManager.Desktop.csproj | 27 ++ src/NoteManager.Desktop/Program.cs | 19 + .../NoteManager.App.Tests.csproj | 4 +- .../PdfDropImportViewModelTests.cs | 133 ++---- .../UiAutomationServerTests.cs | 47 +++ 36 files changed, 1669 insertions(+), 203 deletions(-) create mode 100755 installer/build-macos.sh create mode 100644 installer/macos/Info.plist create mode 100644 spikes/AvaloniaPdfSpike/App.axaml create mode 100644 spikes/AvaloniaPdfSpike/App.axaml.cs create mode 100644 spikes/AvaloniaPdfSpike/AvaloniaPdfSpike.csproj create mode 100644 spikes/AvaloniaPdfSpike/MainWindow.axaml create mode 100644 spikes/AvaloniaPdfSpike/MainWindow.axaml.cs create mode 100644 spikes/AvaloniaPdfSpike/Program.cs create mode 100644 spikes/AvaloniaPdfSpike/README.md create mode 100644 spikes/AvaloniaPdfSpike/app.manifest create mode 100644 src/NoteManager.Core/NoteManager.Core.csproj create mode 100644 src/NoteManager.Desktop/App.axaml create mode 100644 src/NoteManager.Desktop/App.axaml.cs create mode 100644 src/NoteManager.Desktop/Controls/PdfViewer.axaml create mode 100644 src/NoteManager.Desktop/Controls/PdfViewer.axaml.cs create mode 100644 src/NoteManager.Desktop/Converters.cs create mode 100644 src/NoteManager.Desktop/Dialogs/AssignTagsDialog.axaml create mode 100644 src/NoteManager.Desktop/Dialogs/AssignTagsDialog.axaml.cs create mode 100644 src/NoteManager.Desktop/Dialogs/ConfirmDialog.axaml create mode 100644 src/NoteManager.Desktop/Dialogs/ConfirmDialog.axaml.cs create mode 100644 src/NoteManager.Desktop/MainWindow.axaml create mode 100644 src/NoteManager.Desktop/MainWindow.axaml.cs create mode 100644 src/NoteManager.Desktop/NoteManager.Desktop.csproj create mode 100644 src/NoteManager.Desktop/Program.cs create mode 100644 tests/NoteManager.App.Tests/UiAutomationServerTests.cs diff --git a/.gitignore b/.gitignore index 8dcdae4..933d0a4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ obj/ artifacts/ **/.notes/ installer/publish/ +installer/publish-macos/ installer/Output/ *.user *.suo +**/.DS_Store diff --git a/NoteManager.sln b/NoteManager.sln index c024283..3ff362b 100644 --- a/NoteManager.sln +++ b/NoteManager.sln @@ -1,12 +1,14 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 +Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoteManager.App", "src\NoteManager.App\NoteManager.App.csproj", "{A1C64B6F-3D2E-46A2-8F7E-64218B641842}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoteManager.App.Tests", "tests\NoteManager.App.Tests\NoteManager.App.Tests.csproj", "{9F829F14-BF7B-4CB4-8DE4-1C7EB40DB5C7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoteManager.App.UiTests", "tests\NoteManager.App.UiTests\NoteManager.App.UiTests.csproj", "{B7961763-3072-4A43-89D2-52A5373DA9CB}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{40AE1BBE-BA69-42C4-AE41-B9C79190BA46}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoteManager.Core", "src\NoteManager.Core\NoteManager.Core.csproj", "{C5655CB1-54E2-473E-A47A-0E8C2E4409C4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NoteManager.Desktop", "src\NoteManager.Desktop\NoteManager.Desktop.csproj", "{BE8B426F-D536-46C6-8297-768A80CB59F3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -14,17 +16,21 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A1C64B6F-3D2E-46A2-8F7E-64218B641842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A1C64B6F-3D2E-46A2-8F7E-64218B641842}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A1C64B6F-3D2E-46A2-8F7E-64218B641842}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A1C64B6F-3D2E-46A2-8F7E-64218B641842}.Release|Any CPU.Build.0 = Release|Any CPU {9F829F14-BF7B-4CB4-8DE4-1C7EB40DB5C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9F829F14-BF7B-4CB4-8DE4-1C7EB40DB5C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {9F829F14-BF7B-4CB4-8DE4-1C7EB40DB5C7}.Release|Any CPU.ActiveCfg = Release|Any CPU {9F829F14-BF7B-4CB4-8DE4-1C7EB40DB5C7}.Release|Any CPU.Build.0 = Release|Any CPU - {B7961763-3072-4A43-89D2-52A5373DA9CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7961763-3072-4A43-89D2-52A5373DA9CB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7961763-3072-4A43-89D2-52A5373DA9CB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7961763-3072-4A43-89D2-52A5373DA9CB}.Release|Any CPU.Build.0 = Release|Any CPU + {C5655CB1-54E2-473E-A47A-0E8C2E4409C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5655CB1-54E2-473E-A47A-0E8C2E4409C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5655CB1-54E2-473E-A47A-0E8C2E4409C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5655CB1-54E2-473E-A47A-0E8C2E4409C4}.Release|Any CPU.Build.0 = Release|Any CPU + {BE8B426F-D536-46C6-8297-768A80CB59F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE8B426F-D536-46C6-8297-768A80CB59F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE8B426F-D536-46C6-8297-768A80CB59F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE8B426F-D536-46C6-8297-768A80CB59F3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C5655CB1-54E2-473E-A47A-0E8C2E4409C4} = {40AE1BBE-BA69-42C4-AE41-B9C79190BA46} + {BE8B426F-D536-46C6-8297-768A80CB59F3} = {40AE1BBE-BA69-42C4-AE41-B9C79190BA46} EndGlobalSection EndGlobal diff --git a/README.md b/README.md index f6e2c90..fe469d5 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,47 @@ # NoteManager -NoteManager is a .NET 8 WPF desktop application inspired by the supplied three-pane notebook screenshot. It recreates the dense tag navigation, searchable note list, formatting toolbar, selected-note metadata, and a fully interactive in-app PDF preview. +NoteManager is a cross-platform .NET 8 desktop application built with Avalonia. +It provides tag navigation, a searchable note list, Markdown editing, note +metadata, PDF embeds, and public-link publishing on Windows and macOS. ## Run -From PowerShell in the repository root: +From the repository root on Windows or macOS: -```powershell -dotnet run --project .\src\NoteManager.App\NoteManager.App.csproj +```bash +dotnet run --project src/NoteManager.Desktop/NoteManager.Desktop.csproj ``` The repository pins the .NET 8 SDK through `global.json`. On startup, the application recursively loads the Obsidian vault at: ```text -C:\Projects\Obsidian +SampleNotes ``` -Use **File → Open folder…** or `Ctrl+O` to switch to another Markdown folder. +Use **File → Open folder…**, `Ctrl+O` on Windows, or `Command+O` on macOS to +switch to another Markdown folder. For a dialog-free automated launch, inject the startup folder: -```powershell -dotnet run --project .\src\NoteManager.App\NoteManager.App.csproj -- --folder .\SampleNotes +```bash +dotnet run --project src/NoteManager.Desktop/NoteManager.Desktop.csproj -- \ + --folder SampleNotes ``` ## Automated regression tests -The primary UI regression lane uses -[FlaUI 5](https://github.com/FlaUI/FlaUI) with the UIA3 provider and -[NUnit 4](https://nunit.org/). It launches the real WPF executable and verifies -the application through Windows UI Automation, native dialogs, the clipboard, -filesystem outcomes, a loopback Infostacker fake, and initialized WebView2 PDF -surfaces. +The portable service and view-model suite runs on both operating systems: -Run all service and UI tests from an unlocked interactive Windows session: - -```powershell -.\tests\Run-AllTests.ps1 -Configuration Debug +```bash +dotnet test tests/NoteManager.App.Tests/NoteManager.App.Tests.csproj ``` -Run only the serialized UI suite, or filter it to one fixture: - -```powershell -.\tests\Run-UiTests.ps1 -Configuration Debug - -.\tests\Run-UiTests.ps1 ` - -Filter "FullyQualifiedName~TagAssignmentUiTests" -``` - -Every UI test creates a separate guarded vault below the user's temporary -folder. The data covers recursive folders, tagged and untagged notes, multiple -tag blocks, recent/all tag catalogs, Unicode and body-only searches, multiple -PDF embeds, filename collisions, publishing attachments, and a large indexing -set. The vault and its `.notes` database are removed after the scenario. - -The suite covers recursive loading and indexing; tag/search navigation; -create/delete and all automatic-save boundaries; folder switching during -background indexing; tag validation and block merging; public-link publishing -and clipboard output; multiple PDF viewers; and external-PDF copy, collision -rename, embed, save, and preview refresh. Failures attach a screen capture and -UI Automation tree below `artifacts\ui-tests`; runner `.trx` files are stored in -the same area. - -See -[`tests\NoteManager.App.UiTests\README.md`](tests/NoteManager.App.UiTests/README.md) -for the complete regression matrix, test-vault design, runner requirements, and -guidance for adding scenarios. +The former WPF/FlaUI suite remains under `tests/NoteManager.App.UiTests` as +migration reference, but is not part of the cross-platform solution build. ## Build the Windows installer -Inno Setup 6 or 7 can package a self-contained, startup-optimized Release build: +Inno Setup 6 or 7 can package a self-contained Avalonia Release build: ```powershell .\installer\build-installer.ps1 @@ -81,12 +53,18 @@ The finished artifact is written to: installer\Output\NoteManager-1.0.0-win-x64-Setup.exe ``` -Pass `-Version 1.2.0` to version a release. The publish enables composite -ReadyToRun and disables tiered compilation, trimming, and single-file extraction -to favor predictable WPF startup. See +Pass `-Version 1.2.0` to version a release. See [`installer\README.md`](installer/README.md) for prerequisites, ARM64 builds, and unattended installation. +On macOS: + +```bash +./installer/build-macos.sh 1.0.0 osx-arm64 +``` + +Use `osx-x64` for Intel Macs. + ## Included interactions - Recursively load every `.md` file from the selected folder and all subfolders. @@ -98,7 +76,10 @@ unattended installation. - Edit Markdown directly; dirty notes are saved atomically when selecting another note or view, changing folders, publishing, or closing the application. - Drag one or more PDF files onto a note row or the Markdown editor to insert Obsidian `![[...]]` embeds. PDFs dropped from outside the open folder are copied to its root and receive `(1)`, `(2)`, and later suffixes when names collide. - View each Obsidian PDF transclusion in an interactive Edge PDF viewer below the Markdown source. -- Use the PDF viewer's page navigation, scrolling, zoom, search, text selection, outline, print, save, and full-screen controls, or click **Open PDF** to use the default desktop application. +- Use the platform PDF viewer for scrolling, zooming, selection, printing, and + saving, or click **Open PDF** to use the default desktop application. Viewer + toolbar capabilities vary by operating system; PDF text-search parity is not + a migration requirement. - Click **Share** to open a public-link panel directly beneath the main toolbar button. Publishing sends the selected note and its embedded attachments to Infostacker, then copies the returned public URL to the clipboard. - Click **Create** (or press `Ctrl+N`) to create and select an empty `Untitled note.md` in the selected folder's root. Numbered names are used when needed. - Click **Delete**, then confirm the warning, to permanently remove the selected Markdown file from disk. @@ -148,7 +129,7 @@ criteria, and comprehensive implementation checklist are specified in UI tests can opt into a current-user-only named pipe and change the folder in the running application without invoking the native picker: ```powershell -dotnet run --project .\src\NoteManager.App\NoteManager.App.csproj -- ` +dotnet run --project .\src\NoteManager.Desktop\NoteManager.Desktop.csproj -- ` --folder .\SampleNotes ` --automation-pipe NoteManager.UiTest @@ -160,7 +141,7 @@ dotnet run --project .\src\NoteManager.App\NoteManager.App.csproj -- ` The pipe listener is disabled unless `--automation-pipe` is explicitly supplied. Both the injected startup path and runtime commands call the same `ChangeFolderAsync` path as the production folder picker. The FlaUI suite also uses an `import-pdf|` automation command. It is -available only when the opt-in pipe is enabled, is dispatched on the WPF UI +available only when the opt-in pipe is enabled, is dispatched on the Avalonia UI thread, and calls the same PDF import path as a real drop. This makes collision, copy, embed, save, and viewer assertions deterministic without synthetic mouse input. @@ -190,7 +171,7 @@ Following the [`taskscape/InfostackerPlugin`](https://github.com/taskscape/Infos 1. Reads the selected Markdown file and prefixes it with the filename without `.md`. 2. Resolves files referenced by Obsidian `![[...]]` embeds from the selected vault. 3. Sends a multipart `POST` to `https://shr.infostacker.com/sharing/uploadmarkdownwithfiles` using the `markdown` field and repeated `files` fields. -4. Reads the returned post `id`, constructs `https://shr.infostacker.com/sharing/{id}`, and copies it to the Windows clipboard. +4. Reads the returned post `id`, constructs `https://shr.infostacker.com/sharing/{id}`, and copies it to the platform clipboard. The request is made only after the user presses the publish button. The note and combined attachments are checked against the plugin's 100 MB limit before upload. An unreadable attachment is skipped, matching the plugin behavior, while an unavailable service or rejected request is reported inside the Share panel. @@ -268,19 +249,18 @@ These files contain synthetic business, research, invoice, receipt, parcel, and ## Project structure ```text +src/NoteManager.Core/ + NoteManager.Core.csproj platform-neutral models, services, and view model +src/NoteManager.Desktop/ + Controls/ Avalonia PDF viewer + Dialogs/ cross-platform tag and confirmation dialogs + MainWindow.axaml Avalonia three-pane desktop interface + Program.cs Windows/macOS application entry point src/NoteManager.App/ - Assets/ original synthetic PDF artwork - Controls/ note thumbnails and document preview UI - Infrastructure/ binding helpers and commands - Models/ tag-navigation and note models - Services/ Markdown loading, metadata/PDF parsing, SQLite FTS indexing, and sample generation - ViewModels/ folder loading, background indexing, full-text/tag filtering, and selection behavior - MainWindow.xaml high-fidelity three-pane interface + Legacy WPF UI retained as migration reference; not in the portable solution tests/ - NoteManager.App.Tests/ parser, editor, index, and PDF service tests - NoteManager.App.UiTests/ FlaUI/NUnit executable-level regression suite - Run-AllTests.ps1 serialized build, service, and UI entry point - Run-UiTests.ps1 focused UI runner with TRX and failure artifacts + NoteManager.App.Tests/ portable parser, editor, index, PDF, and view-model tests + NoteManager.App.UiTests/ legacy Windows-only FlaUI regression reference ``` Visual comparison evidence and the final design review are documented in `design-qa.md`. diff --git a/global.json b/global.json index 9471ab5..dbe1587 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.120", + "version": "8.0.423", "rollForward": "latestPatch", "allowPrerelease": false } diff --git a/installer/README.md b/installer/README.md index 8057475..49dd39b 100644 --- a/installer/README.md +++ b/installer/README.md @@ -1,19 +1,20 @@ # NoteManager Installer -This folder publishes the .NET 8 WPF application and packages the complete -publish output as an Inno Setup installer. +This folder packages the cross-platform .NET 8 Avalonia application for +Windows and macOS. ## Prerequisites - The .NET 8 SDK selected by the repository `global.json`. - Inno Setup 6 or 7. The script searches `PATH` and the standard 32-bit and 64-bit installation folders, or accepts an explicit `-IsccPath`. -- The Microsoft Edge WebView2 Evergreen Runtime on the target computer. It is - normally present on Windows 11; it can be obtained from the - [official WebView2 download page](https://developer.microsoft.com/microsoft-edge/webview2/). +- The platform web view used by Avalonia (WebView2 on Windows and WKWebView on + macOS) for embedded PDF display. ## Build +### Windows + From the repository root: ```powershell @@ -51,12 +52,27 @@ The build script favors cold startup over output size: - precompiles managed assemblies with ReadyToRun and composite ReadyToRun; - disables tiered compilation so startup does not wait for later JIT tiers; - keeps the application folder-based, avoiding single-file extraction at launch; -- disables trimming because WPF and WebView2 use runtime-discovered types; +- disables trimming because Avalonia and native web views use + runtime-discovered types; - omits debug symbols and creates a deterministic release build. The resulting installer is larger than a framework-dependent or trimmed build, but the target computer does not need a separately installed .NET runtime. +### macOS + +From macOS, build a self-contained application bundle for the current +architecture: + +```bash +./installer/build-macos.sh 1.0.0 osx-arm64 +``` + +Use `osx-x64` for Intel Macs. The application bundle is written to +`installer/Output/NoteManager--.app`. Set +`NOTEMANAGER_CODESIGN_IDENTITY` to sign the bundle during the build; otherwise +an ad-hoc signature is applied when `codesign` is available. + ## Install Run the generated setup executable. It installs NoteManager for all users under diff --git a/installer/build-installer.ps1 b/installer/build-installer.ps1 index 15552e3..493614e 100644 --- a/installer/build-installer.ps1 +++ b/installer/build-installer.ps1 @@ -3,7 +3,7 @@ Publishes NoteManager and builds an Inno Setup installer. .DESCRIPTION - Creates an optimized, self-contained Windows publish of the WPF application + Creates an optimized, self-contained Windows publish of the Avalonia application and compiles it into a versioned Inno Setup installer. Startup-oriented publish settings are enabled by default: @@ -51,7 +51,7 @@ $ErrorActionPreference = "Stop" $scriptDir = [System.IO.Path]::GetFullPath($PSScriptRoot) $repoRoot = [System.IO.Path]::GetFullPath((Join-Path $scriptDir "..")) -$projectPath = Join-Path $repoRoot "src\NoteManager.App\NoteManager.App.csproj" +$projectPath = Join-Path $repoRoot "src\NoteManager.Desktop\NoteManager.Desktop.csproj" $publishDir = Join-Path $scriptDir "publish" $outputDir = Join-Path $scriptDir "Output" $issFile = Join-Path $scriptDir "NoteManager.iss" diff --git a/installer/build-macos.sh b/installer/build-macos.sh new file mode 100755 index 0000000..e27eb3c --- /dev/null +++ b/installer/build-macos.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +set -euo pipefail + +version="${1:-1.0.0}" +runtime="${2:-osx-arm64}" + +case "$runtime" in + osx-arm64|osx-x64) ;; + *) + echo "Unsupported runtime '$runtime'. Use osx-arm64 or osx-x64." >&2 + exit 2 + ;; +esac + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repo_root="$(cd "$script_dir/.." && pwd)" +project="$repo_root/src/NoteManager.Desktop/NoteManager.Desktop.csproj" +publish_dir="$script_dir/publish-macos/$runtime" +app_dir="$script_dir/Output/NoteManager-$version-$runtime.app" +contents_dir="$app_dir/Contents" + +mkdir -p "$publish_dir" "$script_dir/Output" + +dotnet publish "$project" \ + --nologo \ + -c Release \ + -r "$runtime" \ + --self-contained true \ + -o "$publish_dir" \ + -p:Version="$version" \ + -p:UseAppHost=true \ + -p:PublishSingleFile=false \ + -p:PublishTrimmed=false \ + -p:DebugSymbols=false \ + -p:DebugType=None + +if [[ ! -x "$publish_dir/NoteManager" ]]; then + echo "Publish did not produce the NoteManager executable." >&2 + exit 1 +fi + +if [[ -e "$app_dir" ]]; then + echo "Output already exists: $app_dir" >&2 + echo "Move or remove it before rebuilding." >&2 + exit 1 +fi + +mkdir -p "$contents_dir/MacOS" "$contents_dir/Resources" +cp -R "$publish_dir/." "$contents_dir/MacOS/" +sed "s/__VERSION__/$version/g" \ + "$script_dir/macos/Info.plist" > "$contents_dir/Info.plist" + +if command -v codesign >/dev/null 2>&1; then + codesign --force --deep --sign \ + "${NOTEMANAGER_CODESIGN_IDENTITY:--}" "$app_dir" +fi + +echo "Application bundle created: $app_dir" diff --git a/installer/macos/Info.plist b/installer/macos/Info.plist new file mode 100644 index 0000000..da46784 --- /dev/null +++ b/installer/macos/Info.plist @@ -0,0 +1,29 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + NoteManager + CFBundleExecutable + NoteManager + CFBundleIdentifier + com.taskscape.notemanager + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + NoteManager + CFBundlePackageType + APPL + CFBundleShortVersionString + __VERSION__ + CFBundleVersion + __VERSION__ + LSMinimumSystemVersion + 12.0 + NSHighResolutionCapable + + + diff --git a/spikes/AvaloniaPdfSpike/App.axaml b/spikes/AvaloniaPdfSpike/App.axaml new file mode 100644 index 0000000..5de9a16 --- /dev/null +++ b/spikes/AvaloniaPdfSpike/App.axaml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/spikes/AvaloniaPdfSpike/App.axaml.cs b/spikes/AvaloniaPdfSpike/App.axaml.cs new file mode 100644 index 0000000..6deeabb --- /dev/null +++ b/spikes/AvaloniaPdfSpike/App.axaml.cs @@ -0,0 +1,23 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; + +namespace AvaloniaPdfSpike; + +public partial class App : Application +{ + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + desktop.MainWindow = new MainWindow(); + } + + base.OnFrameworkInitializationCompleted(); + } +} \ No newline at end of file diff --git a/spikes/AvaloniaPdfSpike/AvaloniaPdfSpike.csproj b/spikes/AvaloniaPdfSpike/AvaloniaPdfSpike.csproj new file mode 100644 index 0000000..b3b95c9 --- /dev/null +++ b/spikes/AvaloniaPdfSpike/AvaloniaPdfSpike.csproj @@ -0,0 +1,27 @@ + + + WinExe + net8.0 + enable + app.manifest + true + + + + + + + + + + None + All + + + + + + + diff --git a/spikes/AvaloniaPdfSpike/MainWindow.axaml b/spikes/AvaloniaPdfSpike/MainWindow.axaml new file mode 100644 index 0000000..4d8675f --- /dev/null +++ b/spikes/AvaloniaPdfSpike/MainWindow.axaml @@ -0,0 +1,64 @@ + + + + + + + + + +