Compare commits

...

No commits in common. "e4f0c62500bc2624ac8f3453c1ebf048116f71c1" and "00b30b2349b94d46b61a4c09b7e44caf8ed450dd" have entirely different histories.

26 changed files with 5770 additions and 1 deletions

View file

@ -1,3 +1,5 @@
# TagashiFileHub
Tagashi File Hub is a feature-rich file management application developed in C#. With a focus on efficiency and organization, it provides a seamless and intelligent bridge (「橋」hashi) between files and tags.
Tagashi File Hub is a feature-rich file management application developed in C#. With a focus on efficiency and organization, it provides a seamless and intelligent bridge (「橋」hashi) between files and tags. Embracing the essence of "Tagashi," which combines "Tag" and "Hashi" (「橋」 Japanese for "Bridge"), the application empowers users to navigate and organize their files effortlessly through the use of tags.
Tagashi File Hub aims to streamline your file management journey, providing you with the tools to efficiently handle your files and unleash your productivity. Whether you are an anime enthusiast or simply seeking a powerful file management solution, our application caters to users from all walks of life.

49
Tagashi File Hub.sln Normal file
View file

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.33913.275
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tagashi File Hub", "src\Tagashi File Hub\Tagashi File Hub.csproj", "{A4C5EF53-50CC-49D4-B750-C7FB2F848455}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagashiFileHub.Core", "src\TagashiFileHub.Core\TagashiFileHub.Core.csproj", "{39536C05-9C87-44CA-A753-6A317F252666}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TagashiFIleHub.Service", "src\TagashiFIleHub.Service\TagashiFIleHub.Service.csproj", "{368C0084-EBB4-4A9A-9E01-84C48CF184D9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TagashiFileHub.Communication.Abstractions", "src\TagashiFileHub.Communication.Abstractions\TagashiFileHub.Communication.Abstractions.csproj", "{587B3D46-1114-4A84-8F33-4EEA501AE613}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TagashiFileHub.Communication.IPC", "src\TagashiFileHub.Communication.IPC\TagashiFileHub.Communication.IPC.csproj", "{64A274BB-678E-42C5-BD69-6BF7F04AD026}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A4C5EF53-50CC-49D4-B750-C7FB2F848455}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4C5EF53-50CC-49D4-B750-C7FB2F848455}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4C5EF53-50CC-49D4-B750-C7FB2F848455}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4C5EF53-50CC-49D4-B750-C7FB2F848455}.Release|Any CPU.Build.0 = Release|Any CPU
{39536C05-9C87-44CA-A753-6A317F252666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39536C05-9C87-44CA-A753-6A317F252666}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39536C05-9C87-44CA-A753-6A317F252666}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39536C05-9C87-44CA-A753-6A317F252666}.Release|Any CPU.Build.0 = Release|Any CPU
{368C0084-EBB4-4A9A-9E01-84C48CF184D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{368C0084-EBB4-4A9A-9E01-84C48CF184D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{368C0084-EBB4-4A9A-9E01-84C48CF184D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{368C0084-EBB4-4A9A-9E01-84C48CF184D9}.Release|Any CPU.Build.0 = Release|Any CPU
{587B3D46-1114-4A84-8F33-4EEA501AE613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{587B3D46-1114-4A84-8F33-4EEA501AE613}.Debug|Any CPU.Build.0 = Debug|Any CPU
{587B3D46-1114-4A84-8F33-4EEA501AE613}.Release|Any CPU.ActiveCfg = Release|Any CPU
{587B3D46-1114-4A84-8F33-4EEA501AE613}.Release|Any CPU.Build.0 = Release|Any CPU
{64A274BB-678E-42C5-BD69-6BF7F04AD026}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64A274BB-678E-42C5-BD69-6BF7F04AD026}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64A274BB-678E-42C5-BD69-6BF7F04AD026}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64A274BB-678E-42C5-BD69-6BF7F04AD026}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B374DBF1-7DBE-4218-BE5E-DD7A972F881D}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tagashi/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

BIN
resources/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

BIN
resources/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

47
src/Tagashi File Hub/Form1.Designer.cs generated Normal file
View file

@ -0,0 +1,47 @@
namespace Tagashi_File_Hub
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
SuspendLayout();
//
// Form1
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(800, 450);
Icon = (Icon)resources.GetObject("$this.Icon");
Name = "Form1";
Text = "Form1";
ResumeLayout(false);
}
#endregion
}
}

View file

@ -0,0 +1,9 @@
namespace Tagashi_File_Hub;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,17 @@
namespace Tagashi_File_Hub
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}
}

View file

@ -0,0 +1,58 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net7.0-windows</TargetFramework>
<RootNamespace>Tagashi_File_Hub</RootNamespace>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<StartupObject>Tagashi_File_Hub.Program</StartupObject>
<ApplicationIcon>logo.ico</ApplicationIcon>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<DocumentationFile>../../docs/TagashiFileHub.xml</DocumentationFile>
<Title>Tagashi FIle Hub</Title>
<PackageIcon>logo.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<AssemblyVersion>0.1.0</AssemblyVersion>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<IncludeSymbols>True</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<WarningLevel>9999</WarningLevel>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<WarningLevel>9999</WarningLevel>
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
</PropertyGroup>
<ItemGroup>
<Content Include="logo.ico" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\LICENSE">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\..\README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\..\resources\logo.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TagashiFileHub.Core\TagashiFileHub.Core.csproj" />
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

View file

@ -0,0 +1,14 @@
using TagashiFileHub.Communication.IPC;
using TagashiFIleHub.Service;
var host = Host.CreateDefaultBuilder(args)
.UseWindowsService(config => { config.ServiceName = "Tagashi File Hub"; })
.ConfigureServices(services =>
{
services.AddSingleton<TagashiServer>();
services.AddHostedService<Worker>();
services.AddLogging();
})
.Build();
host.Run();

