一个跨平台的`ChatGPT`悬浮窗工具

一个,跨平台,chatgpt,悬浮,工具 · 浏览次数 : 372

小编点评

## 插件开发指南 **1. 创建插件项目** * 在解决方案中创建一个类库项目 * 项目名称以Gotrays.Suspension.PlugIn.开头,例如Gotrays.Suspension.PlugIn.Test * 依赖Gotrays.Suspension.PlugIn类库 **2. 创建插件类** * 在项目中创建一个类,继承Gotrays.Suspension.PlugIn.PlugInBase类,例如:using Gotrays.Suspension.PlugIn;public class SystemTools : PlugInBase{ ... **3. 创建插件类** * 在项目中创建一个类,继承Gotrays.Suspension.PlugInBase类,例如:using Gotrays.Suspension.PlugIn;public class SystemTools : PlugInBase{ ... **4. 实现插件接口** * 在继承PlugInBase类中实现所有方法,例如:SearchAsync、InitAsync、BuilderServiceAsync、Selection、UnSelection、UnloadAsync **5. 建立插件选择器** * 在Selection方法中返回选择插件的类型 **6. 实现插件注册** * 在InitAsync方法中注册插件,例如:services.AddSingleton(); **7. 实现插件发现** * 在服务发现中注册插件,例如:services.AddSingleton(); **8. 实现插件选择** * 在Selection方法中返回选择插件的类型 **9. 实现插件注册** * 在InitAsync方法中注册插件,例如:services.AddSingleton(); **10. 实现插件选择** * 在Selection方法中返回选择插件的类型 **11. 实现插件选择** * 在Selection方法中返回选择插件的类型 **12. 实现插件选择** * 在Selection方法中返回选择插件的类型

正文

一个跨平台的ChatGPT悬浮窗工具

使用avalonia实现的ChatGPT的工具,设计成悬浮窗,并且支持插件。

如何实现悬浮窗?

在使用avalonia实现悬浮窗也是非常的简单的。

实现我们需要将窗体设置成无边框

Window根节点添加一下属性,想要在Linux下生效请务必添加SystemDecorations属性

ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="NoChrome"
ExtendClientAreaTitleBarHeightHint="-1"
SystemDecorations="None"

这样我们的窗口就设置成了无边框。

然后我们还需要将窗体的大小固定,

Height="50"
MaxHeight="50"
Width="{Binding Width}"
MaxWidth="{Binding Width}"

高度固定,宽度绑定到ViewModelWidth属性中,默认270

