diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db12289..73ce0d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: # electron-builder.yml просто копирует resources/zapret, а он у чистого чекаута пуст. - run: node scripts/fetch-zapret.mjs - # electron-builder заливает .exe и .blockmap двумя параллельными publisher'ами: оба + # electron-builder заливает артефакты несколькими параллельными publisher'ами: оба # проверяют, есть ли релиз с этим тегом, оба видят «нет» и оба лезут его создавать — # второй падает с 422 already_exists и уносит с собой свой файл (на v0.5.0 так потерялся # сам .exe). Создаём релиз заранее, тогда обоим остаётся только залить в готовый. @@ -74,6 +74,20 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # differentialPackage: false и publishAutoUpdate: false в electron-builder.yml убирают + # .blockmap и latest.yml из ассетов (electron-updater в приложении нет — они были бы + # мёртвым грузом). В релизе должен остаться только .exe и контрольная сумма к нему. + - name: Контрольная сумма + if: startsWith(github.ref, 'refs/tags/v') + shell: bash + run: | + set -euo pipefail + exe="$(ls release/*.exe)" + md5sum "$exe" | awk '{ print $1 }' > "$exe.md5" + gh release upload "$GITHUB_REF_NAME" "$exe.md5" --clobber + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Релиз создан с пустым описанием, поэтому список изменений дописываем сами: # коммиты между предыдущим тегом vX.Y.Z и текущим. - name: Описание релиза diff --git a/build/icon.icns b/build/icon.icns index 28644aa..1907d60 100644 Binary files a/build/icon.icns and b/build/icon.icns differ diff --git a/build/icon.ico b/build/icon.ico index 72c391e..980ffbe 100644 Binary files a/build/icon.ico and b/build/icon.ico differ diff --git a/build/icon.png b/build/icon.png index cf9e8b2..e3977e0 100644 Binary files a/build/icon.png and b/build/icon.png differ diff --git a/electron-builder.yml b/electron-builder.yml index 7393a73..9e91562 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -7,9 +7,14 @@ directories: # releaseType: release — публиковать релиз сразу, без черновика (draft — поведение по # умолчанию у electron-builder). С черновиком параллельная загрузка нескольких файлов иногда # создаёт два черновика с одним и тем же тегом вместо одного релиза. +# +# publishAutoUpdate: false — не заливать latest.yml. Это метаданные для electron-updater, +# которого в приложении нет (обновляется пользователь вручную, скачивая новый инсталлятор +# со страницы релиза) — файл был бы мёртвым грузом в ассетах. publish: provider: github releaseType: release + publishAutoUpdate: false files: - '!**/.vscode/*' @@ -54,6 +59,10 @@ nsis: # в src/main/zapret/service.win32.ts) — сама установка приложения per-user безопасна. oneClick: true perMachine: false + # Без electron-updater (см. publishAutoUpdate выше) differential-обновления не нужны — + # differentialPackage: false отключает генерацию .blockmap, который иначе всегда + # заливался бы в ассеты релиза рядом с инсталлятором. + differentialPackage: false # Удалять %APPDATA%\rknboost (списки сайтов, метка первого запуска) вместе с приложением. # По умолчанию electron-builder этого НЕ делает, и данные оставались бы в системе после # удаления. Обновление приложения под это не попадает — в шаблоне деинсталлятора стоит diff --git a/package-lock.json b/package-lock.json index 1c6097c..18fb987 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rknboost", - "version": "0.5.1", + "version": "0.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rknboost", - "version": "0.5.1", + "version": "0.5.2", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 756f4be..32645ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rknboost", - "version": "0.5.1", + "version": "0.5.2", "description": "Кроссплатформенное десктопное приложение на Electron + React + TypeScript", "main": "./out/main/index.js", "author": "RKNboost", diff --git a/resources/icon.png b/resources/icon.png index cf9e8b2..e3977e0 100644 Binary files a/resources/icon.png and b/resources/icon.png differ diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 5b7af93..7ac5c68 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -1,4 +1,4 @@ -import { BrowserWindow, ipcMain, nativeTheme, type IpcMainInvokeEvent } from 'electron' +import { app, BrowserWindow, ipcMain, nativeTheme, type IpcMainInvokeEvent } from 'electron' import type { IpcChannel, IpcHandlers, ThemeState } from '../shared/ipc-contract' import { uninstallApp } from './uninstall.win32' import { @@ -46,6 +46,10 @@ function themeState(): ThemeState { export function registerIpcHandlers(): void { handle('theme:get', () => themeState()) + // Ровно то же значение, что electron-builder кладёт в имя установщика и в + // «Установленные приложения» — оба берут его из "version" в package.json. + handle('app:version', () => app.getVersion()) + // Кнопка «Удалить приложение» есть в интерфейсе только на Windows (SettingsView.tsx), // но канал регистрируем всегда — так и должно быть по контракту, просто на других // платформах он никогда не вызывается. diff --git a/src/preload/index.ts b/src/preload/index.ts index e472f0c..d797a26 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -43,6 +43,9 @@ const api = { * службы только на Windows (см. SettingsView.tsx). */ platform: process.platform, + /** Версия запущенной сборки — из package.json через `app.getVersion()` в main. */ + getAppVersion: (): Promise => invoke('app:version'), + getTheme: (): Promise => invoke('theme:get'), onThemeChanged: (listener: (state: ThemeState) => void): (() => void) => subscribe('theme:changed', listener), diff --git a/src/renderer/src/components/SettingsView.tsx b/src/renderer/src/components/SettingsView.tsx index 39a7637..dad4e63 100644 --- a/src/renderer/src/components/SettingsView.tsx +++ b/src/renderer/src/components/SettingsView.tsx @@ -1,6 +1,7 @@ import { useState } from 'react' import type { ZapretListId, ZapretStatus } from '@shared/ipc-contract' import { GITHUB_URL } from '@shared/links' +import { useAppVersion } from '../hooks/useAppVersion' import { useZapretLists } from '../hooks/useZapretLists' import { LIST_TITLES } from '../lib/zapretListMeta' import ListEditor from './ListEditor' @@ -12,9 +13,6 @@ import ListEditor from './ListEditor' */ const isWindows = window.api.platform === 'win32' const APP_CHANNEL = 'beta' -// Держать в синхроне с "version" в package.json — оттуда её берёт electron-builder -// для имени установщика и для «Установленные приложения» в Windows. -const APP_VERSION = '0.4.0' export default function SettingsView({ onBack, @@ -27,6 +25,7 @@ export default function SettingsView({ }): React.JSX.Element { const { lists, autoHostlist, save, reset, clearAuto } = useZapretLists() const [openListId, setOpenListId] = useState(null) + const appVersion = useAppVersion() const openList = lists.find((list) => list.id === openListId) if (openList) { @@ -119,9 +118,13 @@ export default function SettingsView({

Поддержите звёздочкой

-

- {APP_CHANNEL}-{APP_VERSION}-{window.api.platform} -

+ {/* Пока версия не пришла из main, строки нет вовсе: иначе на первом кадре + мелькнуло бы «beta--win32» с пустотой на месте номера. */} + {appVersion && ( +

+ {APP_CHANNEL}-{appVersion}-{window.api.platform} +

+ )} {isWindows && (