feat(phase1): rebrand to TTRPG Player and drop Git updates feed

Rename product to TTRPG Player (TTRPGPlayer / com.ttrpgplayer.app), use .ttrpg.zip for new saves while keeping .dnd.zip import, accept TTRPG- and DND- license keys on client, and remove sync-update-feed plus CI push to DndGamePlayerUpdates.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-05-17 20:56:14 +08:00
parent 2c03921d23
commit 7c858ba633
27 changed files with 253 additions and 1328 deletions
+17 -11
View File
@@ -1,6 +1,14 @@
import { app, BrowserWindow, dialog, Menu, protocol } from 'electron';
import { ipcChannels, type SessionState } from '../shared/ipc/contracts';
import {
PROJECT_ZIP_OPEN_DIALOG_FILTER,
PROJECT_ZIP_SAVE_DIALOG_FILTER,
isProjectZipFileName,
normalizeSaveProjectZipPath,
projectZipFileNameFromBase,
stripProjectZipExtension,
} from '../shared/project/projectZipExtension';
import { EffectsStore } from './effects/effectsStore';
import { installIpcRouter, registerHandler, setLicenseAssert } from './ipc/router';
@@ -52,7 +60,7 @@ if (process.platform === 'win32' && app.isPackaged && process.env.DND_DISABLE_GP
}
if (process.platform === 'win32') {
app.setAppUserModelId('com.dndplayer.app');
app.setAppUserModelId('com.ttrpgplayer.app');
}
// Не вызывать app.setName() с другим именем: на Windows/macOS меняется каталог userData,
// и проекты в …/userData/projects «пропадают» из списка (остаются в старой папке).
@@ -447,7 +455,7 @@ async function main() {
registerHandler(ipcChannels.project.importZip, async () => {
const { canceled, filePaths } = await dialog.showOpenDialog({
properties: ['openFile'],
filters: [{ name: 'Проект DND (*.dnd.zip)', extensions: ['dnd.zip'] }],
filters: [PROJECT_ZIP_OPEN_DIALOG_FILTER],
});
if (canceled || !filePaths[0]) {
return { canceled: true as const };
@@ -473,21 +481,19 @@ async function main() {
if (!entry) {
throw new Error('Проект не найден');
}
const defaultName = entry.fileName.toLowerCase().endsWith('.dnd.zip')
? entry.fileName
: `${entry.fileName}.dnd.zip`;
const defaultName = isProjectZipFileName(entry.fileName)
? entry.fileName.toLowerCase().endsWith('.ttrpg.zip')
? entry.fileName
: projectZipFileNameFromBase(stripProjectZipExtension(entry.fileName))
: projectZipFileNameFromBase(stripProjectZipExtension(entry.fileName));
const { canceled, filePath } = await dialog.showSaveDialog({
defaultPath: defaultName,
filters: [{ name: 'Проект DND (*.dnd.zip)', extensions: ['dnd.zip'] }],
filters: [PROJECT_ZIP_SAVE_DIALOG_FILTER],
});
if (canceled || !filePath) {
return { canceled: true as const };
}
let dest = filePath;
const lower = dest.toLowerCase();
if (!lower.endsWith('.dnd.zip')) {
dest = lower.endsWith('.zip') ? dest.replace(/\.zip$/iu, '.dnd.zip') : `${dest}.dnd.zip`;
}
const dest = normalizeSaveProjectZipPath(filePath);
emitZipProgress({ kind: 'export', stage: 'copy', percent: 0, detail: 'Экспорт…' });
await projectStore.exportProjectZipToPath(projectId, dest, (p) => {
emitZipProgress({