5 Commits

15 changed files with 84 additions and 54 deletions

View File

@@ -49,8 +49,5 @@ lto = true
codegen-units = 1
strip = true
[target.'cfg(windows)'.dependencies]
winres = "0.1"
[build-dependencies]
winres = "0.1"

View File

@@ -1,7 +1,5 @@
# MIT License
Copyright (c) 2026 [Your Name or Company]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

Binary file not shown.

BIN
assets/logo.icns Normal file

Binary file not shown.

View File

@@ -1,9 +1,11 @@
// build.rs
fn main() {
#[cfg(windows)]
{
let mut res = winres::WindowsResource::new();
res.set_icon("assets/logo.ico");
res.compile().unwrap();
if let Err(e) = winres::WindowsResource::new()
.set_icon("assets/logo.ico")
.compile()
{
eprintln!("warning: не удалось встроить иконку: {e}");
}
}
}

View File

@@ -1,4 +1,4 @@
.PHONY: all clean build-mac build-windows build-linux build-linux-musl package help quick package-single icons favicon
.PHONY: all clean build-mac build-windows build-linux build-linux-musl package help quick package-single icons
# Название проекта
PROJECT_NAME := ae_anons
@@ -44,9 +44,9 @@ help:
@echo " make package - Создать пакеты для всех платформ"
@echo " make package-single - Создать пакет для текущей платформы"
@echo ""
@echo "$(GREEN)Иконки:$(NC)"
@echo " make icons - Создать все иконки (logo.ico, logo.icns, favicon.ico)"
@echo " make favicon - Создать только favicon.ico"
@echo "$(GREEN)Подготовка ресурсов:$(NC)"
@echo " make setup - Подготовить иконки (логотипы, favicon)"
@echo " make setup-fontawesome-manual - Скачать и исправить all.min.css (если удалён)"
@echo ""
@echo "$(GREEN)Очистка:$(NC)"
@echo " make clean - Очистить все сборки"
@@ -67,15 +67,14 @@ define measure_time
$(2); \
end=$$(date +%s); \
duration=$$((end - start)); \
echo "$(1): $$duration сек" >> $(TIMING_FILE); \
if [ $$duration -ge 60 ]; then \
min=$$((duration / 60)); \
sec=$$((duration % 60)); \
time_str="$${min}m $${sec}s"; \
echo "$(GREEN)$(1) завершён за $${min}m $${sec}s$(NC)"; \
else \
time_str="$${duration}s"; \
fi; \
echo "$(1): $$time_str" >> $(TIMING_FILE); \
echo "$(GREEN)$(1) завершён за $$time_str$(NC)"
echo "$(GREEN)$(1) завершён за $${duration}s$(NC)"; \
fi
endef
define print_timing_summary
@@ -100,41 +99,56 @@ define print_timing_summary
endef
# ============================================
# ИКОНКИ
# ПОДГОТОВКА РЕСУРСОВ
# ============================================
icons: favicon
@echo "$(GREEN)Создание иконок для Windows и macOS...$(NC)"
setup: icons
@echo "$(GREEN)Все статические ресурсы подготовлены$(NC)"
# Генерация иконок (favicon, .ico, .icns) из логотипа
icons:
@echo "$(GREEN)🎨 Генерация иконок...$(NC)"
@if [ "$(IMAGEMAGICK)" = "false" ]; then \
echo "$(RED)❌ ImageMagick не установлен. Установите: brew install imagemagick$(NC)"; \
exit 1; \
fi
# favicon.ico
@$(IMAGEMAGICK) assets/logo.png -define icon:auto-resize=48,32,16 src/static/favicon.ico
@echo "$(GREEN) ✓ src/static/favicon.ico$(NC)"
# Windows .ico
@$(IMAGEMAGICK) assets/logo.png -define icon:auto-resize=256,128,64,48,32,16 assets/logo.ico
@echo "$(GREEN) ✓ assets/logo.ico$(NC)"
# macOS .icns
@mkdir -p assets/icon.iconset
@sips -z 16 16 assets/logo.png --out assets/icon.iconset/icon_16x16.png 2>/dev/null
@sips -z 32 32 assets/logo.png --out assets/icon.iconset/icon_16x16@2x.png 2>/dev/null
@sips -z 32 32 assets/logo.png --out assets/icon.iconset/icon_32x32.png 2>/dev/null
@sips -z 64 64 assets/logo.png --out assets/icon.iconset/icon_32x32@2x.png 2>/dev/null
@sips -z 128 128 assets/logo.png --out assets/icon.iconset/icon_128x128.png 2>/dev/null
@sips -z 256 256 assets/logo.png --out assets/icon.iconset/icon_128x128@2x.png 2>/dev/null
@sips -z 256 256 assets/logo.png --out assets/icon.iconset/icon_256x256.png 2>/dev/null
@sips -z 512 512 assets/logo.png --out assets/icon.iconset/icon_256x256@2x.png 2>/dev/null
@sips -z 512 512 assets/logo.png --out assets/icon.iconset/icon_512x512.png 2>/dev/null
@iconutil -c icns assets/icon.iconset -o assets/logo.icns 2>/dev/null
@sips -z 16 16 assets/logo.png --out assets/icon.iconset/icon_16x16.png 2>/dev/null || true
@sips -z 32 32 assets/logo.png --out assets/icon.iconset/icon_16x16@2x.png 2>/dev/null || true
@sips -z 32 32 assets/logo.png --out assets/icon.iconset/icon_32x32.png 2>/dev/null || true
@sips -z 64 64 assets/logo.png --out assets/icon.iconset/icon_32x32@2x.png 2>/dev/null || true
@sips -z 128 128 assets/logo.png --out assets/icon.iconset/icon_128x128.png 2>/dev/null || true
@sips -z 256 256 assets/logo.png --out assets/icon.iconset/icon_128x128@2x.png 2>/dev/null || true
@sips -z 256 256 assets/logo.png --out assets/icon.iconset/icon_256x256.png 2>/dev/null || true
@sips -z 512 512 assets/logo.png --out assets/icon.iconset/icon_256x256@2x.png 2>/dev/null || true
@sips -z 512 512 assets/logo.png --out assets/icon.iconset/icon_512x512.png 2>/dev/null || true
@iconutil -c icns assets/icon.iconset -o assets/logo.icns 2>/dev/null || true
@rm -rf assets/icon.iconset
@echo "$(GREEN) ✓ assets/logo.icns$(NC)"
favicon:
@echo "$(GREEN)Создание favicon.ico...$(NC)"
@if [ "$(IMAGEMAGICK)" = "false" ]; then \
echo "$(RED)❌ ImageMagick не установлен. Установите: brew install imagemagick$(NC)"; \
exit 1; \
# Восстановить CSS Font Awesome вручную (если файл удалён)
setup-fontawesome-manual:
@echo "$(GREEN)📥 Скачивание Font Awesome CSS...$(NC)"
@curl -sL -o src/static/fontawesome/all.min.css $(FONTAWESOME_CSS_URL)
@sed -i '' -E 's|(\.\./)*webfonts/|/static/fontawesome/webfonts/|g' \
src/static/fontawesome/all.min.css
@echo "$(GREEN)✓ CSS восстановлен и пути исправлены$(NC)"
# ============================================
# ИКОНКА ДЛЯ WINDOWS .EXE
# ============================================
windows-icon:
@if [ ! -f assets/logo.ico ]; then \
echo "$(YELLOW)logo.ico не найден, запускаю генерацию иконок...$(NC)"; \
$(MAKE) icons; \
fi
@$(IMAGEMAGICK) assets/logo.png -define icon:auto-resize=48,32,16 src/static/favicon.ico
@echo "$(GREEN) ✓ src/static/favicon.ico$(NC)"
# ============================================
# ОПРЕДЕЛЕНИЕ ПЛАТФОРМЫ
@@ -194,7 +208,7 @@ quick-linux:
@echo "$(GREEN)✅ Пакет: $(BINARIES_DIR)/$(PROJECT_NAME)-v$(VERSION)-linux-$(UNAME_M)/$(NC)"
@$(call print_timing_summary)
quick-windows:
quick-windows: windows-icon
@rm -f $(TIMING_FILE)
@if command -v x86_64-w64-mingw32-gcc >/dev/null 2>&1; then \
$(call measure_time,"🪟 Windows x64",cargo build --target x86_64-pc-windows-gnu --release); \
@@ -217,7 +231,7 @@ build-mac:
@echo "$(GREEN)🍎 Сборка для macOS...$(NC)"
@time cargo build --release
build-windows:
build-windows: windows-icon
@echo "$(GREEN)🪟 Сборка для Windows x86_64...$(NC)"
@time cargo build --target x86_64-pc-windows-gnu --release

