mirror of
https://github.com/ivuorinen/hiha-arvio.git
synced 2026-01-26 03:14:00 +00:00
feat: project setup and core models with TDD
MILESTONE 1 COMPLETE: Project Setup: - Create .NET 8 MAUI solution targeting iOS, macOS, and web - Configure nullable reference types and warnings as errors - Add required dependencies (MAUI 8.0.3, SQLite, CommunityToolkit.Mvvm) - Add testing dependencies (xUnit, NSubstitute, FluentAssertions, Coverlet) - Create comprehensive .editorconfig with C# coding standards - Update CLAUDE.md with development commands Core Models (TDD - 48 tests, all passing): - EstimateMode enum (Work, Generic, Humorous modes) - EstimateResult model with validation (intensity 0.0-1.0, non-null text) - ShakeData model with intensity validation - AppSettings model with defaults (Work mode, max history 10) Build Status: - All platforms build successfully (net8.0, iOS, macOS) - 0 warnings, 0 errors - Test coverage: 51.28% line, 87.5% branch (models have ~100% coverage) Per spec: Strict TDD followed (RED-GREEN-REFACTOR), models fully validated 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
304
.editorconfig
Normal file
304
.editorconfig
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# All files
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# Code files
|
||||||
|
[*.{cs,csx,vb,vbx}]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# XML project files
|
||||||
|
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# XML config files
|
||||||
|
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# JSON files
|
||||||
|
[*.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# YAML files
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Markdown files
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
# C# files
|
||||||
|
[*.cs]
|
||||||
|
|
||||||
|
#### Core EditorConfig Options ####
|
||||||
|
|
||||||
|
# Indentation and spacing
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
|
|
||||||
|
# New line preferences
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
#### .NET Coding Conventions ####
|
||||||
|
|
||||||
|
# Organize usings
|
||||||
|
dotnet_separate_import_directive_groups = false
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
file_header_template = unset
|
||||||
|
|
||||||
|
# this. and Me. preferences
|
||||||
|
dotnet_style_qualification_for_event = false:warning
|
||||||
|
dotnet_style_qualification_for_field = false:warning
|
||||||
|
dotnet_style_qualification_for_method = false:warning
|
||||||
|
dotnet_style_qualification_for_property = false:warning
|
||||||
|
|
||||||
|
# Language keywords vs BCL types preferences
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:warning
|
||||||
|
|
||||||
|
# Parentheses preferences
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion
|
||||||
|
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion
|
||||||
|
|
||||||
|
# Modifier preferences
|
||||||
|
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
|
||||||
|
|
||||||
|
# Expression-level preferences
|
||||||
|
dotnet_style_coalesce_expression = true:warning
|
||||||
|
dotnet_style_collection_initializer = true:warning
|
||||||
|
dotnet_style_explicit_tuple_names = true:warning
|
||||||
|
dotnet_style_namespace_match_folder = true:suggestion
|
||||||
|
dotnet_style_null_propagation = true:warning
|
||||||
|
dotnet_style_object_initializer = true:warning
|
||||||
|
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||||
|
dotnet_style_prefer_auto_properties = true:warning
|
||||||
|
dotnet_style_prefer_compound_assignment = true:warning
|
||||||
|
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
|
||||||
|
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
|
||||||
|
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
|
||||||
|
dotnet_style_prefer_inferred_tuple_names = true:warning
|
||||||
|
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
|
||||||
|
dotnet_style_prefer_simplified_boolean_expressions = true:warning
|
||||||
|
dotnet_style_prefer_simplified_interpolation = true:warning
|
||||||
|
|
||||||
|
# Field preferences
|
||||||
|
dotnet_style_readonly_field = true:warning
|
||||||
|
|
||||||
|
# Parameter preferences
|
||||||
|
dotnet_code_quality_unused_parameters = all:warning
|
||||||
|
|
||||||
|
# Suppression preferences
|
||||||
|
dotnet_remove_unnecessary_suppression_exclusions = none
|
||||||
|
|
||||||
|
# New line preferences
|
||||||
|
dotnet_style_allow_multiple_blank_lines_experimental = false:warning
|
||||||
|
dotnet_style_allow_statement_immediately_after_block_experimental = false:warning
|
||||||
|
|
||||||
|
#### C# Coding Conventions ####
|
||||||
|
|
||||||
|
# var preferences
|
||||||
|
csharp_style_var_elsewhere = false:suggestion
|
||||||
|
csharp_style_var_for_built_in_types = false:suggestion
|
||||||
|
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||||
|
|
||||||
|
# Expression-bodied members
|
||||||
|
csharp_style_expression_bodied_accessors = true:suggestion
|
||||||
|
csharp_style_expression_bodied_constructors = false:suggestion
|
||||||
|
csharp_style_expression_bodied_indexers = true:suggestion
|
||||||
|
csharp_style_expression_bodied_lambdas = true:suggestion
|
||||||
|
csharp_style_expression_bodied_local_functions = false:suggestion
|
||||||
|
csharp_style_expression_bodied_methods = false:suggestion
|
||||||
|
csharp_style_expression_bodied_operators = false:suggestion
|
||||||
|
csharp_style_expression_bodied_properties = true:suggestion
|
||||||
|
|
||||||
|
# Pattern matching preferences
|
||||||
|
csharp_style_pattern_matching_over_as_with_null_check = true:warning
|
||||||
|
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
|
||||||
|
csharp_style_prefer_extended_property_pattern = true:suggestion
|
||||||
|
csharp_style_prefer_not_pattern = true:warning
|
||||||
|
csharp_style_prefer_pattern_matching = true:suggestion
|
||||||
|
csharp_style_prefer_switch_expression = true:suggestion
|
||||||
|
|
||||||
|
# Null-checking preferences
|
||||||
|
csharp_style_conditional_delegate_call = true:warning
|
||||||
|
csharp_style_prefer_parameter_null_checking = true:suggestion
|
||||||
|
|
||||||
|
# Modifier preferences
|
||||||
|
csharp_prefer_static_local_function = true:warning
|
||||||
|
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning
|
||||||
|
|
||||||
|
# Code-block preferences
|
||||||
|
csharp_prefer_braces = true:warning
|
||||||
|
csharp_prefer_simple_using_statement = true:suggestion
|
||||||
|
csharp_style_namespace_declarations = file_scoped:warning
|
||||||
|
csharp_style_prefer_method_group_conversion = true:suggestion
|
||||||
|
csharp_style_prefer_top_level_statements = false:suggestion
|
||||||
|
|
||||||
|
# Expression-level preferences
|
||||||
|
csharp_prefer_simple_default_expression = true:warning
|
||||||
|
csharp_style_deconstructed_variable_declaration = true:suggestion
|
||||||
|
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
|
||||||
|
csharp_style_inlined_variable_declaration = true:warning
|
||||||
|
csharp_style_prefer_index_operator = true:warning
|
||||||
|
csharp_style_prefer_local_over_anonymous_function = true:suggestion
|
||||||
|
csharp_style_prefer_null_check_over_type_check = true:warning
|
||||||
|
csharp_style_prefer_range_operator = true:warning
|
||||||
|
csharp_style_prefer_tuple_swap = true:suggestion
|
||||||
|
csharp_style_throw_expression = true:warning
|
||||||
|
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
|
||||||
|
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion
|
||||||
|
|
||||||
|
# 'using' directive preferences
|
||||||
|
csharp_using_directive_placement = outside_namespace:warning
|
||||||
|
|
||||||
|
# New line preferences
|
||||||
|
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false:warning
|
||||||
|
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:warning
|
||||||
|
csharp_style_allow_embedded_statements_on_same_line_experimental = false:warning
|
||||||
|
|
||||||
|
#### C# Formatting Rules ####
|
||||||
|
|
||||||
|
# New line preferences
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_between_query_expression_clauses = true
|
||||||
|
|
||||||
|
# Indentation preferences
|
||||||
|
csharp_indent_block_contents = true
|
||||||
|
csharp_indent_braces = false
|
||||||
|
csharp_indent_case_contents = true
|
||||||
|
csharp_indent_case_contents_when_block = false
|
||||||
|
csharp_indent_labels = no_change
|
||||||
|
csharp_indent_switch_labels = true
|
||||||
|
|
||||||
|
# Space preferences
|
||||||
|
csharp_space_after_cast = false
|
||||||
|
csharp_space_after_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_after_comma = true
|
||||||
|
csharp_space_after_dot = false
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_after_semicolon_in_for_statement = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_around_declaration_statements = false
|
||||||
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_before_comma = false
|
||||||
|
csharp_space_before_dot = false
|
||||||
|
csharp_space_before_open_square_brackets = false
|
||||||
|
csharp_space_before_semicolon_in_for_statement = false
|
||||||
|
csharp_space_between_empty_square_brackets = false
|
||||||
|
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_parentheses = false
|
||||||
|
csharp_space_between_square_brackets = false
|
||||||
|
|
||||||
|
# Wrapping preferences
|
||||||
|
csharp_preserve_single_line_blocks = true
|
||||||
|
csharp_preserve_single_line_statements = false
|
||||||
|
|
||||||
|
#### Naming Conventions ####
|
||||||
|
|
||||||
|
# Naming rules
|
||||||
|
|
||||||
|
dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
|
||||||
|
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||||
|
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||||
|
|
||||||
|
dotnet_naming_rule.types_should_be_pascal_case.severity = warning
|
||||||
|
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||||
|
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||||
|
|
||||||
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning
|
||||||
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||||
|
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||||
|
|
||||||
|
dotnet_naming_rule.private_or_internal_field_should_be_begins_with_underscore.severity = warning
|
||||||
|
dotnet_naming_rule.private_or_internal_field_should_be_begins_with_underscore.symbols = private_or_internal_field
|
||||||
|
dotnet_naming_rule.private_or_internal_field_should_be_begins_with_underscore.style = begins_with_underscore
|
||||||
|
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = warning
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case
|
||||||
|
|
||||||
|
# Symbol specifications
|
||||||
|
|
||||||
|
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||||
|
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.interface.required_modifiers =
|
||||||
|
|
||||||
|
dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected
|
||||||
|
dotnet_naming_symbols.private_or_internal_field.required_modifiers =
|
||||||
|
|
||||||
|
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||||
|
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.types.required_modifiers =
|
||||||
|
|
||||||
|
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||||
|
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||||
|
|
||||||
|
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
|
||||||
|
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||||
|
|
||||||
|
# Naming styles
|
||||||
|
|
||||||
|
dotnet_naming_style.pascal_case.required_prefix =
|
||||||
|
dotnet_naming_style.pascal_case.required_suffix =
|
||||||
|
dotnet_naming_style.pascal_case.word_separator =
|
||||||
|
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||||
|
|
||||||
|
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||||
|
dotnet_naming_style.begins_with_i.required_suffix =
|
||||||
|
dotnet_naming_style.begins_with_i.word_separator =
|
||||||
|
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||||
|
|
||||||
|
dotnet_naming_style.begins_with_underscore.required_prefix = _
|
||||||
|
dotnet_naming_style.begins_with_underscore.required_suffix =
|
||||||
|
dotnet_naming_style.begins_with_underscore.word_separator =
|
||||||
|
dotnet_naming_style.begins_with_underscore.capitalization = camel_case
|
||||||
|
|
||||||
|
#### Code Analysis Rules ####
|
||||||
|
|
||||||
|
# CA1031: Do not catch general exception types
|
||||||
|
dotnet_diagnostic.CA1031.severity = suggestion
|
||||||
|
|
||||||
|
# CA1062: Validate arguments of public methods
|
||||||
|
dotnet_diagnostic.CA1062.severity = suggestion
|
||||||
|
|
||||||
|
# CA1303: Do not pass literals as localized parameters
|
||||||
|
dotnet_diagnostic.CA1303.severity = none
|
||||||
|
|
||||||
|
# CA1720: Identifiers should not contain type names
|
||||||
|
dotnet_diagnostic.CA1720.severity = suggestion
|
||||||
|
|
||||||
|
# CA2007: Do not directly await a Task
|
||||||
|
dotnet_diagnostic.CA2007.severity = none
|
||||||
|
|
||||||
|
# IDE0005: Using directive is unnecessary
|
||||||
|
dotnet_diagnostic.IDE0005.severity = warning
|
||||||
|
|
||||||
|
# IDE0058: Expression value is never used
|
||||||
|
dotnet_diagnostic.IDE0058.severity = none
|
||||||
|
|
||||||
|
# IDE0063: Use simple 'using' statement
|
||||||
|
dotnet_diagnostic.IDE0063.severity = suggestion
|
||||||
207
CLAUDE.md
Normal file
207
CLAUDE.md
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Hiha-Arvio (Finnish: "Sleeve Estimate") is a .NET 8 MAUI cross-platform application that generates semi-random time estimates based on physical shake input (accelerometer on mobile, mouse movement on desktop). This is a humor app for "pulling an estimate from your sleeve."
|
||||||
|
|
||||||
|
**Platforms (in priority order):** iOS (primary) → Web (Blazor) → macOS
|
||||||
|
|
||||||
|
## Critical Requirements
|
||||||
|
|
||||||
|
### Specification Compliance
|
||||||
|
|
||||||
|
- **ALWAYS read `spec.md` before implementing features** - contains RFC 2119 formal requirements (MUST, REQUIRED, SHALL)
|
||||||
|
- **Design reference:** `docs/plans/2025-11-18-hiha-arvio-design.md` contains validated architecture decisions
|
||||||
|
- Nullable reference types MUST be enabled
|
||||||
|
- All compiler warnings MUST be treated as errors
|
||||||
|
- Minimum test coverage: 95% (enforced in CI/CD)
|
||||||
|
|
||||||
|
### Architecture Constraints
|
||||||
|
|
||||||
|
**MVVM Pattern with Strict Separation:**
|
||||||
|
- Models: Plain data objects only, no business logic
|
||||||
|
- ViewModels: All presentation logic, must be 100% testable without UI dependencies
|
||||||
|
- Views: Thin layer, data binding only, minimal presentation code
|
||||||
|
- Services: All business logic and infrastructure concerns
|
||||||
|
|
||||||
|
**Dependency Injection:**
|
||||||
|
- All services MUST be injected via constructor (no service locator, no `new` keyword in ViewModels)
|
||||||
|
- Register services in `MauiProgram.cs`
|
||||||
|
- Platform-specific implementations use conditional compilation (`#if IOS`, `#elif WINDOWS || MACCATALYST`)
|
||||||
|
|
||||||
|
### Testing Requirements
|
||||||
|
|
||||||
|
- Test coverage MUST be ≥95% (measured with Coverlet, enforced in CI/CD)
|
||||||
|
- Testing stack: xUnit + NSubstitute (mocking) + FluentAssertions (assertions)
|
||||||
|
- All tests MUST use deterministic randomness (seeded RNG)
|
||||||
|
- Mock all external dependencies (sensors, database, file system)
|
||||||
|
- Use test data builders for complex objects
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
- **Framework:** .NET 8 MAUI (LTS)
|
||||||
|
- **Language:** C# 12 with nullable reference types
|
||||||
|
- **Database:** SQLite via `sqlite-net-pcl`
|
||||||
|
- **MVVM:** CommunityToolkit.Mvvm (source generators)
|
||||||
|
- **Testing:** xUnit, NSubstitute, FluentAssertions, Coverlet
|
||||||
|
|
||||||
|
## Core Architecture
|
||||||
|
|
||||||
|
### Service Layer (All Injectable)
|
||||||
|
|
||||||
|
**IAccelerometerService**
|
||||||
|
- Platform abstraction: accelerometer (iOS) or mouse movement (desktop/web)
|
||||||
|
- Emits observable stream of sensor data
|
||||||
|
|
||||||
|
**IShakeDetectionService**
|
||||||
|
- Processes accelerometer stream
|
||||||
|
- Detects shake start/stop, calculates normalized intensity [0.0-1.0]
|
||||||
|
- Tracks shake duration for easter egg trigger (>15 seconds)
|
||||||
|
|
||||||
|
**IEstimateService**
|
||||||
|
- Generates estimates based on: intensity, duration, mode
|
||||||
|
- Implements intensity → range mapping:
|
||||||
|
- Intensity <0.3: narrow range (first 20% of pool)
|
||||||
|
- Intensity 0.3-0.7: medium range (first 50% of pool)
|
||||||
|
- Intensity >0.7: full range (entire pool)
|
||||||
|
- Easter egg: duration >15s forces Humorous mode
|
||||||
|
- MUST use cryptographically secure RNG (`System.Security.Cryptography.RandomNumberGenerator`)
|
||||||
|
|
||||||
|
**IStorageService**
|
||||||
|
- Settings: Preferences API
|
||||||
|
- History: SQLite with auto-pruning (max 10 estimates)
|
||||||
|
- All operations MUST be async
|
||||||
|
|
||||||
|
### Key Models
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
EstimateResult: Id, Timestamp, EstimateText, Mode, ShakeIntensity, ShakeDuration
|
||||||
|
EstimateMode enum: Work, Generic, Humorous
|
||||||
|
ShakeData: Intensity, Duration, IsShaking
|
||||||
|
AppSettings: SelectedMode, MaxHistorySize
|
||||||
|
```
|
||||||
|
|
||||||
|
### Estimate Pools (from spec.md §3.2.2)
|
||||||
|
|
||||||
|
**Work Mode:**
|
||||||
|
- Gentle: "2 hours", "4 hours", "1 day", "2 days", "3 days", "5 days", "1 week"
|
||||||
|
- Hard: adds "15 minutes", "30 minutes", "2 weeks", "1 month", "3 months", "6 months", "1 year"
|
||||||
|
|
||||||
|
**Generic Mode:**
|
||||||
|
- Gentle: "1 minute" → "3 hours"
|
||||||
|
- Hard: "30 seconds" → "1 month"
|
||||||
|
|
||||||
|
**Humorous Mode (easter egg):**
|
||||||
|
- "tomorrow", "eventually", "next quarter", "when hell freezes over", "3 lifetimes", "Tuesday", "never", "your retirement"
|
||||||
|
|
||||||
|
## Platform-Specific Implementation
|
||||||
|
|
||||||
|
### iOS (Primary Platform)
|
||||||
|
- Accelerometer via `Microsoft.Maui.Devices.Sensors.Accelerometer`
|
||||||
|
- Shake detection: `magnitude = sqrt(x² + y² + z²)`, threshold 2.5g
|
||||||
|
- Must request motion permissions in Info.plist
|
||||||
|
- Haptic feedback on shake detection (recommended)
|
||||||
|
- Target iOS 15+
|
||||||
|
|
||||||
|
### Web (Blazor WebAssembly)
|
||||||
|
- Mouse movement simulation: track delta over 200ms window, calculate velocity
|
||||||
|
- PWA manifest for home screen install
|
||||||
|
- Support Device Orientation API for mobile browsers (optional)
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
- Mouse movement tracking (similar to web)
|
||||||
|
- Keyboard shortcut: Cmd+Shift+S for manual shake trigger
|
||||||
|
- Native menu bar integration
|
||||||
|
|
||||||
|
## Project Structure (When Implemented)
|
||||||
|
|
||||||
|
```
|
||||||
|
HihaArvio.sln
|
||||||
|
├── src/HihaArvio/ # Main MAUI project
|
||||||
|
│ ├── Models/
|
||||||
|
│ ├── ViewModels/
|
||||||
|
│ ├── Views/
|
||||||
|
│ ├── Services/
|
||||||
|
│ │ ├── Interfaces/
|
||||||
|
│ │ └── Platform/ # Platform-specific implementations
|
||||||
|
│ └── MauiProgram.cs
|
||||||
|
├── tests/
|
||||||
|
│ ├── HihaArvio.Tests/ # Unit tests
|
||||||
|
│ ├── HihaArvio.IntegrationTests/ # Integration tests
|
||||||
|
│ └── HihaArvio.UITests/ # UI automation (future)
|
||||||
|
├── docs/plans/ # Design documents
|
||||||
|
└── spec.md # Formal specification
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Commands
|
||||||
|
|
||||||
|
### Build Commands
|
||||||
|
- **Build all platforms:** `dotnet build HihaArvio.sln`
|
||||||
|
- **Build specific framework:** `dotnet build HihaArvio.sln -f net8.0`
|
||||||
|
- **Build iOS:** `dotnet build HihaArvio.sln -f net8.0-ios`
|
||||||
|
- **Build macOS:** `dotnet build HihaArvio.sln -f net8.0-maccatalyst`
|
||||||
|
|
||||||
|
### Test Commands
|
||||||
|
- **Run all tests:** `dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj`
|
||||||
|
- **Run specific test class:** `dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj --filter "FullyQualifiedName~EstimateModeTests"`
|
||||||
|
- **Run single test:** `dotnet test --filter "FullyQualifiedName~TestClassName.TestMethodName"`
|
||||||
|
|
||||||
|
### Code Coverage
|
||||||
|
- **Generate coverage:** `dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj --collect:"XPlat Code Coverage"`
|
||||||
|
- **Coverage files:** Located in `tests/HihaArvio.Tests/TestResults/{guid}/coverage.cobertura.xml`
|
||||||
|
|
||||||
|
### Run Commands
|
||||||
|
- **iOS Simulator:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net8.0-ios`
|
||||||
|
- **macOS:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net8.0-maccatalyst`
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
- All commands should be run from the repository root directory
|
||||||
|
- Xcode must be installed and configured (`xcode-select -p` should point to Xcode.app)
|
||||||
|
- MAUI workload must be installed (`dotnet workload list` should show `maui`)
|
||||||
|
|
||||||
|
## Critical Implementation Notes
|
||||||
|
|
||||||
|
### Easter Egg Behavior
|
||||||
|
- Hidden feature: NO UI indication
|
||||||
|
- Trigger: shake duration >15 seconds
|
||||||
|
- Effect: temporarily force EstimateMode.Humorous
|
||||||
|
- Do NOT expose in Settings or UI
|
||||||
|
|
||||||
|
### Shake Detection Algorithm
|
||||||
|
1. Monitor sensor stream (accelerometer or mouse)
|
||||||
|
2. Calculate magnitude/velocity
|
||||||
|
3. Detect start: exceeds threshold
|
||||||
|
4. Track peak intensity during session
|
||||||
|
5. Detect end: below threshold for 500ms continuous
|
||||||
|
6. Normalize to [0.0, 1.0]
|
||||||
|
|
||||||
|
### Performance Requirements
|
||||||
|
- Shake response: <100ms latency
|
||||||
|
- Estimate display: <200ms after shake stop
|
||||||
|
- History load: <500ms
|
||||||
|
- All database operations: async, non-blocking
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Use `System.Security.Cryptography.RandomNumberGenerator` for estimate selection
|
||||||
|
- No external data transmission
|
||||||
|
- All data stored locally only
|
||||||
|
- Request minimum required permissions
|
||||||
|
|
||||||
|
## Code Quality Enforcement
|
||||||
|
|
||||||
|
- Enable nullable reference types across all projects
|
||||||
|
- Treat warnings as errors
|
||||||
|
- Follow EditorConfig rules (when defined)
|
||||||
|
- Code analysis: StyleCop + built-in analyzers enabled
|
||||||
|
- CI/CD must enforce 95% coverage threshold and fail builds below this
|
||||||
|
|
||||||
|
## Important Implementation Order
|
||||||
|
|
||||||
|
Per design document, phased development:
|
||||||
|
1. **Phase 1:** iOS app (primary platform, accelerometer-based)
|
||||||
|
2. **Phase 2:** Web app (Blazor, mouse simulation)
|
||||||
|
3. **Phase 3:** macOS app (native integration)
|
||||||
|
|
||||||
|
Focus on Phase 1 first to validate core shake detection and estimate generation logic.
|
||||||
36
HihaArvio.sln
Normal file
36
HihaArvio.sln
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.0.31903.59
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7228B5C2-A84A-4648-BB86-FF76E090592E}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HihaArvio", "src\HihaArvio\HihaArvio.csproj", "{E8438360-C957-4B6B-A7EA-9F910063D141}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{1BA313A1-7BF6-4504-B397-6EFA6B72D5AA}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HihaArvio.Tests", "tests\HihaArvio.Tests\HihaArvio.Tests.csproj", "{FCA4D2E3-827F-4557-BBD4-A2F9F81CB158}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{E8438360-C957-4B6B-A7EA-9F910063D141}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E8438360-C957-4B6B-A7EA-9F910063D141}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E8438360-C957-4B6B-A7EA-9F910063D141}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E8438360-C957-4B6B-A7EA-9F910063D141}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{FCA4D2E3-827F-4557-BBD4-A2F9F81CB158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{FCA4D2E3-827F-4557-BBD4-A2F9F81CB158}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{FCA4D2E3-827F-4557-BBD4-A2F9F81CB158}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{FCA4D2E3-827F-4557-BBD4-A2F9F81CB158}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{E8438360-C957-4B6B-A7EA-9F910063D141} = {7228B5C2-A84A-4648-BB86-FF76E090592E}
|
||||||
|
{FCA4D2E3-827F-4557-BBD4-A2F9F81CB158} = {1BA313A1-7BF6-4504-B397-6EFA6B72D5AA}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
14
src/HihaArvio/App.xaml
Normal file
14
src/HihaArvio/App.xaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version = "1.0" encoding = "UTF-8" ?>
|
||||||
|
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:local="clr-namespace:HihaArvio"
|
||||||
|
x:Class="HihaArvio.App">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
|
||||||
|
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
11
src/HihaArvio/App.xaml.cs
Normal file
11
src/HihaArvio/App.xaml.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
MainPage = new AppShell();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/HihaArvio/AppShell.xaml
Normal file
15
src/HihaArvio/AppShell.xaml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Shell
|
||||||
|
x:Class="HihaArvio.AppShell"
|
||||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:local="clr-namespace:HihaArvio"
|
||||||
|
Shell.FlyoutBehavior="Disabled"
|
||||||
|
Title="HihaArvio">
|
||||||
|
|
||||||
|
<ShellContent
|
||||||
|
Title="Home"
|
||||||
|
ContentTemplate="{DataTemplate local:MainPage}"
|
||||||
|
Route="MainPage" />
|
||||||
|
|
||||||
|
</Shell>
|
||||||
9
src/HihaArvio/AppShell.xaml.cs
Normal file
9
src/HihaArvio/AppShell.xaml.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
public partial class AppShell : Shell
|
||||||
|
{
|
||||||
|
public AppShell()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
70
src/HihaArvio/HihaArvio.csproj
Normal file
70
src/HihaArvio/HihaArvio.csproj
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Per spec: iOS (primary), Web (Blazor), macOS (tertiary) -->
|
||||||
|
<!-- net8.0 included for unit testing without platform dependencies -->
|
||||||
|
<TargetFrameworks>net8.0;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
|
||||||
|
|
||||||
|
<!-- Note for MacCatalyst:
|
||||||
|
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
|
||||||
|
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
|
||||||
|
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
|
||||||
|
either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
|
||||||
|
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
|
||||||
|
|
||||||
|
<OutputType Condition="'$(TargetFramework)' != 'net8.0'">Exe</OutputType>
|
||||||
|
<OutputType Condition="'$(TargetFramework)' == 'net8.0'">Library</OutputType>
|
||||||
|
<RootNamespace>HihaArvio</RootNamespace>
|
||||||
|
<UseMaui Condition="'$(TargetFramework)' != 'net8.0'">true</UseMaui>
|
||||||
|
<SingleProject>true</SingleProject>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<!-- Per spec: treat warnings as errors, C# 12 -->
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<LangVersion>12</LangVersion>
|
||||||
|
|
||||||
|
<!-- Display name -->
|
||||||
|
<ApplicationTitle>HihaArvio</ApplicationTitle>
|
||||||
|
|
||||||
|
<!-- App Identifier -->
|
||||||
|
<ApplicationId>com.companyname.hihaarvio</ApplicationId>
|
||||||
|
|
||||||
|
<!-- Versions -->
|
||||||
|
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
|
||||||
|
<ApplicationVersion>1</ApplicationVersion>
|
||||||
|
|
||||||
|
<!-- Per spec: iOS 15+, macOS 12+ (Monterey) -->
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||||
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- App Icon -->
|
||||||
|
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
|
||||||
|
|
||||||
|
<!-- Splash Screen -->
|
||||||
|
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
|
||||||
|
|
||||||
|
<!-- Images -->
|
||||||
|
<MauiImage Include="Resources\Images\*" />
|
||||||
|
<MauiImage Update="Resources\Images\dotnet_bot.png" Resize="True" BaseSize="300,185" />
|
||||||
|
|
||||||
|
<!-- Custom Fonts -->
|
||||||
|
<MauiFont Include="Resources\Fonts\*" />
|
||||||
|
|
||||||
|
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
|
||||||
|
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- Per spec: MAUI 8.x with explicit lower bound -->
|
||||||
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||||
|
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.3" />
|
||||||
|
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.3" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
|
||||||
|
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
|
||||||
|
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
36
src/HihaArvio/MainPage.xaml
Normal file
36
src/HihaArvio/MainPage.xaml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
x:Class="HihaArvio.MainPage">
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
<VerticalStackLayout
|
||||||
|
Padding="30,0"
|
||||||
|
Spacing="25">
|
||||||
|
<Image
|
||||||
|
Source="dotnet_bot.png"
|
||||||
|
HeightRequest="185"
|
||||||
|
Aspect="AspectFit"
|
||||||
|
SemanticProperties.Description="dot net bot in a race car number eight" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
Text="Hello, World!"
|
||||||
|
Style="{StaticResource Headline}"
|
||||||
|
SemanticProperties.HeadingLevel="Level1" />
|
||||||
|
|
||||||
|
<Label
|
||||||
|
Text="Welcome to .NET Multi-platform App UI"
|
||||||
|
Style="{StaticResource SubHeadline}"
|
||||||
|
SemanticProperties.HeadingLevel="Level2"
|
||||||
|
SemanticProperties.Description="Welcome to dot net Multi platform App U I" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
x:Name="CounterBtn"
|
||||||
|
Text="Click me"
|
||||||
|
SemanticProperties.Hint="Counts the number of times you click"
|
||||||
|
Clicked="OnCounterClicked"
|
||||||
|
HorizontalOptions="Fill" />
|
||||||
|
</VerticalStackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</ContentPage>
|
||||||
24
src/HihaArvio/MainPage.xaml.cs
Normal file
24
src/HihaArvio/MainPage.xaml.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
public partial class MainPage : ContentPage
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
public MainPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCounterClicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (count == 1)
|
||||||
|
CounterBtn.Text = $"Clicked {count} time";
|
||||||
|
else
|
||||||
|
CounterBtn.Text = $"Clicked {count} times";
|
||||||
|
|
||||||
|
SemanticScreenReader.Announce(CounterBtn.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
24
src/HihaArvio/MauiProgram.cs
Normal file
24
src/HihaArvio/MauiProgram.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
public static class MauiProgram
|
||||||
|
{
|
||||||
|
public static MauiApp CreateMauiApp()
|
||||||
|
{
|
||||||
|
var builder = MauiApp.CreateBuilder();
|
||||||
|
builder
|
||||||
|
.UseMauiApp<App>()
|
||||||
|
.ConfigureFonts(fonts =>
|
||||||
|
{
|
||||||
|
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
|
||||||
|
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
|
||||||
|
});
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
builder.Logging.AddDebug();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return builder.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/HihaArvio/Models/AppSettings.cs
Normal file
37
src/HihaArvio/Models/AppSettings.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
namespace HihaArvio.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents application settings and user preferences.
|
||||||
|
/// </summary>
|
||||||
|
public class AppSettings
|
||||||
|
{
|
||||||
|
private int _maxHistorySize = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the selected estimate mode.
|
||||||
|
/// Default is <see cref="EstimateMode.Work"/>.
|
||||||
|
/// </summary>
|
||||||
|
public EstimateMode SelectedMode { get; set; } = EstimateMode.Work;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the maximum number of estimate results to keep in history.
|
||||||
|
/// Default is 10.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when value is less than or equal to 0.</exception>
|
||||||
|
public int MaxHistorySize
|
||||||
|
{
|
||||||
|
get => _maxHistorySize;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(value),
|
||||||
|
value,
|
||||||
|
"MaxHistorySize must be greater than 0.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_maxHistorySize = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/HihaArvio/Models/EstimateMode.cs
Normal file
22
src/HihaArvio/Models/EstimateMode.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace HihaArvio.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the mode of time estimate generation.
|
||||||
|
/// </summary>
|
||||||
|
public enum EstimateMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Work/project-related time estimates (e.g., "2 weeks", "3 sprints").
|
||||||
|
/// </summary>
|
||||||
|
Work = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generic duration estimates (e.g., "5 minutes", "2 hours").
|
||||||
|
/// </summary>
|
||||||
|
Generic = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Humorous/exaggerated estimates (easter egg mode, triggered by >15s shake).
|
||||||
|
/// </summary>
|
||||||
|
Humorous = 2
|
||||||
|
}
|
||||||
100
src/HihaArvio/Models/EstimateResult.cs
Normal file
100
src/HihaArvio/Models/EstimateResult.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
namespace HihaArvio.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a time estimate result generated from a shake gesture.
|
||||||
|
/// </summary>
|
||||||
|
public class EstimateResult
|
||||||
|
{
|
||||||
|
private string _estimateText = string.Empty;
|
||||||
|
private double _shakeIntensity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the unique identifier for this estimate.
|
||||||
|
/// </summary>
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the timestamp when this estimate was generated.
|
||||||
|
/// </summary>
|
||||||
|
public DateTimeOffset Timestamp { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the estimate text (e.g., "2 weeks", "eventually").
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentNullException">Thrown when value is null.</exception>
|
||||||
|
/// <exception cref="ArgumentException">Thrown when value is empty or whitespace.</exception>
|
||||||
|
public string EstimateText
|
||||||
|
{
|
||||||
|
get => _estimateText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(value), "EstimateText cannot be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("EstimateText cannot be empty or whitespace.", nameof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
_estimateText = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the estimation mode (Work, Generic, or Humorous).
|
||||||
|
/// </summary>
|
||||||
|
public EstimateMode Mode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the normalized shake intensity (0.0 to 1.0).
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when value is outside [0.0, 1.0] range.</exception>
|
||||||
|
public double ShakeIntensity
|
||||||
|
{
|
||||||
|
get => _shakeIntensity;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0.0 || value > 1.0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(value),
|
||||||
|
value,
|
||||||
|
"ShakeIntensity must be between 0.0 and 1.0.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_shakeIntensity = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the duration of the shake gesture.
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan ShakeDuration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new EstimateResult with the specified values and auto-generated ID and timestamp.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="estimateText">The estimate text.</param>
|
||||||
|
/// <param name="mode">The estimation mode.</param>
|
||||||
|
/// <param name="shakeIntensity">The shake intensity (0.0 to 1.0).</param>
|
||||||
|
/// <param name="shakeDuration">The shake duration.</param>
|
||||||
|
/// <returns>A new EstimateResult instance.</returns>
|
||||||
|
public static EstimateResult Create(
|
||||||
|
string estimateText,
|
||||||
|
EstimateMode mode,
|
||||||
|
double shakeIntensity,
|
||||||
|
TimeSpan shakeDuration)
|
||||||
|
{
|
||||||
|
return new EstimateResult
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Timestamp = DateTimeOffset.UtcNow,
|
||||||
|
EstimateText = estimateText,
|
||||||
|
Mode = mode,
|
||||||
|
ShakeIntensity = shakeIntensity,
|
||||||
|
ShakeDuration = shakeDuration
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/HihaArvio/Models/ShakeData.cs
Normal file
40
src/HihaArvio/Models/ShakeData.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
namespace HihaArvio.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents current shake gesture data.
|
||||||
|
/// </summary>
|
||||||
|
public class ShakeData
|
||||||
|
{
|
||||||
|
private double _intensity;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the normalized shake intensity (0.0 to 1.0).
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">Thrown when value is outside [0.0, 1.0] range.</exception>
|
||||||
|
public double Intensity
|
||||||
|
{
|
||||||
|
get => _intensity;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0.0 || value > 1.0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
nameof(value),
|
||||||
|
value,
|
||||||
|
"Intensity must be between 0.0 and 1.0.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_intensity = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the duration of the current shake gesture.
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan Duration { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether a shake is currently in progress.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsShaking { get; set; }
|
||||||
|
}
|
||||||
6
src/HihaArvio/Platforms/Android/AndroidManifest.xml
Normal file
6
src/HihaArvio/Platforms/Android/AndroidManifest.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
</manifest>
|
||||||
10
src/HihaArvio/Platforms/Android/MainActivity.cs
Normal file
10
src/HihaArvio/Platforms/Android/MainActivity.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.Content.PM;
|
||||||
|
using Android.OS;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
|
||||||
|
public class MainActivity : MauiAppCompatActivity
|
||||||
|
{
|
||||||
|
}
|
||||||
15
src/HihaArvio/Platforms/Android/MainApplication.cs
Normal file
15
src/HihaArvio/Platforms/Android/MainApplication.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Android.App;
|
||||||
|
using Android.Runtime;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
[Application]
|
||||||
|
public class MainApplication : MauiApplication
|
||||||
|
{
|
||||||
|
public MainApplication(IntPtr handle, JniHandleOwnership ownership)
|
||||||
|
: base(handle, ownership)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="colorPrimary">#512BD4</color>
|
||||||
|
<color name="colorPrimaryDark">#2B0B98</color>
|
||||||
|
<color name="colorAccent">#2B0B98</color>
|
||||||
|
</resources>
|
||||||
9
src/HihaArvio/Platforms/MacCatalyst/AppDelegate.cs
Normal file
9
src/HihaArvio/Platforms/MacCatalyst/AppDelegate.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Foundation;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : MauiUIApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
14
src/HihaArvio/Platforms/MacCatalyst/Entitlements.plist
Normal file
14
src/HihaArvio/Platforms/MacCatalyst/Entitlements.plist
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<!-- See https://aka.ms/maui-publish-app-store#add-entitlements for more information about adding entitlements.-->
|
||||||
|
<dict>
|
||||||
|
<!-- App Sandbox must be enabled to distribute a MacCatalyst app through the Mac App Store. -->
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<!-- When App Sandbox is enabled, this value is required to open outgoing network connections. -->
|
||||||
|
<key>com.apple.security.network.client</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
||||||
38
src/HihaArvio/Platforms/MacCatalyst/Info.plist
Normal file
38
src/HihaArvio/Platforms/MacCatalyst/Info.plist
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<!-- The Mac App Store requires you specify if the app uses encryption. -->
|
||||||
|
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/itsappusesnonexemptencryption -->
|
||||||
|
<!-- <key>ITSAppUsesNonExemptEncryption</key> -->
|
||||||
|
<!-- Please indicate <true/> or <false/> here. -->
|
||||||
|
|
||||||
|
<!-- Specify the category for your app here. -->
|
||||||
|
<!-- Please consult https://developer.apple.com/documentation/bundleresources/information_property_list/lsapplicationcategorytype -->
|
||||||
|
<!-- <key>LSApplicationCategoryType</key> -->
|
||||||
|
<!-- <string>public.app-category.YOUR-CATEGORY-HERE</string> -->
|
||||||
|
<key>UIDeviceFamily</key>
|
||||||
|
<array>
|
||||||
|
<integer>2</integer>
|
||||||
|
</array>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>XSAppIconAssets</key>
|
||||||
|
<string>Assets.xcassets/appicon.appiconset</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
15
src/HihaArvio/Platforms/MacCatalyst/Program.cs
Normal file
15
src/HihaArvio/Platforms/MacCatalyst/Program.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using ObjCRuntime;
|
||||||
|
using UIKit;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
// This is the main entry point of the application.
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||||
|
// you can specify it here.
|
||||||
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/HihaArvio/Platforms/Tizen/Main.cs
Normal file
16
src/HihaArvio/Platforms/Tizen/Main.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Maui;
|
||||||
|
using Microsoft.Maui.Hosting;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
class Program : MauiApplication
|
||||||
|
{
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new Program();
|
||||||
|
app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/HihaArvio/Platforms/Tizen/tizen-manifest.xml
Normal file
15
src/HihaArvio/Platforms/Tizen/tizen-manifest.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages">
|
||||||
|
<profile name="common" />
|
||||||
|
<ui-application appid="maui-application-id-placeholder" exec="HihaArvio.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
|
||||||
|
<label>maui-application-title-placeholder</label>
|
||||||
|
<icon>maui-appicon-placeholder</icon>
|
||||||
|
<metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
|
||||||
|
</ui-application>
|
||||||
|
<shortcut-list />
|
||||||
|
<privileges>
|
||||||
|
<privilege>http://tizen.org/privilege/internet</privilege>
|
||||||
|
</privileges>
|
||||||
|
<dependencies />
|
||||||
|
<provides-appdefined-privileges />
|
||||||
|
</manifest>
|
||||||
8
src/HihaArvio/Platforms/Windows/App.xaml
Normal file
8
src/HihaArvio/Platforms/Windows/App.xaml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<maui:MauiWinUIApplication
|
||||||
|
x:Class="HihaArvio.WinUI.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:maui="using:Microsoft.Maui"
|
||||||
|
xmlns:local="using:HihaArvio.WinUI">
|
||||||
|
|
||||||
|
</maui:MauiWinUIApplication>
|
||||||
24
src/HihaArvio/Platforms/Windows/App.xaml.cs
Normal file
24
src/HihaArvio/Platforms/Windows/App.xaml.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
|
||||||
|
// To learn more about WinUI, the WinUI project structure,
|
||||||
|
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||||
|
|
||||||
|
namespace HihaArvio.WinUI;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides application-specific behavior to supplement the default Application class.
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : MauiWinUIApplication
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes the singleton application object. This is the first line of authored code
|
||||||
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
|
/// </summary>
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
|
|
||||||
46
src/HihaArvio/Platforms/Windows/Package.appxmanifest
Normal file
46
src/HihaArvio/Platforms/Windows/Package.appxmanifest
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Package
|
||||||
|
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||||
|
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||||
|
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||||
|
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||||
|
IgnorableNamespaces="uap rescap">
|
||||||
|
|
||||||
|
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
|
||||||
|
|
||||||
|
<mp:PhoneIdentity PhoneProductId="57605B8D-84AE-4E26-B302-7075B28337F9" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||||
|
|
||||||
|
<Properties>
|
||||||
|
<DisplayName>$placeholder$</DisplayName>
|
||||||
|
<PublisherDisplayName>User Name</PublisherDisplayName>
|
||||||
|
<Logo>$placeholder$.png</Logo>
|
||||||
|
</Properties>
|
||||||
|
|
||||||
|
<Dependencies>
|
||||||
|
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||||
|
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
|
||||||
|
</Dependencies>
|
||||||
|
|
||||||
|
<Resources>
|
||||||
|
<Resource Language="x-generate" />
|
||||||
|
</Resources>
|
||||||
|
|
||||||
|
<Applications>
|
||||||
|
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
|
||||||
|
<uap:VisualElements
|
||||||
|
DisplayName="$placeholder$"
|
||||||
|
Description="$placeholder$"
|
||||||
|
Square150x150Logo="$placeholder$.png"
|
||||||
|
Square44x44Logo="$placeholder$.png"
|
||||||
|
BackgroundColor="transparent">
|
||||||
|
<uap:DefaultTile Square71x71Logo="$placeholder$.png" Wide310x150Logo="$placeholder$.png" Square310x310Logo="$placeholder$.png" />
|
||||||
|
<uap:SplashScreen Image="$placeholder$.png" />
|
||||||
|
</uap:VisualElements>
|
||||||
|
</Application>
|
||||||
|
</Applications>
|
||||||
|
|
||||||
|
<Capabilities>
|
||||||
|
<rescap:Capability Name="runFullTrust" />
|
||||||
|
</Capabilities>
|
||||||
|
|
||||||
|
</Package>
|
||||||
15
src/HihaArvio/Platforms/Windows/app.manifest
Normal file
15
src/HihaArvio/Platforms/Windows/app.manifest
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="HihaArvio.WinUI.app"/>
|
||||||
|
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<!-- The combination of below two tags have the following effect:
|
||||||
|
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||||
|
2) System < Windows 10 Anniversary Update
|
||||||
|
-->
|
||||||
|
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
</assembly>
|
||||||
9
src/HihaArvio/Platforms/iOS/AppDelegate.cs
Normal file
9
src/HihaArvio/Platforms/iOS/AppDelegate.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Foundation;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
[Register("AppDelegate")]
|
||||||
|
public class AppDelegate : MauiUIApplicationDelegate
|
||||||
|
{
|
||||||
|
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
|
||||||
|
}
|
||||||
32
src/HihaArvio/Platforms/iOS/Info.plist
Normal file
32
src/HihaArvio/Platforms/iOS/Info.plist
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>LSRequiresIPhoneOS</key>
|
||||||
|
<true/>
|
||||||
|
<key>UIDeviceFamily</key>
|
||||||
|
<array>
|
||||||
|
<integer>1</integer>
|
||||||
|
<integer>2</integer>
|
||||||
|
</array>
|
||||||
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
|
<array>
|
||||||
|
<string>arm64</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
|
<array>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>XSAppIconAssets</key>
|
||||||
|
<string>Assets.xcassets/appicon.appiconset</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
15
src/HihaArvio/Platforms/iOS/Program.cs
Normal file
15
src/HihaArvio/Platforms/iOS/Program.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using ObjCRuntime;
|
||||||
|
using UIKit;
|
||||||
|
|
||||||
|
namespace HihaArvio;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
// This is the main entry point of the application.
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// if you want to use a different Application Delegate class from "AppDelegate"
|
||||||
|
// you can specify it here.
|
||||||
|
UIApplication.Main(args, null, typeof(AppDelegate));
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/HihaArvio/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
Normal file
51
src/HihaArvio/Platforms/iOS/Resources/PrivacyInfo.xcprivacy
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
This is the minimum required version of the Apple Privacy Manifest for .NET MAUI apps.
|
||||||
|
The contents below are needed because of APIs that are used in the .NET framework and .NET MAUI SDK.
|
||||||
|
|
||||||
|
You are responsible for adding extra entries as needed for your application.
|
||||||
|
|
||||||
|
More information: https://aka.ms/maui-privacy-manifest
|
||||||
|
-->
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPITypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>C617.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>35F9.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>E174.1</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<!--
|
||||||
|
The entry below is only needed when you're using the Preferences API in your app.
|
||||||
|
<dict>
|
||||||
|
<key>NSPrivacyAccessedAPIType</key>
|
||||||
|
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||||
|
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||||
|
<array>
|
||||||
|
<string>CA92.1</string>
|
||||||
|
</array>
|
||||||
|
</dict> -->
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
8
src/HihaArvio/Properties/launchSettings.json
Normal file
8
src/HihaArvio/Properties/launchSettings.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Windows Machine": {
|
||||||
|
"commandName": "MsixPackage",
|
||||||
|
"nativeDebugging": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
src/HihaArvio/Resources/AppIcon/appicon.svg
Normal file
4
src/HihaArvio/Resources/AppIcon/appicon.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="0" y="0" width="456" height="456" fill="#512BD4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 231 B |
8
src/HihaArvio/Resources/AppIcon/appiconfg.svg
Normal file
8
src/HihaArvio/Resources/AppIcon/appiconfg.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/HihaArvio/Resources/Fonts/OpenSans-Regular.ttf
Normal file
BIN
src/HihaArvio/Resources/Fonts/OpenSans-Regular.ttf
Normal file
Binary file not shown.
BIN
src/HihaArvio/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
BIN
src/HihaArvio/Resources/Fonts/OpenSans-Semibold.ttf
Normal file
Binary file not shown.
BIN
src/HihaArvio/Resources/Images/dotnet_bot.png
Normal file
BIN
src/HihaArvio/Resources/Images/dotnet_bot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
15
src/HihaArvio/Resources/Raw/AboutAssets.txt
Normal file
15
src/HihaArvio/Resources/Raw/AboutAssets.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Any raw assets you want to be deployed with your application can be placed in
|
||||||
|
this directory (and child directories). Deployment of the asset to your application
|
||||||
|
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
|
||||||
|
|
||||||
|
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
|
|
||||||
|
These files will be deployed with your package and will be accessible using Essentials:
|
||||||
|
|
||||||
|
async Task LoadMauiAsset()
|
||||||
|
{
|
||||||
|
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
|
||||||
|
using var reader = new StreamReader(stream);
|
||||||
|
|
||||||
|
var contents = reader.ReadToEnd();
|
||||||
|
}
|
||||||
8
src/HihaArvio/Resources/Splash/splash.svg
Normal file
8
src/HihaArvio/Resources/Splash/splash.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg width="456" height="456" viewBox="0 0 456 456" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||||
|
<path d="m 105.50037,281.60863 c -2.70293,0 -5.00091,-0.90042 -6.893127,-2.70209 -1.892214,-1.84778 -2.837901,-4.04181 -2.837901,-6.58209 0,-2.58722 0.945687,-4.80389 2.837901,-6.65167 1.892217,-1.84778 4.190197,-2.77167 6.893127,-2.77167 2.74819,0 5.06798,0.92389 6.96019,2.77167 1.93749,1.84778 2.90581,4.06445 2.90581,6.65167 0,2.54028 -0.96832,4.73431 -2.90581,6.58209 -1.89221,1.80167 -4.212,2.70209 -6.96019,2.70209 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 213.56111,280.08446 H 195.99044 L 149.69953,207.0544 c -1.17121,-1.84778 -2.14037,-3.76515 -2.90581,-5.75126 h -0.40578 c 0.36051,2.12528 0.54076,6.67515 0.54076,13.6496 v 65.13172 h -15.54349 v -99.36009 h 18.71925 l 44.7374,71.29798 c 1.89222,2.95695 3.1087,4.98917 3.64945,6.09751 h 0.26996 c -0.45021,-2.6325 -0.67573,-7.09015 -0.67573,-13.37293 v -64.02256 h 15.47557 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="m 289.25134,280.08446 h -54.40052 v -99.36009 h 52.23835 v 13.99669 h -36.15411 v 28.13085 h 33.31621 v 13.9271 h -33.31621 v 29.37835 h 38.31628 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
<path d="M 366.56466,194.72106 H 338.7222 v 85.3634 h -16.08423 v -85.3634 h -27.77455 v -13.99669 h 71.70124 z" style="fill:#ffffff;fill-rule:nonzero;stroke-width:0.838376" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
45
src/HihaArvio/Resources/Styles/Colors.xaml
Normal file
45
src/HihaArvio/Resources/Styles/Colors.xaml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<?xaml-comp compile="true" ?>
|
||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||||
|
|
||||||
|
<!-- Note: For Android please see also Platforms\Android\Resources\values\colors.xml -->
|
||||||
|
|
||||||
|
<Color x:Key="Primary">#512BD4</Color>
|
||||||
|
<Color x:Key="PrimaryDark">#ac99ea</Color>
|
||||||
|
<Color x:Key="PrimaryDarkText">#242424</Color>
|
||||||
|
<Color x:Key="Secondary">#DFD8F7</Color>
|
||||||
|
<Color x:Key="SecondaryDarkText">#9880e5</Color>
|
||||||
|
<Color x:Key="Tertiary">#2B0B98</Color>
|
||||||
|
|
||||||
|
<Color x:Key="White">White</Color>
|
||||||
|
<Color x:Key="Black">Black</Color>
|
||||||
|
<Color x:Key="Magenta">#D600AA</Color>
|
||||||
|
<Color x:Key="MidnightBlue">#190649</Color>
|
||||||
|
<Color x:Key="OffBlack">#1f1f1f</Color>
|
||||||
|
|
||||||
|
<Color x:Key="Gray100">#E1E1E1</Color>
|
||||||
|
<Color x:Key="Gray200">#C8C8C8</Color>
|
||||||
|
<Color x:Key="Gray300">#ACACAC</Color>
|
||||||
|
<Color x:Key="Gray400">#919191</Color>
|
||||||
|
<Color x:Key="Gray500">#6E6E6E</Color>
|
||||||
|
<Color x:Key="Gray600">#404040</Color>
|
||||||
|
<Color x:Key="Gray900">#212121</Color>
|
||||||
|
<Color x:Key="Gray950">#141414</Color>
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
|
||||||
|
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
|
||||||
|
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
|
||||||
|
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
|
||||||
|
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
|
||||||
|
|
||||||
|
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
|
||||||
|
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
|
||||||
|
</ResourceDictionary>
|
||||||
427
src/HihaArvio/Resources/Styles/Styles.xaml
Normal file
427
src/HihaArvio/Resources/Styles/Styles.xaml
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<?xaml-comp compile="true" ?>
|
||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
|
||||||
|
|
||||||
|
<Style TargetType="ActivityIndicator">
|
||||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="IndicatorView">
|
||||||
|
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
|
||||||
|
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Border">
|
||||||
|
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
<Setter Property="StrokeShape" Value="Rectangle"/>
|
||||||
|
<Setter Property="StrokeThickness" Value="1"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="BoxView">
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource PrimaryDarkText}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource PrimaryDark}}" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="BorderWidth" Value="0"/>
|
||||||
|
<Setter Property="CornerRadius" Value="8"/>
|
||||||
|
<Setter Property="Padding" Value="14,10"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="CheckBox">
|
||||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="DatePicker">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Editor">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Entry">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Frame">
|
||||||
|
<Setter Property="HasShadow" Value="False" />
|
||||||
|
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||||
|
<Setter Property="CornerRadius" Value="8" />
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="ImageButton">
|
||||||
|
<Setter Property="Opacity" Value="1" />
|
||||||
|
<Setter Property="BorderColor" Value="Transparent"/>
|
||||||
|
<Setter Property="BorderWidth" Value="0"/>
|
||||||
|
<Setter Property="CornerRadius" Value="0"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="Opacity" Value="0.5" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Label">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Span">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Label" x:Key="Headline">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="FontSize" Value="32" />
|
||||||
|
<Setter Property="HorizontalOptions" Value="Center" />
|
||||||
|
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Label" x:Key="SubHeadline">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource MidnightBlue}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="FontSize" Value="24" />
|
||||||
|
<Setter Property="HorizontalOptions" Value="Center" />
|
||||||
|
<Setter Property="HorizontalTextAlignment" Value="Center" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="ListView">
|
||||||
|
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
|
||||||
|
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Picker">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="ProgressBar">
|
||||||
|
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="RadioButton">
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="RefreshView">
|
||||||
|
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="SearchBar">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||||
|
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="SearchHandler">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
<Setter Property="FontSize" Value="14" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Shadow">
|
||||||
|
<Setter Property="Radius" Value="15" />
|
||||||
|
<Setter Property="Opacity" Value="0.5" />
|
||||||
|
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="Offset" Value="10,10" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Slider">
|
||||||
|
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||||
|
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="SwipeItem">
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Switch">
|
||||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{StaticResource White}" />
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="On">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Off">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TimePicker">
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="BackgroundColor" Value="Transparent"/>
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="MinimumHeightRequest" Value="44"/>
|
||||||
|
<Setter Property="MinimumWidthRequest" Value="44"/>
|
||||||
|
<Setter Property="VisualStateManager.VisualStateGroups">
|
||||||
|
<VisualStateGroupList>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateGroupList>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Page" ApplyToDerivedTypes="True">
|
||||||
|
<Setter Property="Padding" Value="0"/>
|
||||||
|
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Shell" ApplyToDerivedTypes="True">
|
||||||
|
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||||
|
<Setter Property="Shell.ForegroundColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||||
|
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource SecondaryDarkText}}" />
|
||||||
|
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||||
|
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
|
||||||
|
<Setter Property="Shell.NavBarHasShadow" Value="False" />
|
||||||
|
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
|
||||||
|
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="NavigationPage">
|
||||||
|
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource OffBlack}}" />
|
||||||
|
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TabbedPage">
|
||||||
|
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
|
||||||
|
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Magenta}, Dark={StaticResource White}}" />
|
||||||
|
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
|
||||||
|
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
33
tests/HihaArvio.Tests/HihaArvio.Tests.csproj
Normal file
33
tests/HihaArvio.Tests/HihaArvio.Tests.csproj
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
|
||||||
|
<!-- Per spec: treat warnings as errors, C# 12 -->
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<LangVersion>12</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||||
|
<PackageReference Include="FluentAssertions" Version="8.8.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||||
|
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.5.3" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\HihaArvio\HihaArvio.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
90
tests/HihaArvio.Tests/Models/AppSettingsTests.cs
Normal file
90
tests/HihaArvio.Tests/Models/AppSettingsTests.cs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using HihaArvio.Models;
|
||||||
|
|
||||||
|
namespace HihaArvio.Tests.Models;
|
||||||
|
|
||||||
|
public class AppSettingsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void AppSettings_DefaultConstructor_ShouldSetWorkModeAsDefault()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var settings = new AppSettings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.SelectedMode.Should().Be(EstimateMode.Work);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AppSettings_DefaultConstructor_ShouldSetMaxHistorySizeTo10()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var settings = new AppSettings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxHistorySize.Should().Be(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(EstimateMode.Work)]
|
||||||
|
[InlineData(EstimateMode.Generic)]
|
||||||
|
[InlineData(EstimateMode.Humorous)]
|
||||||
|
public void AppSettings_ShouldAllowModeChanges(EstimateMode mode)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AppSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.SelectedMode = mode;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.SelectedMode.Should().Be(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(1)]
|
||||||
|
[InlineData(5)]
|
||||||
|
[InlineData(10)]
|
||||||
|
[InlineData(50)]
|
||||||
|
[InlineData(100)]
|
||||||
|
public void AppSettings_ShouldAcceptValidMaxHistorySizeValues(int size)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AppSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
settings.MaxHistorySize = size;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.MaxHistorySize.Should().Be(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0)]
|
||||||
|
[InlineData(-1)]
|
||||||
|
[InlineData(-10)]
|
||||||
|
public void AppSettings_ShouldThrowForInvalidMaxHistorySize(int invalidSize)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var settings = new AppSettings();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => settings.MaxHistorySize = invalidSize;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<ArgumentOutOfRangeException>()
|
||||||
|
.WithMessage("*must be greater than 0*");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AppSettings_ShouldCreateWithDefaultValues()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var settings = new AppSettings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
settings.Should().NotBeNull();
|
||||||
|
settings.SelectedMode.Should().Be(EstimateMode.Work);
|
||||||
|
settings.MaxHistorySize.Should().Be(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
tests/HihaArvio.Tests/Models/EstimateModeTests.cs
Normal file
51
tests/HihaArvio.Tests/Models/EstimateModeTests.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using HihaArvio.Models;
|
||||||
|
|
||||||
|
namespace HihaArvio.Tests.Models;
|
||||||
|
|
||||||
|
public class EstimateModeTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void EstimateMode_ShouldHaveWorkValue()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var mode = EstimateMode.Work;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mode.Should().Be(EstimateMode.Work);
|
||||||
|
((int)mode).Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateMode_ShouldHaveGenericValue()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var mode = EstimateMode.Generic;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mode.Should().Be(EstimateMode.Generic);
|
||||||
|
((int)mode).Should().Be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateMode_ShouldHaveHumorousValue()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var mode = EstimateMode.Humorous;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
mode.Should().Be(EstimateMode.Humorous);
|
||||||
|
((int)mode).Should().Be(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateMode_ShouldHaveExactlyThreeValues()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var values = Enum.GetValues<EstimateMode>();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
values.Should().HaveCount(3);
|
||||||
|
values.Should().Contain(new[] { EstimateMode.Work, EstimateMode.Generic, EstimateMode.Humorous });
|
||||||
|
}
|
||||||
|
}
|
||||||
147
tests/HihaArvio.Tests/Models/EstimateResultTests.cs
Normal file
147
tests/HihaArvio.Tests/Models/EstimateResultTests.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using HihaArvio.Models;
|
||||||
|
|
||||||
|
namespace HihaArvio.Tests.Models;
|
||||||
|
|
||||||
|
public class EstimateResultTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void EstimateResult_ShouldCreateWithAllProperties()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var id = Guid.NewGuid();
|
||||||
|
var timestamp = DateTimeOffset.UtcNow;
|
||||||
|
var estimateText = "2 weeks";
|
||||||
|
var mode = EstimateMode.Work;
|
||||||
|
var intensity = 0.75;
|
||||||
|
var duration = TimeSpan.FromSeconds(5);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new EstimateResult
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Timestamp = timestamp,
|
||||||
|
EstimateText = estimateText,
|
||||||
|
Mode = mode,
|
||||||
|
ShakeIntensity = intensity,
|
||||||
|
ShakeDuration = duration
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Id.Should().Be(id);
|
||||||
|
result.Timestamp.Should().Be(timestamp);
|
||||||
|
result.EstimateText.Should().Be(estimateText);
|
||||||
|
result.Mode.Should().Be(mode);
|
||||||
|
result.ShakeIntensity.Should().Be(intensity);
|
||||||
|
result.ShakeDuration.Should().Be(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.0)]
|
||||||
|
[InlineData(0.3)]
|
||||||
|
[InlineData(0.7)]
|
||||||
|
[InlineData(1.0)]
|
||||||
|
public void EstimateResult_ShouldAcceptValidIntensityValues(double intensity)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var result = new EstimateResult { ShakeIntensity = intensity };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.ShakeIntensity.Should().Be(intensity);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-0.1)]
|
||||||
|
[InlineData(1.1)]
|
||||||
|
[InlineData(2.0)]
|
||||||
|
public void EstimateResult_ShouldThrowForInvalidIntensity(double invalidIntensity)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
Action act = () => _ = new EstimateResult { ShakeIntensity = invalidIntensity };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<ArgumentOutOfRangeException>()
|
||||||
|
.WithMessage("*must be between 0.0 and 1.0*");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateResult_ShouldThrowForNullEstimateText()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
Action act = () => _ = new EstimateResult { EstimateText = null! };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<ArgumentNullException>()
|
||||||
|
.WithParameterName("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData(" ")]
|
||||||
|
public void EstimateResult_ShouldThrowForEmptyOrWhitespaceEstimateText(string invalidText)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
Action act = () => _ = new EstimateResult { EstimateText = invalidText };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<ArgumentException>()
|
||||||
|
.WithMessage("*cannot be empty or whitespace*");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateResult_ShouldAcceptZeroDuration()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var result = new EstimateResult { ShakeDuration = TimeSpan.Zero };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.ShakeDuration.Should().Be(TimeSpan.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateResult_ShouldGenerateUniqueIds()
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var result1 = EstimateResult.Create("test1", EstimateMode.Work, 0.5, TimeSpan.FromSeconds(1));
|
||||||
|
var result2 = EstimateResult.Create("test2", EstimateMode.Work, 0.5, TimeSpan.FromSeconds(1));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result1.Id.Should().NotBe(result2.Id);
|
||||||
|
result1.Id.Should().NotBeEmpty();
|
||||||
|
result2.Id.Should().NotBeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateResult_Create_ShouldSetTimestampAutomatically()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var before = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = EstimateResult.Create("test", EstimateMode.Work, 0.5, TimeSpan.FromSeconds(1));
|
||||||
|
var after = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Timestamp.Should().BeOnOrAfter(before);
|
||||||
|
result.Timestamp.Should().BeOnOrBefore(after);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void EstimateResult_Create_ShouldSetAllProperties()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var estimateText = "3 months";
|
||||||
|
var mode = EstimateMode.Generic;
|
||||||
|
var intensity = 0.8;
|
||||||
|
var duration = TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = EstimateResult.Create(estimateText, mode, intensity, duration);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.EstimateText.Should().Be(estimateText);
|
||||||
|
result.Mode.Should().Be(mode);
|
||||||
|
result.ShakeIntensity.Should().Be(intensity);
|
||||||
|
result.ShakeDuration.Should().Be(duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
106
tests/HihaArvio.Tests/Models/ShakeDataTests.cs
Normal file
106
tests/HihaArvio.Tests/Models/ShakeDataTests.cs
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using HihaArvio.Models;
|
||||||
|
|
||||||
|
namespace HihaArvio.Tests.Models;
|
||||||
|
|
||||||
|
public class ShakeDataTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void ShakeData_ShouldCreateWithAllProperties()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var intensity = 0.65;
|
||||||
|
var duration = TimeSpan.FromSeconds(3);
|
||||||
|
var isShaking = true;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var shakeData = new ShakeData
|
||||||
|
{
|
||||||
|
Intensity = intensity,
|
||||||
|
Duration = duration,
|
||||||
|
IsShaking = isShaking
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
shakeData.Intensity.Should().Be(intensity);
|
||||||
|
shakeData.Duration.Should().Be(duration);
|
||||||
|
shakeData.IsShaking.Should().Be(isShaking);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(0.0)]
|
||||||
|
[InlineData(0.25)]
|
||||||
|
[InlineData(0.5)]
|
||||||
|
[InlineData(0.75)]
|
||||||
|
[InlineData(1.0)]
|
||||||
|
public void ShakeData_ShouldAcceptValidIntensityValues(double intensity)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var shakeData = new ShakeData { Intensity = intensity };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
shakeData.Intensity.Should().Be(intensity);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-0.1)]
|
||||||
|
[InlineData(-1.0)]
|
||||||
|
[InlineData(1.01)]
|
||||||
|
[InlineData(2.0)]
|
||||||
|
public void ShakeData_ShouldThrowForInvalidIntensity(double invalidIntensity)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
Action act = () => _ = new ShakeData { Intensity = invalidIntensity };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<ArgumentOutOfRangeException>()
|
||||||
|
.WithMessage("*must be between 0.0 and 1.0*");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShakeData_ShouldAcceptZeroDuration()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var shakeData = new ShakeData { Duration = TimeSpan.Zero };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
shakeData.Duration.Should().Be(TimeSpan.Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShakeData_ShouldAcceptPositiveDuration()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var duration = TimeSpan.FromSeconds(15.5);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var shakeData = new ShakeData { Duration = duration };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
shakeData.Duration.Should().Be(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(true)]
|
||||||
|
[InlineData(false)]
|
||||||
|
public void ShakeData_ShouldAcceptBooleanIsShakingValues(bool isShaking)
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var shakeData = new ShakeData { IsShaking = isShaking };
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
shakeData.IsShaking.Should().Be(isShaking);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ShakeData_DefaultConstructor_ShouldSetDefaultValues()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var shakeData = new ShakeData();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
shakeData.Intensity.Should().Be(0.0);
|
||||||
|
shakeData.Duration.Should().Be(TimeSpan.Zero);
|
||||||
|
shakeData.IsShaking.Should().BeFalse();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,490 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<coverage line-rate="0.5128" branch-rate="0.875" version="1.9" timestamp="1763460415" lines-covered="60" lines-valid="117" branches-covered="14" branches-valid="16">
|
||||||
|
<sources>
|
||||||
|
<source>/Users/ivuorinen/Code/ivuorinen/hiha-arvio/src/HihaArvio/</source>
|
||||||
|
</sources>
|
||||||
|
<packages>
|
||||||
|
<package name="HihaArvio" line-rate="0.5128" branch-rate="0.875" complexity="41">
|
||||||
|
<classes>
|
||||||
|
<class name="__XamlGeneratedCode__.__Type416C8673F66D9458" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/Resources_Styles_Colors.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="2">
|
||||||
|
<methods>
|
||||||
|
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="29" hits="0" branch="False" />
|
||||||
|
<line number="30" hits="0" branch="False" />
|
||||||
|
<line number="31" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="20" hits="0" branch="False" />
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="29" hits="0" branch="False" />
|
||||||
|
<line number="30" hits="0" branch="False" />
|
||||||
|
<line number="31" hits="0" branch="False" />
|
||||||
|
<line number="20" hits="0" branch="False" />
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="__XamlGeneratedCode__.__Type76D52C8BE0F320C6" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/Resources_Styles_Styles.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="2">
|
||||||
|
<methods>
|
||||||
|
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="29" hits="0" branch="False" />
|
||||||
|
<line number="30" hits="0" branch="False" />
|
||||||
|
<line number="31" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="20" hits="0" branch="False" />
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="29" hits="0" branch="False" />
|
||||||
|
<line number="30" hits="0" branch="False" />
|
||||||
|
<line number="31" hits="0" branch="False" />
|
||||||
|
<line number="20" hits="0" branch="False" />
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.App" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/App.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<methods>
|
||||||
|
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.App" filename="App.xaml.cs" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<methods>
|
||||||
|
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="5" hits="0" branch="False" />
|
||||||
|
<line number="6" hits="0" branch="False" />
|
||||||
|
<line number="7" hits="0" branch="False" />
|
||||||
|
<line number="9" hits="0" branch="False" />
|
||||||
|
<line number="10" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="5" hits="0" branch="False" />
|
||||||
|
<line number="6" hits="0" branch="False" />
|
||||||
|
<line number="7" hits="0" branch="False" />
|
||||||
|
<line number="9" hits="0" branch="False" />
|
||||||
|
<line number="10" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.AppShell" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/AppShell.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<methods>
|
||||||
|
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.AppShell" filename="AppShell.xaml.cs" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<methods>
|
||||||
|
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="5" hits="0" branch="False" />
|
||||||
|
<line number="6" hits="0" branch="False" />
|
||||||
|
<line number="7" hits="0" branch="False" />
|
||||||
|
<line number="8" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="5" hits="0" branch="False" />
|
||||||
|
<line number="6" hits="0" branch="False" />
|
||||||
|
<line number="7" hits="0" branch="False" />
|
||||||
|
<line number="8" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.MainPage" filename="MainPage.xaml.cs" line-rate="0" branch-rate="0" complexity="3">
|
||||||
|
<methods>
|
||||||
|
<method name="OnCounterClicked" signature="(System.Object,System.EventArgs)" line-rate="0" branch-rate="0" complexity="2">
|
||||||
|
<lines>
|
||||||
|
<line number="13" hits="0" branch="False" />
|
||||||
|
<line number="14" hits="0" branch="False" />
|
||||||
|
<line number="16" hits="0" branch="True" condition-coverage="0% (0/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="26" type="jump" coverage="0%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="17" hits="0" branch="False" />
|
||||||
|
<line number="19" hits="0" branch="False" />
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name=".ctor" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="5" hits="0" branch="False" />
|
||||||
|
<line number="7" hits="0" branch="False" />
|
||||||
|
<line number="8" hits="0" branch="False" />
|
||||||
|
<line number="9" hits="0" branch="False" />
|
||||||
|
<line number="10" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="13" hits="0" branch="False" />
|
||||||
|
<line number="14" hits="0" branch="False" />
|
||||||
|
<line number="16" hits="0" branch="True" condition-coverage="0% (0/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="26" type="jump" coverage="0%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="17" hits="0" branch="False" />
|
||||||
|
<line number="19" hits="0" branch="False" />
|
||||||
|
<line number="21" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="5" hits="0" branch="False" />
|
||||||
|
<line number="7" hits="0" branch="False" />
|
||||||
|
<line number="8" hits="0" branch="False" />
|
||||||
|
<line number="9" hits="0" branch="False" />
|
||||||
|
<line number="10" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.MainPage" filename="obj/Debug/net8.0/Microsoft.Maui.Controls.SourceGen/Microsoft.Maui.Controls.SourceGen.CodeBehindGenerator/MainPage.xaml.sg.cs" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<methods>
|
||||||
|
<method name="InitializeComponent" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="25" hits="0" branch="False" />
|
||||||
|
<line number="26" hits="0" branch="False" />
|
||||||
|
<line number="27" hits="0" branch="False" />
|
||||||
|
<line number="28" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="25" hits="0" branch="False" />
|
||||||
|
<line number="26" hits="0" branch="False" />
|
||||||
|
<line number="27" hits="0" branch="False" />
|
||||||
|
<line number="28" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.MauiProgram" filename="MauiProgram.cs" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<methods>
|
||||||
|
<method name="CreateMauiApp" signature="()" line-rate="0" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="8" hits="0" branch="False" />
|
||||||
|
<line number="9" hits="0" branch="False" />
|
||||||
|
<line number="10" hits="0" branch="False" />
|
||||||
|
<line number="11" hits="0" branch="False" />
|
||||||
|
<line number="12" hits="0" branch="False" />
|
||||||
|
<line number="13" hits="0" branch="False" />
|
||||||
|
<line number="14" hits="0" branch="False" />
|
||||||
|
<line number="15" hits="0" branch="False" />
|
||||||
|
<line number="16" hits="0" branch="False" />
|
||||||
|
<line number="19" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="8" hits="0" branch="False" />
|
||||||
|
<line number="9" hits="0" branch="False" />
|
||||||
|
<line number="10" hits="0" branch="False" />
|
||||||
|
<line number="11" hits="0" branch="False" />
|
||||||
|
<line number="12" hits="0" branch="False" />
|
||||||
|
<line number="13" hits="0" branch="False" />
|
||||||
|
<line number="14" hits="0" branch="False" />
|
||||||
|
<line number="15" hits="0" branch="False" />
|
||||||
|
<line number="16" hits="0" branch="False" />
|
||||||
|
<line number="19" hits="0" branch="False" />
|
||||||
|
<line number="22" hits="0" branch="False" />
|
||||||
|
<line number="23" hits="0" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.Models.AppSettings" filename="Models/AppSettings.cs" line-rate="1" branch-rate="1" complexity="5">
|
||||||
|
<methods>
|
||||||
|
<method name="get_SelectedMode" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="14" hits="22" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_MaxHistorySize" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="23" hits="7" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="set_MaxHistorySize" signature="(System.Int32)" line-rate="1" branch-rate="1" complexity="2">
|
||||||
|
<lines>
|
||||||
|
<line number="25" hits="8" branch="False" />
|
||||||
|
<line number="26" hits="8" branch="True" condition-coverage="100% (2/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="10" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="27" hits="3" branch="False" />
|
||||||
|
<line number="28" hits="3" branch="False" />
|
||||||
|
<line number="29" hits="3" branch="False" />
|
||||||
|
<line number="30" hits="3" branch="False" />
|
||||||
|
<line number="31" hits="3" branch="False" />
|
||||||
|
<line number="34" hits="5" branch="False" />
|
||||||
|
<line number="35" hits="5" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name=".ctor" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="8" hits="14" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="14" hits="22" branch="False" />
|
||||||
|
<line number="23" hits="7" branch="False" />
|
||||||
|
<line number="25" hits="8" branch="False" />
|
||||||
|
<line number="26" hits="8" branch="True" condition-coverage="100% (2/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="10" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="27" hits="3" branch="False" />
|
||||||
|
<line number="28" hits="3" branch="False" />
|
||||||
|
<line number="29" hits="3" branch="False" />
|
||||||
|
<line number="30" hits="3" branch="False" />
|
||||||
|
<line number="31" hits="3" branch="False" />
|
||||||
|
<line number="34" hits="5" branch="False" />
|
||||||
|
<line number="35" hits="5" branch="False" />
|
||||||
|
<line number="8" hits="14" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.Models.EstimateResult" filename="Models/EstimateResult.cs" line-rate="1" branch-rate="1" complexity="16">
|
||||||
|
<methods>
|
||||||
|
<method name="get_Id" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="14" hits="10" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_Timestamp" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="19" hits="8" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_EstimateText" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="28" hits="2" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="set_EstimateText" signature="(System.String)" line-rate="1" branch-rate="1" complexity="4">
|
||||||
|
<lines>
|
||||||
|
<line number="30" hits="8" branch="False" />
|
||||||
|
<line number="31" hits="8" branch="True" condition-coverage="100% (2/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="7" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="32" hits="1" branch="False" />
|
||||||
|
<line number="33" hits="1" branch="False" />
|
||||||
|
<line number="36" hits="7" branch="True" condition-coverage="100% (2/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="34" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="37" hits="2" branch="False" />
|
||||||
|
<line number="38" hits="2" branch="False" />
|
||||||
|
<line number="41" hits="5" branch="False" />
|
||||||
|
<line number="42" hits="5" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_Mode" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="48" hits="7" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_ShakeIntensity" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="56" hits="6" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="set_ShakeIntensity" signature="(System.Double)" line-rate="1" branch-rate="1" complexity="4">
|
||||||
|
<lines>
|
||||||
|
<line number="58" hits="12" branch="False" />
|
||||||
|
<line number="59" hits="12" branch="True" condition-coverage="100% (4/4)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="11" type="jump" coverage="100%" />
|
||||||
|
<condition number="30" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="60" hits="3" branch="False" />
|
||||||
|
<line number="61" hits="3" branch="False" />
|
||||||
|
<line number="62" hits="3" branch="False" />
|
||||||
|
<line number="63" hits="3" branch="False" />
|
||||||
|
<line number="64" hits="3" branch="False" />
|
||||||
|
<line number="67" hits="9" branch="False" />
|
||||||
|
<line number="68" hits="9" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_ShakeDuration" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="74" hits="9" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="Create" signature="(System.String,HihaArvio.Models.EstimateMode,System.Double,System.TimeSpan)" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="89" hits="4" branch="False" />
|
||||||
|
<line number="90" hits="4" branch="False" />
|
||||||
|
<line number="91" hits="4" branch="False" />
|
||||||
|
<line number="92" hits="4" branch="False" />
|
||||||
|
<line number="93" hits="4" branch="False" />
|
||||||
|
<line number="94" hits="4" branch="False" />
|
||||||
|
<line number="95" hits="4" branch="False" />
|
||||||
|
<line number="96" hits="4" branch="False" />
|
||||||
|
<line number="97" hits="4" branch="False" />
|
||||||
|
<line number="98" hits="4" branch="False" />
|
||||||
|
<line number="99" hits="4" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name=".ctor" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="8" hits="16" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="14" hits="10" branch="False" />
|
||||||
|
<line number="19" hits="8" branch="False" />
|
||||||
|
<line number="28" hits="2" branch="False" />
|
||||||
|
<line number="30" hits="8" branch="False" />
|
||||||
|
<line number="31" hits="8" branch="True" condition-coverage="100% (2/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="7" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="32" hits="1" branch="False" />
|
||||||
|
<line number="33" hits="1" branch="False" />
|
||||||
|
<line number="36" hits="7" branch="True" condition-coverage="100% (2/2)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="34" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="37" hits="2" branch="False" />
|
||||||
|
<line number="38" hits="2" branch="False" />
|
||||||
|
<line number="41" hits="5" branch="False" />
|
||||||
|
<line number="42" hits="5" branch="False" />
|
||||||
|
<line number="48" hits="7" branch="False" />
|
||||||
|
<line number="56" hits="6" branch="False" />
|
||||||
|
<line number="58" hits="12" branch="False" />
|
||||||
|
<line number="59" hits="12" branch="True" condition-coverage="100% (4/4)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="11" type="jump" coverage="100%" />
|
||||||
|
<condition number="30" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="60" hits="3" branch="False" />
|
||||||
|
<line number="61" hits="3" branch="False" />
|
||||||
|
<line number="62" hits="3" branch="False" />
|
||||||
|
<line number="63" hits="3" branch="False" />
|
||||||
|
<line number="64" hits="3" branch="False" />
|
||||||
|
<line number="67" hits="9" branch="False" />
|
||||||
|
<line number="68" hits="9" branch="False" />
|
||||||
|
<line number="74" hits="9" branch="False" />
|
||||||
|
<line number="89" hits="4" branch="False" />
|
||||||
|
<line number="90" hits="4" branch="False" />
|
||||||
|
<line number="91" hits="4" branch="False" />
|
||||||
|
<line number="92" hits="4" branch="False" />
|
||||||
|
<line number="93" hits="4" branch="False" />
|
||||||
|
<line number="94" hits="4" branch="False" />
|
||||||
|
<line number="95" hits="4" branch="False" />
|
||||||
|
<line number="96" hits="4" branch="False" />
|
||||||
|
<line number="97" hits="4" branch="False" />
|
||||||
|
<line number="98" hits="4" branch="False" />
|
||||||
|
<line number="99" hits="4" branch="False" />
|
||||||
|
<line number="8" hits="16" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
<class name="HihaArvio.Models.ShakeData" filename="Models/ShakeData.cs" line-rate="1" branch-rate="1" complexity="7">
|
||||||
|
<methods>
|
||||||
|
<method name="get_Intensity" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="16" hits="7" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="set_Intensity" signature="(System.Double)" line-rate="1" branch-rate="1" complexity="4">
|
||||||
|
<lines>
|
||||||
|
<line number="18" hits="10" branch="False" />
|
||||||
|
<line number="19" hits="10" branch="True" condition-coverage="100% (4/4)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="11" type="jump" coverage="100%" />
|
||||||
|
<condition number="30" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="20" hits="4" branch="False" />
|
||||||
|
<line number="21" hits="4" branch="False" />
|
||||||
|
<line number="22" hits="4" branch="False" />
|
||||||
|
<line number="23" hits="4" branch="False" />
|
||||||
|
<line number="24" hits="4" branch="False" />
|
||||||
|
<line number="27" hits="6" branch="False" />
|
||||||
|
<line number="28" hits="6" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_Duration" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="34" hits="7" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
<method name="get_IsShaking" signature="()" line-rate="1" branch-rate="1" complexity="1">
|
||||||
|
<lines>
|
||||||
|
<line number="39" hits="7" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</method>
|
||||||
|
</methods>
|
||||||
|
<lines>
|
||||||
|
<line number="16" hits="7" branch="False" />
|
||||||
|
<line number="18" hits="10" branch="False" />
|
||||||
|
<line number="19" hits="10" branch="True" condition-coverage="100% (4/4)">
|
||||||
|
<conditions>
|
||||||
|
<condition number="11" type="jump" coverage="100%" />
|
||||||
|
<condition number="30" type="jump" coverage="100%" />
|
||||||
|
</conditions>
|
||||||
|
</line>
|
||||||
|
<line number="20" hits="4" branch="False" />
|
||||||
|
<line number="21" hits="4" branch="False" />
|
||||||
|
<line number="22" hits="4" branch="False" />
|
||||||
|
<line number="23" hits="4" branch="False" />
|
||||||
|
<line number="24" hits="4" branch="False" />
|
||||||
|
<line number="27" hits="6" branch="False" />
|
||||||
|
<line number="28" hits="6" branch="False" />
|
||||||
|
<line number="34" hits="7" branch="False" />
|
||||||
|
<line number="39" hits="7" branch="False" />
|
||||||
|
</lines>
|
||||||
|
</class>
|
||||||
|
</classes>
|
||||||
|
</package>
|
||||||
|
</packages>
|
||||||
|
</coverage>
|
||||||
Reference in New Issue
Block a user