Initial commit: NexusArchitect Professional Workstation Overhaul
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
using FluentResults;
|
||||
using MediatR;
|
||||
|
||||
namespace NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
public interface ICommand : IRequest<Result>
|
||||
{
|
||||
}
|
||||
|
||||
public interface ICommand<TResponse> : IRequest<Result<TResponse>>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using FluentResults;
|
||||
using MediatR;
|
||||
|
||||
namespace NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
public interface ICommandHandler<TCommand> : IRequestHandler<TCommand, Result>
|
||||
where TCommand : ICommand
|
||||
{
|
||||
}
|
||||
|
||||
public interface ICommandHandler<TCommand, TResponse> : IRequestHandler<TCommand, Result<TResponse>>
|
||||
where TCommand : ICommand<TResponse>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using FluentResults;
|
||||
using MediatR;
|
||||
|
||||
namespace NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
public interface IQuery<TResponse> : IRequest<Result<TResponse>>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using FluentResults;
|
||||
using MediatR;
|
||||
|
||||
namespace NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
public interface IQueryHandler<TQuery, TResponse> : IRequestHandler<TQuery, Result<TResponse>>
|
||||
where TQuery : IQuery<TResponse>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using FluentResults;
|
||||
using NexusReader.Application.Queries.Quiz;
|
||||
|
||||
namespace NexusReader.Application.Abstractions.Services;
|
||||
|
||||
public interface IAiGenerateQuizService
|
||||
{
|
||||
Task<Result<QuizDto>> GenerateQuizAsync(string contextBlockId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using FluentResults;
|
||||
|
||||
namespace NexusReader.Application.Abstractions.Services;
|
||||
|
||||
public interface INativeStorageService
|
||||
{
|
||||
Result SaveString(string key, string value);
|
||||
Result<string?> GetString(string key);
|
||||
Result SaveBool(string key, bool value);
|
||||
Result<bool> GetBool(string key, bool defaultValue = false);
|
||||
Result Remove(string key);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using FluentResults;
|
||||
|
||||
namespace NexusReader.Application.Abstractions.Services;
|
||||
|
||||
public interface IPlatformService
|
||||
{
|
||||
Task<Result> VibrateSuccessAsync();
|
||||
Task<Result> VibrateErrorAsync();
|
||||
Task<Result> VibrateAsync(int milliseconds);
|
||||
Result<DeviceContext> GetDeviceContext();
|
||||
}
|
||||
|
||||
public record DeviceContext(
|
||||
string Model,
|
||||
string Manufacturer,
|
||||
DeviceType DeviceType,
|
||||
DisplayOrientation Orientation
|
||||
);
|
||||
|
||||
public enum DeviceType
|
||||
{
|
||||
Unknown,
|
||||
Phone,
|
||||
Tablet,
|
||||
Desktop
|
||||
}
|
||||
|
||||
public enum DisplayOrientation
|
||||
{
|
||||
Unknown,
|
||||
Portrait,
|
||||
Landscape
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Commands.Quiz;
|
||||
|
||||
public record SubmitAnswerCommand(int SelectedIndex, int CorrectIndex) : ICommand;
|
||||
@@ -0,0 +1,26 @@
|
||||
using FluentResults;
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
using NexusReader.Application.Abstractions.Services;
|
||||
|
||||
namespace NexusReader.Application.Commands.Quiz;
|
||||
|
||||
internal sealed class SubmitAnswerCommandHandler : ICommandHandler<SubmitAnswerCommand>
|
||||
{
|
||||
private readonly IPlatformService _platformService;
|
||||
|
||||
public SubmitAnswerCommandHandler(IPlatformService platformService)
|
||||
{
|
||||
_platformService = platformService;
|
||||
}
|
||||
|
||||
public async Task<Result> Handle(SubmitAnswerCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (request.SelectedIndex == request.CorrectIndex)
|
||||
{
|
||||
await _platformService.VibrateAsync(50);
|
||||
return Result.Ok();
|
||||
}
|
||||
|
||||
return Result.Fail("Incorrect answer.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using NexusReader.Application.Queries.Graph;
|
||||
|
||||
namespace NexusReader.Application.Common;
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true)]
|
||||
[JsonSerializable(typeof(GraphNodeDto))]
|
||||
[JsonSerializable(typeof(GraphLinkDto))]
|
||||
[JsonSerializable(typeof(GraphDataDto))]
|
||||
[JsonSerializable(typeof(List<GraphNodeDto>))]
|
||||
[JsonSerializable(typeof(List<GraphLinkDto>))]
|
||||
public partial class AppJsonContext : JsonSerializerContext
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NexusReader.Application.Mappings;
|
||||
|
||||
namespace NexusReader.Application;
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddApplication(this IServiceCollection services)
|
||||
{
|
||||
services.AddMapsterConfiguration();
|
||||
|
||||
services.AddMediatR(config =>
|
||||
{
|
||||
config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly);
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Mapster;
|
||||
using MapsterMapper;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace NexusReader.Application.Mappings;
|
||||
|
||||
public static class MappingConfig
|
||||
{
|
||||
public static IServiceCollection AddMapsterConfiguration(this IServiceCollection services)
|
||||
{
|
||||
var config = TypeAdapterConfig.GlobalSettings;
|
||||
|
||||
// Manual registration for AOT (or use Source Generator)
|
||||
// config.NewConfig<Source, Destination>();
|
||||
|
||||
services.AddSingleton(config);
|
||||
services.AddScoped<IMapper, ServiceMapper>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NexusReader.Domain\NexusReader.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentResults" Version="4.0.0" />
|
||||
<PackageReference Include="Mapster" Version="10.0.7" />
|
||||
<PackageReference Include="Mapster.DependencyInjection" Version="10.0.7" />
|
||||
<PackageReference Include="MediatR" Version="12.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,5 @@
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Queries.Graph;
|
||||
|
||||
public record GetKnowledgeGraphQuery : IQuery<GraphDataDto>;
|
||||
@@ -0,0 +1,30 @@
|
||||
using FluentResults;
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Queries.Graph;
|
||||
|
||||
internal sealed class GetKnowledgeGraphQueryHandler : IQueryHandler<GetKnowledgeGraphQuery, GraphDataDto>
|
||||
{
|
||||
public Task<Result<GraphDataDto>> Handle(GetKnowledgeGraphQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var nodes = new List<GraphNodeDto>
|
||||
{
|
||||
new("renesans-intro", "Renesans", "Concept"),
|
||||
new("florencja", "Florencja", "Location"),
|
||||
new("medyceusze", "Medyceusze", "Entity"),
|
||||
new("da-vinci-ai", "Leonardo da Vinci", "Person"),
|
||||
new("humanizm", "Humanizm", "Concept")
|
||||
};
|
||||
|
||||
var links = new List<GraphLinkDto>
|
||||
{
|
||||
new("renesans-intro", "florencja", 1),
|
||||
new("florencja", "medyceusze", 2),
|
||||
new("medyceusze", "da-vinci-ai", 3),
|
||||
new("renesans-intro", "humanizm", 1),
|
||||
new("da-vinci-ai", "humanizm", 2)
|
||||
};
|
||||
|
||||
return Task.FromResult(Result.Ok(new GraphDataDto(nodes, links)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace NexusReader.Application.Queries.Graph;
|
||||
|
||||
public record GraphNodeDto(string Id, string Label, string Group);
|
||||
public record GraphLinkDto(string Source, string Target, int Value);
|
||||
public record GraphDataDto(List<GraphNodeDto> Nodes, List<GraphLinkDto> Links);
|
||||
@@ -0,0 +1,5 @@
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Queries.Quiz;
|
||||
|
||||
public record GetQuizQuestionsQuery(string ContextBlockId) : IQuery<QuizDto>;
|
||||
@@ -0,0 +1,20 @@
|
||||
using FluentResults;
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
using NexusReader.Application.Abstractions.Services;
|
||||
|
||||
namespace NexusReader.Application.Queries.Quiz;
|
||||
|
||||
internal sealed class GetQuizQuestionsQueryHandler : IQueryHandler<GetQuizQuestionsQuery, QuizDto>
|
||||
{
|
||||
private readonly IAiGenerateQuizService _aiService;
|
||||
|
||||
public GetQuizQuestionsQueryHandler(IAiGenerateQuizService aiService)
|
||||
{
|
||||
_aiService = aiService;
|
||||
}
|
||||
|
||||
public async Task<Result<QuizDto>> Handle(GetQuizQuestionsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
return await _aiService.GenerateQuizAsync(request.ContextBlockId, cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace NexusReader.Application.Queries.Quiz;
|
||||
|
||||
public record QuizQuestionDto(string Question, List<string> Options, int CorrectIndex);
|
||||
public record QuizDto(List<QuizQuestionDto> Questions);
|
||||
@@ -0,0 +1,5 @@
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Queries.Reader;
|
||||
|
||||
public record GetReaderPageQuery : IQuery<ReaderPageViewModel>;
|
||||
@@ -0,0 +1,20 @@
|
||||
using FluentResults;
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Queries.Reader;
|
||||
|
||||
internal sealed class GetReaderPageQueryHandler : IQueryHandler<GetReaderPageQuery, ReaderPageViewModel>
|
||||
{
|
||||
public Task<Result<ReaderPageViewModel>> Handle(GetReaderPageQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var blocks = new List<ContentBlock>
|
||||
{
|
||||
new TextSegmentBlock("renesans-intro", "Renesans, nazywany również odrodzeniem, to epoka w historii kultury europejskiej, która zapoczątkowała odejście od średniowiecznego teocentryzmu na rzecz humanizmu. Narodził się we Włoszech, a dokładnie we Florencji, w XV wieku, skąd promieniował na całą Europę."),
|
||||
new TextSegmentBlock("medyceusze", "Głównym mecenasem sztuki i nauki we Florencji był potężny ród Medyceuszy. To dzięki ich wsparciu miasto stało się kolebką nowożytnej myśli, gromadząc wokół siebie najwybitniejsze umysły tamtych czasów."),
|
||||
new AiActionTriggerBlock("da-vinci-ai", "Leonardo da Vinci był jednym z najważniejszych twórców tego okresu. Czy chciałbyś dowiedzieć się więcej o jego najważniejszych wynalazkach, czy wolisz sprawdzić swoją dotychczasową wiedzę?", new List<string> { "Pokaż więcej", "Rozwiąż quiz" }),
|
||||
new TextSegmentBlock("leonardo-detail", "Człowiek renesansu, uosabiany właśnie przez Leonarda, był wszechstronnie wykształcony. Interesował się sztuką, inżynierią, anatomią i filozofią, stawiając jednostkę w centrum wszechświata.")
|
||||
};
|
||||
|
||||
return Task.FromResult(Result.Ok(new ReaderPageViewModel(blocks)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace NexusReader.Application.Queries.Reader;
|
||||
|
||||
public abstract record ContentBlock(string Id);
|
||||
public record TextSegmentBlock(string Id, string Content) : ContentBlock(Id);
|
||||
public record AiActionTriggerBlock(string Id, string Dialogue, List<string> ActionOptions) : ContentBlock(Id);
|
||||
|
||||
public record ReaderPageViewModel(List<ContentBlock> Blocks);
|
||||
@@ -0,0 +1,5 @@
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Queries.System;
|
||||
|
||||
public record GetInitializationStatusQuery : IQuery<string>;
|
||||
@@ -0,0 +1,12 @@
|
||||
using FluentResults;
|
||||
using NexusReader.Application.Abstractions.Messaging;
|
||||
|
||||
namespace NexusReader.Application.Queries.System;
|
||||
|
||||
internal sealed class GetInitializationStatusQueryHandler : IQueryHandler<GetInitializationStatusQuery, string>
|
||||
{
|
||||
public Task<Result<string>> Handle(GetInitializationStatusQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(Result.Ok("Nexus E-Reader Application is fully initialized and operational."));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user