View file

@ -0,0 +1,11 @@
{
"profiles": {
"TagashiFIleHub.Service": {
"commandName": "Project",
"dotnetRunMessages": true,
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
}
}
}

View file

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Worker">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UserSecretsId>dotnet-TagashiFIleHub.Service-f42ced2e-207a-4058-b846-f77037e5ac5a</UserSecretsId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TagashiFileHub.Communication.IPC\TagashiFileHub.Communication.IPC.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,28 @@
using TagashiFileHub.Communication.IPC;
namespace TagashiFIleHub.Service;
internal class Worker : BackgroundService
{
private readonly ILogger<Worker>? _logger;
private readonly TagashiServer _server;
public Worker(ILogger<Worker>? logger, TagashiServer server)
{
_logger = logger;
_server = server;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger?.LogInformation("Starting service worker");
await _server.StartAsync("Service", stoppingToken);
while (!stoppingToken.IsCancellationRequested)
{
_logger?.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}

View file

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View file

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View file

@ -0,0 +1,5 @@
namespace TagashiFileHub.Communication.Abstractions;
public interface ITagashiClient
{
}

View file

@ -0,0 +1,5 @@
namespace TagashiFileHub.Communication.Abstractions;
public interface ITagashiServer
{
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View file

@ -0,0 +1,11 @@
namespace TagashiFileHub.Communication.IPC;
internal static class IpcUtils
{
public static string PipeNamePrefix => "TagashiFileHub";
public static string PipeName(string name)
{
return $"{PipeNamePrefix}.{name}";
}
}

View file

@ -0,0 +1,63 @@
using System.IO.Pipes;
using Microsoft.Extensions.Logging;
using TagashiFileHub.Communication.Abstractions;
namespace TagashiFileHub.Communication.IPC;
public class TagashiClient : ITagashiClient, IDisposable
{
private readonly ILogger<TagashiClient>? _logger;
public TagashiClient(ILogger<TagashiClient>? logger)
{
_logger = logger;
}
private CancellationTokenSource DisconnectingSource { get; } = new();
private NamedPipeClientStream? ClientPipe { get; set; }
public void Dispose()
{
TryDisconnectCurrentPipe();
}
private void TryDisconnectCurrentPipe()
{
_logger?.LogInformation("Closing current pipe connection if existing.");
DisconnectingSource.Cancel(false);
ClientPipe?.Close();
ClientPipe?.Dispose();
ClientPipe = null;
}
public async Task ConnectAsync(string pipeName)
{
if (ClientPipe is not null)
{
_logger?.LogWarning("Client pipe already opened.");
TryDisconnectCurrentPipe();
}
_logger?.LogInformation($"Creating pipe for \".\" with name \"{pipeName}\"");
ClientPipe = new NamedPipeClientStream(".", IpcUtils.PipeName(pipeName), PipeDirection.InOut, PipeOptions.None);
await ClientPipe.ConnectAsync().ConfigureAwait(false);
DisconnectingSource.TryReset();
_ = NewListenTask(ClientPipe, DisconnectingSource.Token);
}
private static Task NewListenTask(NamedPipeClientStream clientPipe, CancellationToken cancellationToken)
{
return Task.Factory.StartNew(async () =>
{
while (!cancellationToken.IsCancellationRequested)
{
using var reader = new StreamReader(clientPipe);
var message = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
}
}, cancellationToken);
}
}

View file

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.1" />
<PackageReference Include="System.IO.Pipes" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TagashiFileHub.Communication.Abstractions\TagashiFileHub.Communication.Abstractions.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,66 @@
using System.Collections.Concurrent;
using System.IO.Pipes;
using Microsoft.Extensions.Logging;
using TagashiFileHub.Communication.Abstractions;
namespace TagashiFileHub.Communication.IPC;
public class TagashiServer : ITagashiServer
{
private readonly ConcurrentBag<StreamWriter> _clients = new();
private readonly ILogger<TagashiServer>? _logger;
public TagashiServer(ILogger<TagashiServer>? logger = null)
{
_logger = logger;
}
public async Task StartAsync(string pipeName, CancellationToken cancellationToken)
{
await Task.Run(async () =>
{
_logger?.LogInformation($"Starting up tagashi server for pipe \"{pipeName}\"");
while (!cancellationToken.IsCancellationRequested)
{
await using var serverPipe = new NamedPipeServerStream(IpcUtils.PipeName(pipeName), PipeDirection.InOut,
1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
await serverPipe.WaitForConnectionAsync(cancellationToken);
using var reader = new StreamReader(serverPipe);
await using var writer = new StreamWriter(serverPipe) { AutoFlush = true };
_clients.Add(writer);
await HandleClientInternalAsync(reader, writer, cancellationToken).ConfigureAwait(false);
}
_logger?.LogInformation($"Shut down tagashi server for pipe \"{pipeName}\"");
}, cancellationToken).ConfigureAwait(false);
}
private async Task HandleClientInternalAsync(StreamReader reader, StreamWriter writer,
CancellationToken cancellationToken)
{
try
{
_logger?.LogInformation("New client connected");
while (!cancellationToken.IsCancellationRequested)
{
var message = await reader.ReadLineAsync(cancellationToken);
if (message == null)
break;
}
}
catch
{
// TODO
}
finally
{
_clients.TryTake(out writer!);
writer.Close();
_logger?.LogInformation("Client disconnected");
}
}
}

View file

@ -0,0 +1,7 @@
namespace TagashiFileHub.Core
{
public class Class1
{
}
}

View file

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>