接下来给出所有代码,

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:Gotrays.Suspension.Client.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:valueConverter="clr-namespace:Gotrays.Suspension.Client.ValueConverter"
        xmlns:md="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
        xmlns:avedit="https://github.com/avaloniaui/avaloniaedit"
        xmlns:ctxt="clr-namespace:ColorTextBlock.Avalonia;assembly=ColorTextBlock.Avalonia"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="Gotrays.Suspension.Client.Views.MainWindow"
        x:DataType="vm:MainWindowViewModel"
        ExtendClientAreaToDecorationsHint="True"
        ExtendClientAreaChromeHints="NoChrome"
        ExtendClientAreaTitleBarHeightHint="-1"
        SystemDecorations="None"
        WindowStartupLocation="CenterScreen"
        Height="50"
        MaxHeight="50"
        Width="{Binding Width}"
        MaxWidth="{Binding Width}"
        Icon="/Assets/ai.png"
        Title="Gotrays.Suspension.Client">

    <Window.Resources>
        <valueConverter:ImageConverter x:Key="ImageConverter" />
        <valueConverter:ChatToStyleConverter x:Key="ChatToStyleConverter" />
    </Window.Resources>

    <Design.DataContext>
        <vm:MainWindowViewModel />
    </Design.DataContext>

    <Window.Styles>
        <Style Selector="Window">
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="Padding" Value="0" />
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="BorderBrush" Value="Transparent" />
        </Style>
        <Style Selector="TextBox.red:pointerover">
            <Setter Property="Opacity" Value="1" />
        </Style>
    </Window.Styles>

    <Border Name="MainBorder" CornerRadius="1000" Background="Black" Margin="0,0,0,0" Padding="0,0,0,0"
            HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Height="50">
        <Grid>
            <!-- 图标 -->
            <Image Source="../Assets/ai.png" Name="Logo" HorizontalAlignment="Left" VerticalAlignment="Center"
                   Width="46"
                   Tapped="Logo_OnTapped"
                   RenderOptions.BitmapInterpolationMode="HighQuality"
                   PointerPressed="OnLogoClick"
                   PointerEntered="Logo_OnPointerEntered"
                   PointerExited="Logo_OnPointerExited"
                   Height="46" Margin="0,0,0,0" />

            <!-- 模型选择 -->
            <Popup Name="ModulePopup" IsOpen="False" PlacementTarget="{Binding ElementName=MainBorder}"
                   PlacementMode="Top">
                <StackPanel Margin="5">
                    <Border Background="#1F1F1F" BorderBrush="Black" BorderThickness="1" CornerRadius="12"
                            MaxHeight="400" Width="120">
                        <ScrollViewer Name="ModuleScrollViewer" VerticalScrollBarVisibility="Auto">
                            <ItemsControl CornerRadius="12" ItemsSource="{Binding Modules}" Margin="2">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <Border Margin="5"
                                                Background="{Binding Color}"
                                                PointerExited="OnSelectStackPointerExited"
                                                PointerEntered="OnSelectStackPointerEntered"
                                                PointerPressed="OnSelectStackPointerPressed"
                                                Tag="{Binding GetThis}"
                                                CornerRadius="8">
                                            <!-- 左边显示图标,右边显示名称 -->
                                            <StackPanel Orientation="Horizontal">
                                                <Image
                                                    RenderOptions.BitmapInterpolationMode="HighQuality"
                                                    Source="{Binding Icon, Converter={StaticResource ImageConverter}}"
                                                    HorizontalAlignment="Left"
                                                    Width="20"
                                                    Height="20" />
                                                <TextBlock TextWrapping="Wrap" Width="60" Text="{Binding Title}"
                                                           Margin="5" Foreground="White" />
                                            </StackPanel>
                                        </Border>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </ScrollViewer>
                    </Border>
                </StackPanel>
            </Popup>

            <!-- 静止状态下的搜索按钮 -->
            <Border PointerPressed="SearchBorder_OnPointerPressed"
                    PointerEntered="searchBorder_PointerEnter"
                    PointerExited="OnPointerExited"
                    Name="searchBorder"
                    CornerRadius="1000" Background="#000000" BorderBrush="#FFFFFF"
                    BorderThickness="1" Margin="50,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Left"
                    VerticalAlignment="Center" Width="46" Height="46" Cursor="Hand">
                <Image Source="../Assets/search.png"
                       RenderOptions.BitmapInterpolationMode="HighQuality"
                       HorizontalAlignment="Center" VerticalAlignment="Center"
                       Width="20" Height="20" Margin="0,0,0,0" />
            </Border>

            <!-- 当点击搜索按钮时,显示搜索框 -->
            <TextBox FontSize="20" Name="SearchText" Margin="50,0,0,0" IsVisible="False" Width="0" Height="40"
                     HorizontalAlignment="Left" VerticalAlignment="Center">
                <TextBox.Styles>
                    <Styles>
                        <Style Selector="TextBox">
                            <Setter Property="CornerRadius" Value="0,50,50,0"></Setter>
                        </Style>
                    </Styles>
                </TextBox.Styles>
                <TextBox.Transitions>
                    <Transitions>
                        <DoubleTransition Property="Width" Duration="0:0:0.1" />
                    </Transitions>
                </TextBox.Transitions>
            </TextBox>
            <!-- 消息显示区域 -->
            <Popup x:Name="MessagePopup"
                   IsOpen="False"
                   PlacementTarget="{Binding ElementName=MainBorder}"
                   PlacementMode="Bottom">
                <StackPanel
                    PointerEntered="MessagePopup_OnPointerEntered"
                    PointerExited="MessagePopup_OnPointerExited" Margin="5">
                    <Border Name="MessageBorder"
                            Background="#1F1F1F"
                            BorderBrush="Black"
                            BorderThickness="1"
                            CornerRadius="12"
                            MaxHeight="300">
                        <ScrollViewer Name="ScrollViewer" VerticalScrollBarVisibility="Auto">
                            <ItemsControl ItemsSource="{Binding Messages}" CornerRadius="12" Margin="2">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <StackPanel Margin="5">
                                            <StackPanel.Resources>
                                                <valueConverter:ChatToBackgroundConverter
                                                    x:Key="ChatToBackgroundConverter" />
                                            </StackPanel.Resources>
                                            <Border
                                                Background="{Binding Chat, Converter={StaticResource ChatToBackgroundConverter}}"
                                                CornerRadius="5">

                                                <md:MarkdownScrollViewer
                                                    VerticalAlignment="Stretch"
                                                    MarkdownStyleName="Standard"
                                                    SaveScrollValueWhenContentUpdated="True"
                                                    Markdown="{Binding Message}">
                                                    <md:MarkdownScrollViewer.Styles>

                                                        <Style Selector="ctxt|CCode">
                                                            <Style.Setters>
                                                                <Setter Property="BorderBrush" Value="Green" />
                                                                <Setter Property="BorderThickness" Value="2" />
                                                                <Setter Property="Padding" Value="2" />
                                                                <Setter Property="MonospaceFontFamily" Value="Meiryo" />
                                                                <Setter Property="Foreground" Value="DarkGreen" />
                                                                <Setter Property="Background" Value="LightGreen" />
                                                            </Style.Setters>
                                                        </Style>

                                                        <Style Selector="Border.CodeBlock">
                                                            <Style.Setters>
                                                                <Setter Property="BorderBrush" Value="Blue" />
                                                                <Setter Property="BorderThickness" Value="0,5,0,5" />
                                                                <Setter Property="Margin" Value="5,0,5,0" />
                                                                <Setter Property="Background" Value="LightBlue" />
                                                            </Style.Setters>
                                                        </Style>

                                                        <Style Selector="TextBlock.CodeBlock">
                                                            <Style.Setters>
                                                                <Setter Property="Foreground" Value="DarkBlue" />
                                                                <Setter Property="FontFamily" Value="Meiryo" />
                                                            </Style.Setters>
                                                        </Style>

                                                        <Style Selector="avedit|TextEditor">
                                                            <Setter Property="Background" Value="Gray" />
                                                            <Setter Property="CornerRadius" Value="10"></Setter>
                                                        </Style>

                                                    </md:MarkdownScrollViewer.Styles>
                                                </md:MarkdownScrollViewer>
                                            </Border>
                                        </StackPanel>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </ScrollViewer>
                    </Border>
                </StackPanel>
            </Popup>

        </Grid>
        <Border.Transitions>
            <Transitions>
                <DoubleTransition Property="Width" Duration="0:0:0.2" />
            </Transitions>
        </Border.Transitions>
    </Border>

