Версия 0.5.2
Иконки: пересобраны из мастера 1024×1024. В .icns было одно представление 512×512 — macOS домасштабировала остальные сама; теперь все десять, от 16 до 1024. В .ico добавлен размер 24 и своя картинка вместо заглушки Electron. Релиз: differentialPackage и publishAutoUpdate выключены — .blockmap и latest.yml нужны electron-updater, которого в приложении нет, и лежали в ассетах мёртвым грузом. Вместо них CI кладёт рядом с установщиком .md5. Версия в интерфейсе больше не константа: renderer спрашивает её у main через app.getVersion(). Держать константу «в синхроне с package.json» вручную не вышло ни разу — она осталась на 0.4.0, и релизы 0.5.0 и 0.5.1 показали пользователю чужую версию.
This commit is contained in:
@@ -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: Описание релиза
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 121 KiB After Width: | Height: | Size: 147 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 633 KiB |
@@ -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 этого НЕ делает, и данные оставались бы в системе после
|
||||
# удаления. Обновление приложения под это не попадает — в шаблоне деинсталлятора стоит
|
||||
|
||||
Generated
+2
-2
@@ -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": {
|
||||
|
||||
+1
-1
@@ -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",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 633 KiB |
+5
-1
@@ -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),
|
||||
// но канал регистрируем всегда — так и должно быть по контракту, просто на других
|
||||
// платформах он никогда не вызывается.
|
||||
|
||||
@@ -43,6 +43,9 @@ const api = {
|
||||
* службы только на Windows (см. SettingsView.tsx). */
|
||||
platform: process.platform,
|
||||
|
||||
/** Версия запущенной сборки — из package.json через `app.getVersion()` в main. */
|
||||
getAppVersion: (): Promise<string> => invoke('app:version'),
|
||||
|
||||
getTheme: (): Promise<ThemeState> => invoke('theme:get'),
|
||||
onThemeChanged: (listener: (state: ThemeState) => void): (() => void) =>
|
||||
subscribe('theme:changed', listener),
|
||||
|
||||
@@ -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<ZapretListId | null>(null)
|
||||
const appVersion = useAppVersion()
|
||||
|
||||
const openList = lists.find((list) => list.id === openListId)
|
||||
if (openList) {
|
||||
@@ -119,9 +118,13 @@ export default function SettingsView({
|
||||
<p className="settings__support-hint">Поддержите звёздочкой</p>
|
||||
</section>
|
||||
|
||||
<p className="settings__version">
|
||||
{APP_CHANNEL}-{APP_VERSION}-{window.api.platform}
|
||||
</p>
|
||||
{/* Пока версия не пришла из main, строки нет вовсе: иначе на первом кадре
|
||||
мелькнуло бы «beta--win32» с пустотой на месте номера. */}
|
||||
{appVersion && (
|
||||
<p className="settings__version">
|
||||
{APP_CHANNEL}-{appVersion}-{window.api.platform}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{isWindows && (
|
||||
<button
|
||||
|
||||
@@ -52,7 +52,7 @@ export default function ZapretCard(): React.JSX.Element {
|
||||
)}
|
||||
|
||||
<div className="settings__field">
|
||||
<span className="settings__label">Стратегия</span>
|
||||
<span className="settings__label">Способ</span>
|
||||
{/* На время переключения список заблокирован: смена стратегии на работающем
|
||||
обходе останавливает и перенастраивает службу, и второй выбор посреди этого
|
||||
наложился бы на первый. */}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
/**
|
||||
* Версия запущенной сборки — та же, что в имени установщика и в «Установленных
|
||||
* приложениях»: main отдаёт её через `app.getVersion()`, то есть прямо из package.json.
|
||||
*
|
||||
* Раньше renderer держал версию своей константой с пометкой «держать в синхроне с
|
||||
* package.json». Синхронизировать вручную забыли: константа осталась на 0.4.0, и релизы
|
||||
* 0.5.0 и 0.5.1 показывали пользователю чужую версию. Спрашивать у main дороже на один
|
||||
* IPC-вызов, зато разъехаться уже нечему.
|
||||
*
|
||||
* `null` — версия ещё не пришла; показывать её в этот момент нечего.
|
||||
*/
|
||||
export function useAppVersion(): string | null {
|
||||
const [version, setVersion] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// Окно могло закрыться, пока шёл ответ — тогда setState уже некому применять.
|
||||
let cancelled = false
|
||||
void window.api.getAppVersion().then((value) => {
|
||||
if (!cancelled) setVersion(value)
|
||||
})
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [])
|
||||
|
||||
return version
|
||||
}
|
||||
@@ -101,6 +101,14 @@ export interface ZapretDiagnosticResult extends ZapretDiagnosticTarget {
|
||||
export interface IpcHandlers {
|
||||
'theme:get': () => ThemeState
|
||||
|
||||
/**
|
||||
* Версия приложения — `app.getVersion()`, то есть `"version"` из package.json той сборки,
|
||||
* которая сейчас запущена. Раньше renderer держал её отдельной константой «в синхроне
|
||||
* с package.json» вручную: константа осталась на 0.4.0 и релизы 0.5.0 и 0.5.1 показали
|
||||
* пользователю чужую версию. Спрашивать у main — единственный способ не разъехаться.
|
||||
*/
|
||||
'app:version': () => string
|
||||
|
||||
/** Windows: подтверждает диалогом ОС, запускает деинсталлятор и закрывает приложение. */
|
||||
'app:uninstall': () => void
|
||||
|
||||
|
||||
Reference in New Issue
Block a user