🐛 Fixed window pinning issue

This commit is contained in:
2025-09-02 23:59:04 +08:00
parent 5f22ee3b1f
commit 6149bc133d
17 changed files with 211 additions and 146 deletions

View File

@@ -1,10 +1,10 @@
# <img src="./frontend/public/appicon.png" alt="VoidRaft Logo" width="32" height="32" style="vertical-align: middle;"> VoidRaft # <img src="./frontend/public/appicon.png" alt="voidraft Logo" width="32" height="32" style="vertical-align: middle;"> voidraft
[中文](README_ZH.md) | **English** [中文](README_ZH.md) | **English**
> *An elegant text snippet recording tool designed for developers.* > *An elegant text snippet recording tool designed for developers.*
VoidRaft is a modern developer-focused text editor that allows you to record, organize, and manage various text snippets anytime, anywhere. Whether it's temporary code snippets, API responses, meeting notes, or daily to-do lists, VoidRaft provides a smooth and elegant editing experience. voidraft is a modern developer-focused text editor that allows you to record, organize, and manage various text snippets anytime, anywhere. Whether it's temporary code snippets, API responses, meeting notes, or daily to-do lists, voidraft provides a smooth and elegant editing experience.
## Core Features ## Core Features
@@ -87,7 +87,7 @@ After building, the executable will be generated in the `bin` directory.
## Project Structure ## Project Structure
``` ```
Voidraft/ voidraft/
├── frontend/ # Vue 3 frontend application ├── frontend/ # Vue 3 frontend application
│ ├── src/ │ ├── src/
│ │ ├── views/editor/ # Editor core views │ │ ├── views/editor/ # Editor core views
@@ -129,11 +129,11 @@ Voidraft/
> Standing on the shoulders of giants, paying tribute to the open source spirit > Standing on the shoulders of giants, paying tribute to the open source spirit
The birth of VoidRaft is inseparable from the following excellent open source projects: The birth of voidraft is inseparable from the following excellent open source projects:
### Special Thanks ### Special Thanks
- **[Heynote](https://github.com/heyman/heynote/)** - VoidRaft is a feature-enhanced version based on Heynote's concept - **[Heynote](https://github.com/heyman/heynote/)** - voidraft is a feature-enhanced version based on Heynote's concept
- Inherits Heynote's elegant block editing philosophy - Inherits Heynote's elegant block editing philosophy
- Adds more practical features on the original foundation - Adds more practical features on the original foundation
- Rebuilt with modern technology stack - Rebuilt with modern technology stack
@@ -157,7 +157,7 @@ This project is open source under the [MIT License](LICENSE).
Welcome to Fork, Star, and contribute code. Welcome to Fork, Star, and contribute code.
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub stars](https://img.shields.io/github/stars/landaiqing/Voidraft.svg?style=social&label=Star)](https://github.com/yourusername/Voidraft) [![GitHub stars](https://img.shields.io/github/stars/landaiqing/voidraft.svg?style=social&label=Star)](https://github.com/yourusername/voidraft)
[![GitHub forks](https://img.shields.io/github/forks/landaiqing/Voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/Voidraft) [![GitHub forks](https://img.shields.io/github/forks/landaiqing/voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/voidraft)
*Made with ❤️ by landaiqing* *Made with ❤️ by landaiqing*

View File

@@ -1,10 +1,10 @@
# <img src="./frontend/public/appicon.png" alt="Voidraft Logo" width="32" height="32" style="vertical-align: middle;"> Voidraft # <img src="./frontend/public/appicon.png" alt="voidraft Logo" width="32" height="32" style="vertical-align: middle;"> voidraft
**中文** | [English](README.md) **中文** | [English](README.md)
> *一个专为开发者打造的优雅文本片段记录工具。* > *一个专为开发者打造的优雅文本片段记录工具。*
Voidraft 是一个现代化的开发者专用文本编辑器让你能够随时随地记录、整理和管理各种文本片段。无论是临时的代码片段、API 响应、会议笔记,还是日常的待办事项,Voidraft 都能为你提供流畅而优雅的编辑体验。 voidraft 是一个现代化的开发者专用文本编辑器让你能够随时随地记录、整理和管理各种文本片段。无论是临时的代码片段、API 响应、会议笔记,还是日常的待办事项,voidraft 都能为你提供流畅而优雅的编辑体验。
## 核心特性 ## 核心特性
@@ -88,7 +88,7 @@ wails3 package
## 项目结构 ## 项目结构
``` ```
Voidraft/ voidraft/
├── frontend/ # Vue 3 前端应用 ├── frontend/ # Vue 3 前端应用
│ ├── src/ │ ├── src/
│ │ ├── views/editor/ # 编辑器核心视图 │ │ ├── views/editor/ # 编辑器核心视图
@@ -131,11 +131,11 @@ Voidraft/
> 站在巨人的肩膀上,致敬开源精神 > 站在巨人的肩膀上,致敬开源精神
Voidraft 的诞生离不开以下优秀的开源项目: voidraft 的诞生离不开以下优秀的开源项目:
### 特别感谢 ### 特别感谢
- **[Heynote](https://github.com/heyman/heynote/)** - Voidraft 是基于 Heynote 概念的功能增强版本 - **[Heynote](https://github.com/heyman/heynote/)** - voidraft 是基于 Heynote 概念的功能增强版本
- 继承了 Heynote 优雅的块状编辑理念 - 继承了 Heynote 优雅的块状编辑理念
- 在原有基础上增加了更多实用功能 - 在原有基础上增加了更多实用功能
- 采用现代化技术栈重新构建 - 采用现代化技术栈重新构建
@@ -159,7 +159,7 @@ Voidraft 的诞生离不开以下优秀的开源项目:
欢迎 Fork、Star 和贡献代码。 欢迎 Fork、Star 和贡献代码。
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub stars](https://img.shields.io/github/stars/landaiqing/Voidraft.svg?style=social&label=Star)](https://github.com/yourusername/Voidraft) [![GitHub stars](https://img.shields.io/github/stars/landaiqing/voidraft.svg?style=social&label=Star)](https://github.com/yourusername/voidraft)
[![GitHub forks](https://img.shields.io/github/forks/landaiqing/Voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/Voidraft) [![GitHub forks](https://img.shields.io/github/forks/landaiqing/voidraft.svg?style=social&label=Fork)](https://github.com/yourusername/voidraft)
*Made with ❤️ by landaiqing* *Made with ❤️ by landaiqing*

View File

@@ -5,12 +5,12 @@ version: '3'
# This information is used to generate the build assets. # This information is used to generate the build assets.
info: info:
companyName: "Voidraft" # The name of the company companyName: "voidraft" # The name of the company
productName: "Voidraft" # The name of the application productName: "voidraft" # The name of the application
productIdentifier: "landaiqing" # The unique product identifier productIdentifier: "landaiqing" # The unique product identifier
description: "Voidraft" # The application description description: "voidraft" # The application description
copyright: "© 2025 Voidraft. All rights reserved." # Copyright text copyright: "© 2025 voidraft. All rights reserved." # Copyright text
comments: "Voidraft" # Comments comments: "voidraft" # Comments
version: "0.0.1.0" # The application version version: "0.0.1.0" # The application version
# Dev mode configuration # Dev mode configuration

View File

@@ -4,15 +4,15 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Voidraft</string> <string>voidraft</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>Voidraft</string> <string>voidraft</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>landaiqing</string> <string>landaiqing</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.0.1.0</string> <string>0.0.1.0</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>Voidraft</string> <string>voidraft</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.0.1.0</string> <string>0.0.1.0</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
@@ -22,7 +22,7 @@
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<string>true</string> <string>true</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>© 2025 Voidraft. All rights reserved.</string> <string>© 2025 voidraft. All rights reserved.</string>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsLocalNetworking</key> <key>NSAllowsLocalNetworking</key>

View File

@@ -4,15 +4,15 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>Voidraft</string> <string>voidraft</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>Voidraft</string> <string>voidraft</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>landaiqing</string> <string>landaiqing</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.0.1.0</string> <string>0.0.1.0</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>Voidraft</string> <string>voidraft</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.0.1.0</string> <string>0.0.1.0</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
@@ -22,6 +22,6 @@
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<string>true</string> <string>true</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>© 2025 Voidraft. All rights reserved.</string> <string>© 2025 voidraft. All rights reserved.</string>
</dict> </dict>
</plist> </plist>

View File

@@ -3,26 +3,26 @@
# #
# The lines below are called `modelines`. See `:help modeline` # The lines below are called `modelines`. See `:help modeline`
name: "Voidraft" name: "voidraft"
arch: ${GOARCH} arch: ${GOARCH}
platform: "linux" platform: "linux"
version: "0.0.1.0" version: "0.0.1.0"
section: "default" section: "default"
priority: "extra" priority: "extra"
maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}>
description: "Voidraft" description: "voidraft"
vendor: "Voidraft" vendor: "voidraft"
homepage: "https://wails.io" homepage: "https://voidraft.landaiqing.cn"
license: "MIT" license: "MIT"
release: "1" release: "1"
contents: contents:
- src: "./bin/Voidraft" - src: "./bin/voidraft"
dst: "/usr/local/bin/Voidraft" dst: "/usr/local/bin/voidraft"
- src: "./build/appicon.png" - src: "./build/appicon.png"
dst: "/usr/share/icons/hicolor/128x128/apps/Voidraft.png" dst: "/usr/share/icons/hicolor/128x128/apps/voidraft.png"
- src: "./build/linux/Voidraft.desktop" - src: "./build/linux/voidraft.desktop"
dst: "/usr/share/applications/Voidraft.desktop" dst: "/usr/share/applications/voidraft.desktop"
depends: depends:
- gtk3 - gtk3

View File

@@ -5,11 +5,11 @@
"info": { "info": {
"0000": { "0000": {
"ProductVersion": "0.0.1.0", "ProductVersion": "0.0.1.0",
"CompanyName": "Voidraft", "CompanyName": "voidraft",
"FileDescription": "Voidraft", "FileDescription": "voidraft",
"LegalCopyright": "© 2025 Voidraft. All rights reserved.", "LegalCopyright": "© 2025 voidraft. All rights reserved.",
"ProductName": "Voidraft", "ProductName": "voidraft",
"Comments": "Voidraft" "Comments": "voidraft"
} }
} }
} }

View File

@@ -5,19 +5,19 @@
!include "FileFunc.nsh" !include "FileFunc.nsh"
!ifndef INFO_PROJECTNAME !ifndef INFO_PROJECTNAME
!define INFO_PROJECTNAME "Voidraft" !define INFO_PROJECTNAME "voidraft"
!endif !endif
!ifndef INFO_COMPANYNAME !ifndef INFO_COMPANYNAME
!define INFO_COMPANYNAME "Voidraft" !define INFO_COMPANYNAME "voidraft"
!endif !endif
!ifndef INFO_PRODUCTNAME !ifndef INFO_PRODUCTNAME
!define INFO_PRODUCTNAME "Voidraft" !define INFO_PRODUCTNAME "voidraft"
!endif !endif
!ifndef INFO_PRODUCTVERSION !ifndef INFO_PRODUCTVERSION
!define INFO_PRODUCTVERSION "0.0.1.0" !define INFO_PRODUCTVERSION "0.0.1.0"
!endif !endif
!ifndef INFO_COPYRIGHT !ifndef INFO_COPYRIGHT
!define INFO_COPYRIGHT "© 2025 Voidraft. All rights reserved." !define INFO_COPYRIGHT "© 2025 voidraft. All rights reserved."
!endif !endif
!ifndef PRODUCT_EXECUTABLE !ifndef PRODUCT_EXECUTABLE
!define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VoidRaft - Changelog</title> <title>voidraft - Changelog</title>
<link rel="stylesheet" href="css/styles.css"> <link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="css/changelog.css"> <link rel="stylesheet" href="css/changelog.css">
<link rel="icon" href="img/favicon.ico"> <link rel="icon" href="img/favicon.ico">
@@ -16,7 +16,7 @@
<!-- 主卡片 --> <!-- 主卡片 -->
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<h1 class="card-title" data-en="VoidRaft Changelog" data-zh="VoidRaft 更新日志">VoidRaft Changelog</h1> <h1 class="card-title" data-en="voidraft Changelog" data-zh="voidraft 更新日志">voidraft Changelog</h1>
<div class="card-controls"> <div class="card-controls">
<button id="theme-toggle" class="btn btn-secondary" title="切换主题"> <button id="theme-toggle" class="btn btn-secondary" title="切换主题">
<i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span> <i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span>
@@ -59,7 +59,7 @@
<!-- 页脚 --> <!-- 页脚 -->
<footer class="footer"> <footer class="footer">
<p class="footer-text" data-en="© 2025 VoidRaft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 VoidRaft - 专为开发者打造的优雅文本片段记录工具">© 2023-2024 VoidRaft - An elegant text snippet recording tool designed for developers</p> <p class="footer-text" data-en="© 2025 voidraft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 voidraft - 专为开发者打造的优雅文本片段记录工具">© 2023-2024 voidraft - An elegant text snippet recording tool designed for developers</p>
<div class="footer-links"> <div class="footer-links">
<a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a> <a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a>
<a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a> <a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a>

View File

@@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VoidRaft - An elegant text snippet recording tool designed for developers.</title> <title>voidraft - An elegant text snippet recording tool designed for developers.</title>
<meta name="description" content="VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more."> <meta name="description" content="voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
<meta name="keywords" content="text editor, code snippets, developer tools, syntax highlighting, code formatting, multi-language, VoidRaft"> <meta name="keywords" content="text editor, code snippets, developer tools, syntax highlighting, code formatting, multi-language, voidraft">
<meta name="author" content="VoidRaft Team"> <meta name="author" content="voidraft Team">
<meta name="robots" content="index, follow"> <meta name="robots" content="index, follow">
<link rel="canonical" href="https://landaiqing.github.io/voidraft/"> <link rel="canonical" href="https://landaiqing.github.io/voidraft/">
@@ -18,16 +18,16 @@
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:url" content="https://landaiqing.github.io/voidraft/"> <meta property="og:url" content="https://landaiqing.github.io/voidraft/">
<meta property="og:title" content="VoidRaft - An elegant text snippet recording tool designed for developers"> <meta property="og:title" content="voidraft - An elegant text snippet recording tool designed for developers">
<meta property="og:description" content="VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more."> <meta property="og:description" content="voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
<meta property="og:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png"> <meta property="og:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png">
<meta property="og:site_name" content="VoidRaft"> <meta property="og:site_name" content="voidraft">
<!-- Twitter --> <!-- Twitter -->
<meta property="twitter:card" content="summary_large_image"> <meta property="twitter:card" content="summary_large_image">
<meta property="twitter:url" content="https://landaiqing.github.io/voidraft/"> <meta property="twitter:url" content="https://landaiqing.github.io/voidraft/">
<meta property="twitter:title" content="VoidRaft - An elegant text snippet recording tool designed for developers"> <meta property="twitter:title" content="voidraft - An elegant text snippet recording tool designed for developers">
<meta property="twitter:description" content="VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more."> <meta property="twitter:description" content="voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.">
<meta property="twitter:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png"> <meta property="twitter:image" content="https://landaiqing.github.io/voidraft/img/screenshot-dark.png">
<link rel="stylesheet" href="./css/styles.css"> <link rel="stylesheet" href="./css/styles.css">
@@ -39,13 +39,13 @@
{ {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "SoftwareApplication", "@type": "SoftwareApplication",
"name": "VoidRaft", "name": "voidraft",
"description": "An elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.", "description": "An elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.",
"url": "https://landaiqing.github.io/voidraft/", "url": "https://landaiqing.github.io/voidraft/",
"downloadUrl": "https://github.com/landaiqing/voidraft/releases", "downloadUrl": "https://github.com/landaiqing/voidraft/releases",
"author": { "author": {
"@type": "Organization", "@type": "Organization",
"name": "VoidRaft" "name": "voidraft"
}, },
"operatingSystem": ["Windows", "macOS", "Linux"], "operatingSystem": ["Windows", "macOS", "Linux"],
"applicationCategory": "DeveloperApplication", "applicationCategory": "DeveloperApplication",
@@ -66,7 +66,7 @@
<!-- 主卡片 --> <!-- 主卡片 -->
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<h1 class="card-title">VoidRaft</h1> <h1 class="card-title">voidraft</h1>
<div class="card-controls"> <div class="card-controls">
<button id="theme-toggle" class="btn btn-secondary" title="切换主题"> <button id="theme-toggle" class="btn btn-secondary" title="切换主题">
<i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span> <i class="fas fa-sun"></i> <span data-en="Theme" data-zh="主题">Theme</span>
@@ -81,9 +81,9 @@
<!-- Logo和介绍 --> <!-- Logo和介绍 -->
<div class="logo-container"> <div class="logo-container">
<div class="logo-frame"> <div class="logo-frame">
<img src="img/logo.png" alt="VoidRaft Logo" class="logo-image"> <img src="img/logo.png" alt="voidraft Logo" class="logo-image">
</div> </div>
<h2 class="logo-text" data-en="VoidRaft" data-zh="VoidRaft">VoidRaft</h2> <h2 class="logo-text" data-en="voidraft" data-zh="voidraft">voidraft</h2>
<p class="tagline" data-en="An elegant text snippet recording tool" data-zh="优雅的文本片段记录工具">An elegant text snippet recording tool</p> <p class="tagline" data-en="An elegant text snippet recording tool" data-zh="优雅的文本片段记录工具">An elegant text snippet recording tool</p>
</div> </div>
@@ -195,15 +195,15 @@
<div class="block-language">text</div> <div class="block-language">text</div>
</div> </div>
<pre class="code-block"> <pre class="code-block">
<span class="comment">// VoidRaft - An elegant text snippet recording tool</span> <span class="comment">// voidraft - An elegant text snippet recording tool</span>
<span class="comment">// Multi-language support | Code formatting | Custom themes</span> <span class="comment">// Multi-language support | Code formatting | Custom themes</span>
<span class="comment">// A modern text editor designed for developers</span></pre> <span class="comment">// A modern text editor designed for developers</span></pre>
</div> </div>
</div> </div>
</div> </div>
<div class="preview-window"> <div class="preview-window">
<img src="img/screenshot-dark.png" alt="VoidRaft 界面预览" class="preview-image dark-theme-img"> <img src="img/screenshot-dark.png" alt="voidraft 界面预览" class="preview-image dark-theme-img">
<img src="img/screenshot-light.png" alt="VoidRaft 界面预览" class="preview-image light-theme-img" style="display: none;"> <img src="img/screenshot-light.png" alt="voidraft 界面预览" class="preview-image light-theme-img" style="display: none;">
</div> </div>
</div> </div>
@@ -241,7 +241,7 @@
<!-- 页脚 --> <!-- 页脚 -->
<footer class="footer"> <footer class="footer">
<p class="footer-text" data-en="© 2025 VoidRaft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 VoidRaft - 专为开发者打造的优雅文本片段记录工具">© 2025 VoidRaft - An elegant text snippet recording tool designed for developers</p> <p class="footer-text" data-en="© 2025 voidraft - An elegant text snippet recording tool designed for developers" data-zh="© 2025 voidraft - 专为开发者打造的优雅文本片段记录工具">© 2025 voidraft - An elegant text snippet recording tool designed for developers</p>
<div class="footer-links"> <div class="footer-links">
<a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a> <a href="https://github.com/landaiqing/voidraft" target="_blank" class="footer-link">GitHub</a>
<a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a> <a href="https://github.com/landaiqing/voidraft/issues" target="_blank" class="footer-link" data-en="Issues" data-zh="问题反馈">Issues</a>

View File

@@ -1,5 +1,5 @@
/** /**
* VoidRaft - Changelog Script * voidraft - Changelog Script
* 从GitHub API获取发布信息支持Gitea备用源 * 从GitHub API获取发布信息支持Gitea备用源
*/ */

View File

@@ -1,5 +1,5 @@
/** /**
* VoidRaft - Website Script * voidraft - Website Script
*/ */
/** /**
@@ -233,14 +233,14 @@ class SEOManager {
this.languageManager = languageManager; this.languageManager = languageManager;
this.metaTexts = { this.metaTexts = {
en: { en: {
description: 'VoidRaft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.', description: 'voidraft is an elegant text snippet recording tool designed for developers. Features multi-language code blocks, syntax highlighting, code formatting, custom themes, and more.',
title: 'VoidRaft - An elegant text snippet recording tool designed for developers.', title: 'voidraft - An elegant text snippet recording tool designed for developers.',
ogTitle: 'VoidRaft - An elegant text snippet recording tool designed for developers' ogTitle: 'voidraft - An elegant text snippet recording tool designed for developers'
}, },
zh: { zh: {
description: 'VoidRaft 是专为开发者打造的优雅文本片段记录工具。支持多语言代码块、语法高亮、代码格式化、自定义主题等功能。', description: 'voidraft 是专为开发者打造的优雅文本片段记录工具。支持多语言代码块、语法高亮、代码格式化、自定义主题等功能。',
title: 'VoidRaft - 专为开发者打造的优雅文本片段记录工具', title: 'voidraft - 专为开发者打造的优雅文本片段记录工具',
ogTitle: 'VoidRaft - 专为开发者打造的优雅文本片段记录工具' ogTitle: 'voidraft - 专为开发者打造的优雅文本片段记录工具'
} }
}; };
this.init(); this.init();
@@ -371,9 +371,9 @@ class UIEffects {
} }
/** /**
* VoidRaft主应用类 * voidraft主应用类
*/ */
class VoidRaftApp { class voidraftApp {
constructor() { constructor() {
this.themeManager = null; this.themeManager = null;
this.languageManager = null; this.languageManager = null;
@@ -404,7 +404,7 @@ class VoidRaftApp {
* 显示控制台品牌信息 * 显示控制台品牌信息
*/ */
showConsoleBranding() { showConsoleBranding() {
console.log('%c VoidRaft', 'color: #ff006e; font-size: 20px; font-family: "Space Mono", monospace;'); console.log('%c voidraft', 'color: #ff006e; font-size: 20px; font-family: "Space Mono", monospace;');
console.log('%c An elegant text snippet recording tool designed for developers.', 'color: #073B4C; font-family: "Space Mono", monospace;'); console.log('%c An elegant text snippet recording tool designed for developers.', 'color: #073B4C; font-family: "Space Mono", monospace;');
} }
@@ -439,5 +439,5 @@ class VoidRaftApp {
// 当DOM加载完成时初始化应用 // 当DOM加载完成时初始化应用
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
window.voidRaftApp = new VoidRaftApp(); window.voidRaftApp = new voidraftApp();
}); });

View File

@@ -1,10 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import {useI18n} from 'vue-i18n'; import {useI18n} from 'vue-i18n';
import {onMounted, onUnmounted, ref, watch, computed} from 'vue'; import {computed, onMounted, onUnmounted, ref, watch} from 'vue';
import {useConfigStore} from '@/stores/configStore'; import {useConfigStore} from '@/stores/configStore';
import {useEditorStore} from '@/stores/editorStore'; import {useEditorStore} from '@/stores/editorStore';
import {useUpdateStore} from '@/stores/updateStore'; import {useUpdateStore} from '@/stores/updateStore';
import {useWindowStore} from '@/stores/windowStore'; import {useWindowStore} from '@/stores/windowStore';
import {useSystemStore} from '@/stores/systemStore';
import * as runtime from '@wailsio/runtime'; import * as runtime from '@wailsio/runtime';
import {useRouter} from 'vue-router'; import {useRouter} from 'vue-router';
import BlockLanguageSelector from './BlockLanguageSelector.vue'; import BlockLanguageSelector from './BlockLanguageSelector.vue';
@@ -17,22 +18,32 @@ const editorStore = useEditorStore();
const configStore = useConfigStore(); const configStore = useConfigStore();
const updateStore = useUpdateStore(); const updateStore = useUpdateStore();
const windowStore = useWindowStore(); const windowStore = useWindowStore();
const systemStore = useSystemStore();
const {t} = useI18n(); const {t} = useI18n();
const router = useRouter(); const router = useRouter();
// 当前块是否支持格式化的响应式状态 // 当前块是否支持格式化的响应式状态
const canFormatCurrentBlock = ref(false); const canFormatCurrentBlock = ref(false);
// 窗口置顶状态管理(仅当前窗口,不同步到配置文件) // 窗口置顶状态 - 合并配置和临时状态
const isCurrentWindowOnTop = ref(false); const isCurrentWindowOnTop = computed(() => {
return configStore.config.general.alwaysOnTop || systemStore.isWindowOnTop;
const setWindowAlwaysOnTop = async (isTop: boolean) => { });
await runtime.Window.SetAlwaysOnTop(isTop);
};
// 切换窗口置顶状态
const toggleAlwaysOnTop = async () => { const toggleAlwaysOnTop = async () => {
isCurrentWindowOnTop.value = !isCurrentWindowOnTop.value; const currentlyOnTop = isCurrentWindowOnTop.value;
await runtime.Window.SetAlwaysOnTop(isCurrentWindowOnTop.value);
if (currentlyOnTop) {
// 如果当前是置顶状态,彻底关闭所有置顶
if (configStore.config.general.alwaysOnTop) {
await configStore.setAlwaysOnTop(false);
}
await systemStore.setWindowOnTop(false);
} else {
// 如果当前不是置顶状态,开启临时置顶
await systemStore.setWindowOnTop(true);
}
}; };
// 跳转到设置页面 // 跳转到设置页面
@@ -59,11 +70,11 @@ const updateFormatButtonState = () => {
// 获取活动块和语言信息 // 获取活动块和语言信息
const state = view.state; const state = view.state;
const activeBlock = getActiveNoteBlock(state as any); const activeBlock = getActiveNoteBlock(state as any);
// 检查块和语言格式化支持 // 检查块和语言格式化支持
canFormatCurrentBlock.value = !!( canFormatCurrentBlock.value = !!(
activeBlock && activeBlock &&
getLanguage(activeBlock.language.name as any)?.prettier getLanguage(activeBlock.language.name as any)?.prettier
); );
} catch (error) { } catch (error) {
console.warn('Error checking format capability:', error); console.warn('Error checking format capability:', error);
@@ -74,32 +85,32 @@ const updateFormatButtonState = () => {
// 创建带300ms防抖的更新函数 // 创建带300ms防抖的更新函数
const debouncedUpdateFormatButton = (() => { const debouncedUpdateFormatButton = (() => {
let timeout: number | null = null; let timeout: number | null = null;
return () => { return () => {
if (timeout) clearTimeout(timeout); if (timeout) clearTimeout(timeout);
timeout = window.setTimeout(() => { timeout = window.setTimeout(() => {
updateFormatButtonState(); updateFormatButtonState();
timeout = null; timeout = null;
}, 300); }, 1000);
}; };
})(); })();
// 编辑器事件管理 // 编辑器事件管理
const setupEditorListeners = (view: any) => { const setupEditorListeners = (view: any) => {
if (!view?.dom) return []; if (!view?.dom) return [];
const events = [ const events = [
{ type: 'click', handler: updateFormatButtonState }, {type: 'click', handler: updateFormatButtonState},
{ type: 'keyup', handler: debouncedUpdateFormatButton }, {type: 'keyup', handler: debouncedUpdateFormatButton},
{ type: 'focus', handler: updateFormatButtonState } {type: 'focus', handler: updateFormatButtonState}
]; ];
// 注册所有事件 // 注册所有事件
events.forEach(event => view.dom.addEventListener(event.type, event.handler)); events.forEach(event => view.dom.addEventListener(event.type, event.handler));
// 返回清理函数数组 // 返回清理函数数组
return events.map(event => return events.map(event =>
() => view.dom.removeEventListener(event.type, event.handler) () => view.dom.removeEventListener(event.type, event.handler)
); );
}; };
@@ -107,22 +118,22 @@ const setupEditorListeners = (view: any) => {
let cleanupListeners: (() => void)[] = []; let cleanupListeners: (() => void)[] = [];
watch( watch(
() => editorStore.editorView, () => editorStore.editorView,
(newView) => { (newView) => {
// 清理旧监听器 // 清理旧监听器
cleanupListeners.forEach(cleanup => cleanup()); cleanupListeners.forEach(cleanup => cleanup());
cleanupListeners = []; cleanupListeners = [];
if (newView) { if (newView) {
// 初始更新状态 // 初始更新状态
updateFormatButtonState(); updateFormatButtonState();
// 设置新监听器 // 设置新监听器
cleanupListeners = setupEditorListeners(newView); cleanupListeners = setupEditorListeners(newView);
} else { } else {
canFormatCurrentBlock.value = false; canFormatCurrentBlock.value = false;
} }
}, },
{ immediate: true } {immediate: true}
); );
// 组件生命周期 // 组件生命周期
@@ -143,12 +154,28 @@ onUnmounted(() => {
// 组件加载后初始化置顶状态 // 组件加载后初始化置顶状态
watch(isLoaded, async (loaded) => { watch(isLoaded, async (loaded) => {
if (loaded) { if (loaded) {
// 初始化时从配置文件读取置顶状态 // 应用合并后的置顶状态
isCurrentWindowOnTop.value = configStore.config.general.alwaysOnTop; const shouldBeOnTop = configStore.config.general.alwaysOnTop || systemStore.isWindowOnTop;
await setWindowAlwaysOnTop(isCurrentWindowOnTop.value); try {
await runtime.Window.SetAlwaysOnTop(shouldBeOnTop);
} catch (error) {
console.error('Failed to apply window pin state:', error);
}
} }
}); });
// 监听配置变化,同步窗口状态
watch(
() => isCurrentWindowOnTop.value,
async (shouldBeOnTop) => {
try {
await runtime.Window.SetAlwaysOnTop(shouldBeOnTop);
} catch (error) {
console.error('Failed to sync window pin state:', error);
}
}
);
const handleUpdateButtonClick = async () => { const handleUpdateButtonClick = async () => {
if (updateStore.hasUpdate && !updateStore.isUpdating && !updateStore.updateSuccess) { if (updateStore.hasUpdate && !updateStore.isUpdating && !updateStore.updateSuccess) {
// 开始下载更新 // 开始下载更新
@@ -230,29 +257,33 @@ const updateButtonTitle = computed(() => {
@click="handleUpdateButtonClick" @click="handleUpdateButtonClick"
> >
<!-- 检查更新中 --> <!-- 检查更新中 -->
<svg v-if="updateStore.isChecking" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" <svg v-if="updateStore.isChecking" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24"
fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rotating"> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rotating">
<path d="M21 12a9 9 0 1 1-6.219-8.56"/> <path d="M21 12a9 9 0 1 1-6.219-8.56"/>
</svg> </svg>
<!-- 下载更新中 --> <!-- 下载更新中 -->
<svg v-else-if="updateStore.isUpdating" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" <svg v-else-if="updateStore.isUpdating" xmlns="http://www.w3.org/2000/svg" width="14" height="14"
viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rotating"> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="rotating">
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path> <path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
<path d="M12 2a10 10 0 1 0 10 10"></path> <path d="M12 2a10 10 0 1 0 10 10"></path>
</svg> </svg>
<!-- 更新成功等待重启 --> <!-- 更新成功等待重启 -->
<svg v-else-if="updateStore.updateSuccess" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" <svg v-else-if="updateStore.updateSuccess" xmlns="http://www.w3.org/2000/svg" width="14" height="14"
viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="pulsing"> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="pulsing">
<path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path> <path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path>
<line x1="12" y1="2" x2="12" y2="12"></line> <line x1="12" y1="2" x2="12" y2="12"></line>
</svg> </svg>
<!-- 有更新可用 --> <!-- 有更新可用 -->
<svg v-else xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" <svg v-else xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/> <path
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/>
<polyline points="7.5,10.5 12,15 16.5,10.5"/> <polyline points="7.5,10.5 12,15 16.5,10.5"/>
<polyline points="12,15 12,3"/> <polyline points="12,15 12,3"/>
</svg> </svg>
@@ -338,39 +369,39 @@ const updateButtonTitle = computed(() => {
&.available { &.available {
background-color: rgba(76, 175, 80, 0.1); background-color: rgba(76, 175, 80, 0.1);
animation: pulse 2s infinite; animation: pulse 2s infinite;
svg { svg {
stroke: #4caf50; stroke: #4caf50;
} }
&:hover { &:hover {
background-color: rgba(76, 175, 80, 0.2); background-color: rgba(76, 175, 80, 0.2);
transform: scale(1.05); transform: scale(1.05);
} }
} }
/* 检查更新中状态 */ /* 检查更新中状态 */
&.checking { &.checking {
background-color: rgba(255, 193, 7, 0.1); background-color: rgba(255, 193, 7, 0.1);
svg { svg {
stroke: #ffc107; stroke: #ffc107;
} }
} }
/* 更新下载中状态 */ /* 更新下载中状态 */
&.updating { &.updating {
background-color: rgba(33, 150, 243, 0.1); background-color: rgba(33, 150, 243, 0.1);
svg { svg {
stroke: #2196f3; stroke: #2196f3;
} }
} }
/* 更新成功状态 */ /* 更新成功状态 */
&.success { &.success {
background-color: rgba(156, 39, 176, 0.1); background-color: rgba(156, 39, 176, 0.1);
svg { svg {
stroke: #9c27b0; stroke: #9c27b0;
} }
@@ -380,7 +411,7 @@ const updateButtonTitle = computed(() => {
.rotating { .rotating {
animation: rotate 1.5s linear infinite; animation: rotate 1.5s linear infinite;
} }
/* 脉冲动画 */ /* 脉冲动画 */
.pulsing { .pulsing {
animation: pulse-strong 1.2s ease-in-out infinite; animation: pulse-strong 1.2s ease-in-out infinite;
@@ -394,7 +425,7 @@ const updateButtonTitle = computed(() => {
opacity: 0.7; opacity: 0.7;
} }
} }
@keyframes pulse-strong { @keyframes pulse-strong {
0%, 100% { 0%, 100% {
transform: scale(1); transform: scale(1);
@@ -405,7 +436,7 @@ const updateButtonTitle = computed(() => {
opacity: 0.8; opacity: 0.8;
} }
} }
@keyframes rotate { @keyframes rotate {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);

View File

@@ -3,13 +3,15 @@ import {computed, ref} from 'vue';
import {DocumentService} from '@/../bindings/voidraft/internal/services'; import {DocumentService} from '@/../bindings/voidraft/internal/services';
import {OpenDocumentWindow} from '@/../bindings/voidraft/internal/services/windowservice'; import {OpenDocumentWindow} from '@/../bindings/voidraft/internal/services/windowservice';
import {Document} from '@/../bindings/voidraft/internal/models/models'; import {Document} from '@/../bindings/voidraft/internal/models/models';
import {useSystemStore} from './systemStore';
const SCRATCH_DOCUMENT_ID = 1; // 默认草稿文档ID
export const useDocumentStore = defineStore('document', () => { export const useDocumentStore = defineStore('document', () => {
const DEFAULT_DOCUMENT_ID = ref<number>(1); // 默认草稿文档ID
// === 核心状态 === // === 核心状态 ===
const documents = ref<Record<number, Document>>({}); const documents = ref<Record<number, Document>>({});
const recentDocumentIds = ref<number[]>([SCRATCH_DOCUMENT_ID]); const recentDocumentIds = ref<number[]>([DEFAULT_DOCUMENT_ID.value]);
const currentDocumentId = ref<number | null>(null); const currentDocumentId = ref<number | null>(null);
const currentDocument = ref<Document | null>(null); const currentDocument = ref<Document | null>(null);
@@ -159,7 +161,7 @@ export const useDocumentStore = defineStore('document', () => {
const deleteDocument = async (docId: number): Promise<boolean> => { const deleteDocument = async (docId: number): Promise<boolean> => {
try { try {
// 检查是否是默认文档使用ID判断 // 检查是否是默认文档使用ID判断
if (docId === SCRATCH_DOCUMENT_ID) { if (docId === DEFAULT_DOCUMENT_ID.value) {
return false; return false;
} }
@@ -221,6 +223,7 @@ export const useDocumentStore = defineStore('document', () => {
}; };
return { return {
DEFAULT_DOCUMENT_ID,
// 状态 // 状态
documents, documents,
documentList, documentList,

View File

@@ -19,14 +19,15 @@ export const useSystemStore = defineStore('system', () => {
// 状态 // 状态
const environment = ref<SystemEnvironment | null>(null); const environment = ref<SystemEnvironment | null>(null);
const isLoading = ref(false); const isLoading = ref(false);
// 窗口置顶状态管理
const isWindowOnTop = ref<boolean>(false);
// 计算属性 // 计算属性
const isWindows = computed(() => environment.value?.OS === 'windows'); const isWindows = computed(() => environment.value?.OS === 'windows');
const isMacOS = computed(() => environment.value?.OS === 'darwin'); const isMacOS = computed(() => environment.value?.OS === 'darwin');
const isLinux = computed(() => environment.value?.OS === 'linux'); const isLinux = computed(() => environment.value?.OS === 'linux');
// 获取标题栏高度 // 获取标题栏高度
const titleBarHeight = computed(() => { const titleBarHeight = computed(() => {
if (isWindows.value) return '32px'; if (isWindows.value) return '32px';
@@ -49,10 +50,31 @@ export const useSystemStore = defineStore('system', () => {
} }
}; };
// 设置窗口置顶状态
const setWindowOnTop = async (isPinned: boolean): Promise<void> => {
isWindowOnTop.value = isPinned;
try {
await runtime.Window.SetAlwaysOnTop(isPinned);
} catch (error) {
console.error('Failed to set window always on top:', error);
}
};
// 切换窗口置顶状态
const toggleWindowOnTop = async (): Promise<void> => {
await setWindowOnTop(!isWindowOnTop.value);
};
// 重置临时置顶状态不调用系统API
const resetWindowOnTop = (): void => {
isWindowOnTop.value = false;
};
return { return {
// 状态 // 状态
environment, environment,
isLoading, isLoading,
isWindowOnTop,
// 计算属性 // 计算属性
isWindows, isWindows,
@@ -62,5 +84,14 @@ export const useSystemStore = defineStore('system', () => {
// 方法 // 方法
initializeSystemInfo, initializeSystemInfo,
setWindowOnTop,
toggleWindowOnTop,
resetWindowOnTop,
}; };
}, {
persist: {
key: 'voidraft-system',
storage: localStorage,
pick: ['isWindowOnTop']
}
}); });

View File

@@ -263,7 +263,7 @@ func (s *BackupService) PushToRemote() error {
// 创建提交 // 创建提交
_, err = w.Commit(fmt.Sprintf("Backup %s", time.Now().Format("2006-01-02 15:04:05")), &git.CommitOptions{ _, err = w.Commit(fmt.Sprintf("Backup %s", time.Now().Format("2006-01-02 15:04:05")), &git.CommitOptions{
Author: &object.Signature{ Author: &object.Signature{
Name: "VoidRaft", Name: "voidraft",
Email: "backup@voidraft.app", Email: "backup@voidraft.app",
When: time.Now(), When: time.Now(),
}, },

View File

@@ -12,13 +12,13 @@ func SetupSystemTray(app *application.App, mainWindow *application.WebviewWindow
// 创建系统托盘 // 创建系统托盘
systray := app.SystemTray.New() systray := app.SystemTray.New()
// 设置标签
systray.SetLabel("voidraft")
systray.Label()
// 设置图标 // 设置图标
iconBytes, _ := assets.ReadFile("appicon.png") iconBytes, _ := assets.ReadFile("appicon.png")
systray.SetIcon(iconBytes) systray.SetIcon(iconBytes)
// 设置标签
systray.SetLabel("VoidRaft")
// 创建托盘菜单 // 创建托盘菜单
menu := app.NewMenu() menu := app.NewMenu()