</Window>

只需要设置无边框并且固定大小。悬浮窗的效果就达到了。

我们看看执行效果

image-20230702133719931

就这样简单的悬浮窗写好了,我们使用一下悬浮窗的搜索功能

image-20230702133757221

这个就是简单的使用效果,对比其他的工具,这个悬浮窗更简洁,并且跨平台和开源。

image-20230702133839454

目前的项目结构。

plugin下面的项目是默认的插件,用于搜索系统文件(未完善)

Gotrays.Suspension.Client则是实际的客户端。

Gotrays.Suspension.PlugIn则是插件定义的接口规范。

Gotrays.Update则是检查更新程序,用于更新主程序。

实现插件

plug-in

插件模块,用于扩展功能。

插件开发

1. 创建插件项目

在解决方案中创建一个类库项目,项目名称以Gotrays.Suspension.PlugIn.开头,例如Gotrays.Suspension.PlugIn.Test
然后在项目中依赖Gotrays.Suspension.PlugIn类库。

2. 创建插件类

在项目中创建一个类,继承Gotrays.Suspension.PlugIn.PlugInBase类,例如:

using Gotrays.Suspension.PlugIn;

public class SystemTools : PlugInBase
{
    public SystemTools()
    {
        Name = "系统搜索";

​        // 获取system.png嵌入资源的Stream
​        var stream = GetType().Assembly.GetManifestResourceStream("SystemTools.system.png");
​        if (stream == null) return;

​        // 读取Stream到byte数组
​        var bytes = new byte[stream.Length];
​        var read = stream.Read(bytes, 0, bytes.Length);
​        Icon = bytes;
​    }

​    // 搜索触发
​    public override async Task SearchAsync(string value)
​    {
​        // 打开系统搜索
​        Process.Start("explorer.exe", "search://" + value);

​        await Task.CompletedTask;
​    }
​    
​    protected override async Task InitAsync(IServiceCollection services){
​        // 插件首次加载时执行
​    }
​    public override async Task BuilderServiceAsync(IServiceProvider provider)
​    {
​        // 这里可以得到服务提供者,可以通过服务提供者获取其他服务
​    }
​    protected override void Selection()
​    {
​        //  当插件被选中时执行
​    }
​    
​    protected override void UnSelection()
​    {
​        // 当插件被取消选中时执行
​    }
​    
​    protected override async Task UnloadAsync()
​    {
​        // 当插件被卸载插件发生
​    }
​    
}

工具服务会进行自动发现,无需手动注册。
只需要将程序集放置在./plug-in目录下即可。
服务会在一个程序集中发现所有的插件类,并且进行注册。

