advanced-calculator/docs/migration-plan.md

148 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Advanced Calculator Migration Plan
Migration target: .NET 4.7 WPF (src.4.7) → Avalonia on .NET 8 (src) with Desktop, Android, and Browser heads.
## Objectives
- Preserve existing features and UX while adopting MVVM and crossplatform patterns.
- Encapsulate the expression engine behind a service to isolate API differences.
- Maintain a single shared UI project for all heads; avoid platformspecific code.
## Repo Overview
- New solution (src):
- `AdvancedCalculator` (shared UI, Avalonia 11, net8.0)
- Heads: `AdvancedCalculator.Desktop` (net8.0), `AdvancedCalculator.Android` (net8.0-android), `AdvancedCalculator.Browser` (net8.0-browser)
- Uses `CommunityToolkit.Mvvm` and already references `CSMic.StandardLibrary`.
- Old project (src.4.7):
- WPF `MainWindow` with variables, function definitions panel, history, and input with Enter submit.
- Icons via Material Design Icons TTF + `IconFont.cs` glyph map.
- Models: `HistoryItem`, `VariableItem`, `FunctionDefinitonItem`.
- Interpreter: `csmic.InputInterpreter` in code-behind.
## High-Level Approach
1) Port models and static data to the shared project.
2) Wrap the interpreter in a service (`ICalculatorService`) that maintains state and exposes async APIs.
3) Move UI logic from code-behind to `MainViewModel` using commands and observable collections.
4) Recreate the WPF layout in Avalonia XAML (`MainView.axaml`), preserving behavior and styling.
5) Migrate icons/assets and wire up font usage across platforms.
6) Polish interactions (auto-scroll, focus, virtualization) and verify crossplatform.
## Mapping WPF → Avalonia
- Events → Commands:
- `txtInput_KeyDown` (Enter) → `SubmitCommand` with `KeyBinding` on the input `TextBox`.
- `btnFx_Click``ToggleFunctionsCommand`.
- Collections:
- `List<T>``ObservableCollection<T>` for `History` and `Variables`.
- Visibility:
- WPF `Visibility``bool` properties (`IsExpression`, `IsFunctionsPanelOpen`) bound to `IsVisible` or via a simple `BoolToGridLength`/`BoolToVisibility` converter.
- Icons:
- Keep `IconFont` glyphs and ship the TTF in `Assets/Fonts`, or reduce to the required subset.
- Scrolling:
- Use `ListBox`/`ListView` and set selected index to last; optionally call `ScrollIntoView` from code-behind or via behavior.
## Phased Plan
### Phase 1: Models and Service
- Add `Models` in `src/AdvancedCalculator`:
- `HistoryItem.cs` (copy shape from WPF)
- `VariableItem.cs` (replace `Visibility` with `bool IsExpression` and `string? ExpressionComputation`)
- `FunctionDefinitionItem.cs` (rename to fix spelling; copy `DefinedFunctions` static enumeration)
- Add `Services`:
- `ICalculatorService` with methods like:
- `Task<InterpretResult> InterpretAsync(string input)`
- `CalculatorService` that holds a persistent interpreter instance from `CSMic.StandardLibrary` and returns:
- Computed `Output`
- Current variables (name, value, type)
- For equation variables: compute and store `ExpressionComputation`
Notes:
- The service isolates any API delta between WPFs `csmic.InputInterpreter` and the current `CSMic.StandardLibrary`.
### Phase 2: ViewModel
- Expand `MainViewModel`:
- Properties: `InputText`, `IsFunctionsPanelOpen`, `ObservableCollection<HistoryItem> History`, `ObservableCollection<VariableItem> Variables`.
- Commands: `SubmitCommand`, `ToggleFunctionsCommand` using `RelayCommand`/`AsyncRelayCommand`.
- On submit: call `CalculatorService.InterpretAsync(InputText)`, append to `History`, rebuild `Variables`, clear `InputText`, and request UI scroll to last.
### Phase 3: UI Layout
- Update `Views/MainView.axaml` to mirror WPF layout:
- Grid with two columns; left hosts Variables (row 0) + Functions panel (row 1, height toggled), right hosts History (row 0) + input row (row 1).
- Add `GridSplitter` between columns.
- Bind `ItemsSource` for lists and set `DataTemplates` for item visuals (icon column + text stacks as in WPF XAML).
- Input row: toggle `Button` bound to `ToggleFunctionsCommand`; `TextBox` bound to `InputText` with `KeyBinding` Enter → `SubmitCommand`.
### Phase 4: Icons and Assets
- Copy `materialdesignicons-webfont.ttf` to `src/AdvancedCalculator/Assets/Fonts`.
- Update `AdvancedCalculator.csproj` to include the font as an `AvaloniaResource`.
- Reference the font in XAML via `FontFamily="avares://AdvancedCalculator/Assets/Fonts#Material Design Icons"`.
- Optionally copy a slimmed `IconFont.cs` (only used glyphs) and bind `TextBlock` to those glyph strings.
### Phase 5: Interaction Polish
- Auto-scroll History on submit (select last item or call `ScrollIntoView` in code-behind for `MainView`).
- Ensure lists use virtualization (default templates are virtualized; confirm template choice preserves it).
- Focus management: focus input `TextBox` after submit.
### Phase 6: Cross-Platform Verification
- Desktop: smoke test.
- Browser: ensure font loads correctly as an Avalonia resource; verify icons render and inputs submit with Enter.
- Android: verify IME enter (Done/Go) triggers submit; confirm font packaged and renders.
### Phase 7: Cleanup and Docs
- Remove placeholder greeting and unused templates.
- Update `README.md` with build/run instructions per target, plus basic usage.
- (Optional) Add a few unit tests for `CalculatorService` if practical without heavy harness.
## File-Level Checklist
- Add:
- `src/AdvancedCalculator/Models/HistoryItem.cs`
- `src/AdvancedCalculator/Models/VariableItem.cs`
- `src/AdvancedCalculator/Models/FunctionDefinitionItem.cs`
- `src/AdvancedCalculator/Services/ICalculatorService.cs`
- `src/AdvancedCalculator/Services/CalculatorService.cs`
- `src/AdvancedCalculator/Assets/Fonts/materialdesignicons-webfont.ttf`
- Update:
- `src/AdvancedCalculator/AdvancedCalculator.csproj` (Avalonia resources for Fonts)
- `src/AdvancedCalculator/ViewModels/MainViewModel.cs` (properties + commands)
- `src/AdvancedCalculator/Views/MainView.axaml` (+ optional code-behind for scroll/focus)
## Risks & Mitigations
- Interpreter API changes: contained by `CalculatorService`; adjust adapter logic without touching UI.
- Font payload size (Browser, Android): if large, switch to a reduced subset or alternate icon source.
- Visibility semantics: prefer `bool` bindings to `IsVisible` to avoid platform enums.
- WebAssembly resource loading: verify `avares://` URIs and that the font is included as a resource.
## Acceptance Criteria
- Entering an expression appends to History and updates Variables.
- Variables defined as equations show computed `ExpressionComputation` and a distinct icon.
- Function definitions panel toggles and displays static help list.
- Icons render on Desktop and Browser; Android renders acceptable icons.
- Solution builds and runs across Desktop, Browser, and Android heads.
## Timeline Estimate
- Phase 12 (Models, Service, VM): 0.51 day
- Phase 3 (UI layout and bindings): 11.5 days
- Phase 45 (Assets, polish): 0.5 day
- Phase 6 (Crossplatform checks): 0.51 day
- Total: ~2.54 days including docs and smoke tests
## Next Actions
1) Create `Models` and `Services` scaffolding in `AdvancedCalculator` and wire `MainViewModel`.
2) Port the XAML layout and data templates into `MainView.axaml`.
3) Add icon font resources and verify rendering on Desktop.
4) Smoke test on Browser and Android heads; adjust assets if needed.