View File

@@ -1,7 +1,5 @@
# MIT License
Copyright (c) 2026 [Your Name or Company]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View File

@@ -1,7 +1,5 @@
# MIT License
Copyright (c) 2026 [Your Name or Company]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View File

@@ -1,7 +1,5 @@
# MIT License
Copyright (c) 2026 [Your Name or Company]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View File

@@ -1,7 +1,5 @@
# MIT License
Copyright (c) 2026 [Your Name or Company]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights

View File

@@ -11,7 +11,6 @@ use serde::Serialize;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::sync::Mutex;
use tower_http::services::ServeDir;
use tower_http::trace::TraceLayer;
#[derive(Clone)]
@@ -89,19 +88,26 @@ pub async fn run_web_server(config: Config) -> anyhow::Result<()> {
.route("/favicon.ico", get(favicon))
.route("/static/style.css", get(style_css))
.route("/static/fontawesome/all.min.css", get(fontawesome_css))
.route(
"/static/fontawesome/webfonts/fa-solid-900.woff2",
get(fa_solid_woff2),
)
.route(
"/static/fontawesome/webfonts/fa-regular-400.woff2",
get(fa_regular_woff2),
)
.route(
"/static/fontawesome/webfonts/fa-brands-400.woff2",
get(fa_brands_woff2),
)
.route("/assets/logo.png", get(logo_png))
.route("/api/jobs", get(list_jobs))
.route("/api/generate", post(generate_jobs))
.route("/api/cleanup", post(cleanup_jobs))
.route("/api/status", get(get_status))
.route("/api/jobs/stop-all", post(stop_all_jobs))
.nest_service(
"/static/fontawesome/webfonts",
ServeDir::new("src/static/fontawesome/webfonts"),
)
.layer(TraceLayer::new_for_http())
.with_state(state);
let addr: SocketAddr = format!("0.0.0.0:{}", web_port).parse()?;
log::info!("Web server listening on http://{}", addr);
@@ -229,6 +235,27 @@ async fn stop_all_jobs(State(state): State<AppState>) -> Result<impl IntoRespons
Ok((StatusCode::OK, format!("Stopped {} jobs", stopped)))
}
async fn fa_solid_woff2() -> impl IntoResponse {
(
[(CONTENT_TYPE, "font/woff2")],
include_bytes!("static/fontawesome/webfonts/fa-solid-900.woff2").as_slice(),
)
}
async fn fa_regular_woff2() -> impl IntoResponse {
(
[(CONTENT_TYPE, "font/woff2")],
include_bytes!("static/fontawesome/webfonts/fa-regular-400.woff2").as_slice(),
)
}
async fn fa_brands_woff2() -> impl IntoResponse {
(
[(CONTENT_TYPE, "font/woff2")],
include_bytes!("static/fontawesome/webfonts/fa-brands-400.woff2").as_slice(),
)
}
struct AppError(StatusCode, String);
impl IntoResponse for AppError {