按照上面的方式非常的简单就集成了插件。

开源地址

Gitee:https://gitee.com/gotrays/gotrays-suspension

Github:https://github.com/239573049/Suspension
技术交流群:737776595

与一个跨平台的`ChatGPT`悬浮窗工具相似的内容:

一个跨平台的`ChatGPT`悬浮窗工具

# 一个跨平台的`ChatGPT`悬浮窗工具 使用`avalonia`实现的`ChatGPT`的工具,设计成悬浮窗,并且支持插件。 ## 如何实现悬浮窗? 在使用`avalonia`实现悬浮窗也是非常的简单的。 实现我们需要将窗体设置成无边框 在`Window`根节点添加一下属性,想要在Linux下

跨平台`ChatGpt` 客户端

跨平台ChatGpt 客户端 一款基于Avalonia实现的跨平台ChatGpt客户端 ,通过对接ChatGpt官方提供的ChatGpt 3.5模型实现聊天对话 实现创建ChatGpt的项目名称 ,项目类型是Avalonia MVVM , 添加项目需要使用的Nuget包

claude3国内API接口对接

众所周知,由于地理位置原因,Claude3不对国内开放,而国内的镜像网站使用又贵的离谱! 因此,团队萌生了一个想法:为什么不创建一个一站式的平台,让用户能够通过单一的接口与多个模型交流呢?这样,用户就可以轻松地比较不同模型的表现,并根据需要选择最合适的一个。于是诞生了这个ChatGPT,Claude

Ui2Code+ChatGPT助力低代码搭建

低代码开发平台(LCDP),是低代码或无代码通过快速搭建配置的方式完成一个应用程序的开发与上线,可视化低代码就是可视化的DSL,它的优点更多的是来源可视化,相对的,它的局限性也还是来源于可视化,复杂的业务逻辑用低代码可能会更加复杂。低代码应该是特定领域问题的简化和抽象,如果只是单纯将原有的编码工作转换为 GUI 的模式,并没有多大意义。

震惊!火爆全网的ChatGPT背后使用的数据库居然是……

摘要:ChatGPT承认了自己背后使用的数据库是Cassandra。 OpenAI最近发布的AI驱动的智能聊天机器人ChatGPT在互联网上掀起了一阵风暴,热衷于尝试这一新AI成果的网民不在少数。ChatGPT针对网友广泛的问题提供了非常有针对性的回答,其不可思议的能力成为各大媒体平台的头条新闻,其

Seal AppManager v0.2 发布:进一步简化应用部署体验

经过近3个月的研发,Seal AppManager v0.2 已正式发布。 Seal AppManager 是一款基于平台工程理念的应用统一部署管理平台,于今年4月首次推出。在上一版本中,我们已经释出**集成 ChatGPT 简化服务模板代码生成、云成本可视化、动态环境管理**等功能,通过降低基础设

ChatGPT插件开发实战

1.概述 ChatGPT是一款由OpenAI推出的先进对话模型,其强大的自然语言处理能力使得它成为构建智能对话系统和人机交互应用的理想选择。为了进一步拓展ChatGPT的功能和适应不同领域的需求,OpenAI提供了插件开发平台,让开发者可以定制化和扩展ChatGPT的能力。 2.内容 OpenAI

基于ChatGPT的API的C#接入研究

今年开年,最火的莫过于ChatGPT的相关讨论,这个提供了非常强大的AI处理,并且整个平台也提供了很多对应的API进行接入的处理,使得我们可以在各种程序上无缝接入AI的后端处理,从而实现智能AI的各种应用。ChatGPT的API可以在前端,以及一些后端进行API的接入,本篇随笔主要介绍基于ChatGPT的API的C#接入研究。

Airtest图像识别测试工具原理解读&最佳实践

Airtest是一个跨平台的、基于图像识别的UI自动化测试框架,适用于游戏和App,支持平台有Windows、Android和iOS。Airtest框架基于一种图形脚本语言Sikuli,引用该框架后,不再需要一行行的写代码,通过截取按钮或输入框的图片,用图片组成测试场景,这种方式学习成本低,简单易上手。

ONNX Runtime入门示例:在C#中使用ResNet50v2进行图像识别

ONNX Runtime简介 ONNX Runtime 是一个跨平台的推理和训练机器学习加速器。ONNX 运行时推理可以实现更快的客户体验和更低的成本,支持来自深度学习框架(如 PyTorch 和 TensorFlow/Keras)以及经典机器学习库(如 scikit-learn、LightGBM、