55 Commits
Author SHA1 Message Date
M_Viper ce5a655758 Delete 13 files via Git Manager GUI 2026-10-22 07:39:41 +00:00
M_Viper 7660b5de1a Delete data/credentials.json via Git Manager GUI 2026-10-22 07:39:34 +00:00
M_Viper 50705d1197 Delete .claude/settings.local.json via Git Manager GUI 2026-10-22 07:39:18 +00:00
M_Viper 1f635d33cc Upload via GUI (60 Dateien) 2026-10-22 07:22:51 +00:00
M_Viper 38a75bc720 Upload via GUI (60 Dateien) 2026-10-22 07:22:49 +00:00
M_Viper ead123c62b Upload via GUI (12 Dateien) 2026-10-22 07:16:16 +00:00
M_Viper 9b3aed6f0a Upload via GUI (28 Dateien) 2026-10-22 07:15:59 +00:00
M_Viper 99d9629e25 Upload via GUI (10 Dateien) 2026-10-22 07:15:41 +00:00
M_Viper 85a222a9fb Upload via GUI (7543 Dateien) 2026-10-22 07:03:23 +00:00
M_Viper dedb09b9c6 Upload via GUI (7543 Dateien) 2026-10-22 07:03:19 +00:00
M_Viper c45ad3ba32 Upload via GUI (7543 Dateien) 2026-10-22 07:03:16 +00:00
M_Viper 937c72ce4a Upload via GUI (7543 Dateien) 2026-10-22 07:03:12 +00:00
M_Viper 61d6d11a2f Upload via GUI (7543 Dateien) 2026-10-22 07:03:09 +00:00
M_Viper ef911afb06 Upload via GUI (7543 Dateien) 2026-10-22 07:03:04 +00:00
M_Viper 4f9494ae7b Upload via GUI (7543 Dateien) 2026-10-22 07:03:00 +00:00
M_Viper 37820af6dd Upload via GUI (7543 Dateien) 2026-10-22 07:02:57 +00:00
M_Viper 9c6a69cc53 Upload via GUI (7543 Dateien) 2026-10-22 07:02:52 +00:00
M_Viper eb549d3975 Upload via GUI (7543 Dateien) 2026-10-22 07:02:42 +00:00
M_Viper b2314f6fe6 Upload via GUI (7543 Dateien) 2026-10-22 07:02:28 +00:00
M_Viper 42fb8dfe9b Upload via GUI (7543 Dateien) 2026-10-22 07:02:04 +00:00
M_Viper 54baf9b874 Upload via GUI (7543 Dateien) 2026-10-22 07:01:41 +00:00
M_Viper 8d29040b57 Upload via GUI (7543 Dateien) 2026-10-22 07:01:11 +00:00
M_Viper 8c7b2ddf47 Upload via GUI (7543 Dateien) 2026-10-22 07:00:36 +00:00
M_Viper 03f4fa6fbc Upload via GUI (7543 Dateien) 2026-10-22 06:59:59 +00:00
M_Viper a57786fe54 Upload via GUI (7543 Dateien) 2026-10-22 06:59:38 +00:00
M_Viper 6f73a87314 Upload via GUI (7543 Dateien) 2026-10-22 06:59:13 +00:00
M_Viper 7ef5522258 Upload via GUI (7543 Dateien) 2026-10-22 06:58:47 +00:00
M_Viper 860c714301 Upload via GUI (7543 Dateien) 2026-10-22 06:58:16 +00:00
M_Viper 68133f4d0f Upload via GUI (7543 Dateien) 2026-10-22 06:57:52 +00:00
M_Viper 75cc88a011 Upload via GUI (7543 Dateien) 2026-10-22 06:57:20 +00:00
M_Viper bac355eabb Upload via GUI (7543 Dateien) 2026-10-22 06:56:47 +00:00
M_Viper d7658c873f Upload via GUI (7543 Dateien) 2026-10-22 06:56:30 +00:00
M_Viper 8830aac76c Upload via GUI (7543 Dateien) 2026-10-22 06:56:23 +00:00
M_Viper 336d9e600b Upload via GUI (7543 Dateien) 2026-10-22 06:56:21 +00:00
M_Viper d6518698b1 Upload via GUI (7543 Dateien) 2026-10-22 06:56:19 +00:00
M_Viper e4585e50ee Upload via GUI (7543 Dateien) 2026-10-22 06:56:17 +00:00
M_Viper 12a2f5faa9 Upload via GUI (7543 Dateien) 2026-10-22 06:56:16 +00:00
M_Viper 8aede65bd7 Upload via GUI (7543 Dateien) 2026-10-22 06:56:15 +00:00
M_Viper ae68900363 Upload via GUI (7543 Dateien) 2026-10-22 06:55:39 +00:00
M_Viper 81c541a0b5 Upload via GUI (7543 Dateien) 2026-10-22 06:55:33 +00:00
M_Viper 089257d740 Upload via GUI (7543 Dateien) 2026-10-22 06:55:01 +00:00
M_Viper 2ecc57c761 Upload via GUI (7543 Dateien) 2026-10-22 06:54:55 +00:00
M_Viper 4654eed12c Upload via GUI (7543 Dateien) 2026-10-22 06:54:26 +00:00
M_Viper 434a4e1c7b Upload via GUI (7543 Dateien) 2026-10-22 06:54:18 +00:00
M_Viper a0546c562d Upload via GUI (7543 Dateien) 2026-10-22 06:54:05 +00:00
M_Viper 264f1b7e45 Upload via GUI (7543 Dateien) 2026-10-22 06:54:02 +00:00
M_Viper 3b31c5893c Upload via GUI (7543 Dateien) 2026-10-22 06:53:49 +00:00
M_Viper 047196c4d0 Upload via GUI (7543 Dateien) 2026-10-22 06:53:45 +00:00
M_Viper 5571f225d5 Upload via GUI (27 Dateien) 2026-08-13 07:21:45 +00:00
Git Manager GUI 565835418e Upload via GUI (31 Dateien) 2026-07-16 08:01:04 +02:00
Git Manager GUI 3ed561fe78 Upload via Git Manager GUI 2026-05-24 22:33:27 +02:00
Git Manager GUI fe6c31793e Upload via Git Manager GUI 2026-05-24 22:33:22 +02:00
Git Manager GUI 4bb948d665 Upload via Git Manager GUI 2026-05-24 22:33:20 +02:00
Git Manager GUI 5c792eb1a8 Upload folder via GUI - src 2026-05-24 22:33:18 +02:00
Git Manager GUI 309babf849 Upload folder via GUI - renderer 2026-05-24 22:33:16 +02:00
1504 changed files with 152104 additions and 9087 deletions
+58
View File
@@ -0,0 +1,58 @@
# ===== Zugangsdaten / Secrets (NIE hochladen!) =====
/data/
credentials.json
*.env
.env*
*.pem
*.key
*.pfx
*.p12
# ===== Abhängigkeiten =====
node_modules/
.npm/
.cache/
# ===== Build-Ausgaben =====
dist/
out/
release/
*.exe
*.blockmap
*.sha256
*.sha256sum
# ===== .NET Installer (Visual Studio / dotnet) =====
installer/bin/
installer/obj/
**/bin/
**/obj/
.vs/
*.user
*.suo
# ===== Große gebündelte Binaries (MinGit, ca. 93 MB) =====
vendor/mingit/
# ===== Laufzeitdaten / Backups / Repos =====
/repos/
/backup/
*.zip
*.rar
*.7z
# ===== Logs =====
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# ===== Editor / OS =====
.vscode/
.idea/
.DS_Store
Thumbs.db
desktop.ini
# ===== Claude Code (lokale Einstellungen) =====
.claude/settings.local.json
+116
View File
@@ -0,0 +1,116 @@
const test = require('node:test');
const assert = require('node:assert');
const http = require('node:http');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
require('../src/git/gitBinary.js').useBundledGit();
const { registerFeatureIpc } = require('../src/features/featuresIpc.js');
// Drei Repos; das ZIP von "langsam" kommt in kleinen Stücken über ~3 s, damit ein Abbruch mitten hineinfällt
function fakeGitea() {
const server = http.createServer((req, res) => {
const u = new URL(req.url, 'http://x');
const send = (code, obj) => { res.statusCode = code; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(obj)); };
if (u.pathname === '/api/v1/user/repos') {
if (u.searchParams.get('page') !== '1') return send(200, []);
const port = server.address().port;
return send(200, ['eins', 'langsam', 'drei'].map(name => ({
name, owner: { login: 'M_Viper' }, default_branch: 'main', empty: false,
clone_url: `http://127.0.0.1:${port}/M_Viper/${name}.git`
})));
}
const m = u.pathname.match(/^\/api\/v1\/repos\/M_Viper\/(\w+)\/archive\/main\.zip$/);
if (m) {
const total = 64 * 1024;
res.writeHead(200, { 'Content-Type': 'application/zip', 'Content-Length': String(total) });
if (m[1] !== 'langsam') return res.end(Buffer.alloc(total, 1));
let sent = 0;
const t = setInterval(() => {
if (res.destroyed) return clearInterval(t);
res.write(Buffer.alloc(2048, 1));
sent += 2048;
if (sent >= total) { clearInterval(t); res.end(); }
}, 100);
return;
}
send(404, { message: 'not found' });
});
return new Promise(r => server.listen(0, '127.0.0.1', () => r({ server, url: `http://127.0.0.1:${server.address().port}` })));
}
function setup(url) {
const handlers = {};
const events = [];
registerFeatureIpc({
ipcMain: { handle: (name, fn) => { handlers[name] = fn; } },
app: { getPath: () => fs.mkdtempSync(path.join(os.tmpdir(), 'gm-ud-')) },
readCredentials: () => ({ giteaURL: url, giteaToken: 't' }),
buildItemsFromPaths: async () => ({ items: [], skipped: [], ignored: [] }),
clearGitTransportBlock: () => false,
broadcast: (channel, p) => { if (channel === 'repo-backup-progress') events.push(p); }
});
return { call: (name, data) => handlers[name]({ sender: { send() {} } }, data), events };
}
test('Backup meldet Fortschritt: Phasen, aktuelles Repo, Bytes und Ergebnis je Repo', async () => {
const g = await fakeGitea();
try {
const { call, events } = setup(g.url);
const target = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-bk-'));
await call('repo-backup-set-config', { targetDir: target });
const r = await call('repo-backup-run-now', {});
assert.strictEqual(r.summary.ok, 3, JSON.stringify(r));
const phases = [...new Set(events.map(e => e.phase))];
assert.deepStrictEqual(phases, ['start', 'list', 'running', 'done']);
assert.deepStrictEqual(events.find(e => e.phase === 'running').repos, ['M_Viper/eins', 'M_Viper/langsam', 'M_Viper/drei']);
assert.ok(events.some(e => e.repo === 'M_Viper/langsam' && e.bytes > 0 && e.bytesTotal === 64 * 1024), 'Download-Fortschritt fehlt');
const last = events[events.length - 1];
assert.strictEqual(last.results.length, 3);
assert.ok(last.results.every(x => x.ok && x.method === 'ZIP'));
assert.ok(!events.some(e => 'abort' in e), 'interne Felder dürfen nicht nach außen gehen');
// Während kein Backup läuft, gibt es auch keinen Zwischenstand
const state = await call('repo-backup-get-config', {});
assert.strictEqual(state.running, false);
assert.strictEqual(state.progress, null);
} finally {
g.server.close();
}
});
test('Abbrechen beendet den laufenden ZIP-Download sofort und überspringt den Rest', async () => {
const g = await fakeGitea();
try {
const { call, events } = setup(g.url);
const target = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-bk-'));
await call('repo-backup-set-config', { targetDir: target });
const started = Date.now();
const running = call('repo-backup-run-now', {});
// warten, bis der langsame Download läuft
while (!events.some(e => e.repo === 'M_Viper/langsam' && e.bytes > 0)) {
if (Date.now() - started > 10000) throw new Error('Download startete nicht');
await new Promise(r => setTimeout(r, 50));
}
const state = await call('repo-backup-get-config', {});
assert.strictEqual(state.running, true);
assert.strictEqual(state.progress.repo, 'M_Viper/langsam');
assert.strictEqual((await call('repo-backup-cancel', {})).ok, true);
const r = await running;
assert.ok(Date.now() - started < 2500, 'Abbruch muss den Download sofort beenden');
assert.strictEqual(r.ok, false);
assert.strictEqual(r.summary.cancelled, true);
assert.strictEqual(r.summary.ok, 1);
assert.strictEqual(r.summary.skipped, 2);
// keine halbe Datei zurücklassen
const archiv = path.join(target, 'M_Viper', 'langsam-archiv');
assert.deepStrictEqual(fs.existsSync(archiv) ? fs.readdirSync(archiv) : [], []);
assert.strictEqual((await call('repo-backup-cancel', {})).ok, false);
} finally {
g.server.close();
}
});
+60
View File
@@ -0,0 +1,60 @@
const test = require('node:test');
const assert = require('node:assert');
const http = require('node:http');
const { deleteGiteaPathsBatched } = require('../src/git/apiHandler.js');
// Minimaler Gitea-Nachbau: Repo-Info, Trees-API (seitenweise) und Mehrfach-Commit-Endpunkt.
function fakeGitea(paths, { perPage = 1000, failPath = null } = {}) {
const files = new Map(paths.map((p, i) => [p, `sha${i}`]));
const commits = [];
const server = http.createServer((req, res) => {
const u = new URL(req.url, 'http://x');
const send = (code, obj) => { res.statusCode = code; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(obj)); };
if (req.method === 'GET' && u.pathname === '/api/v1/repos/o/r') return send(200, { default_branch: 'main' });
if (req.method === 'GET' && u.pathname === '/api/v1/repos/o/r/git/trees/main') {
const page = Number(u.searchParams.get('page') || 1);
const all = [...files.keys()].map(p => ({ path: p, type: 'blob', sha: files.get(p) }));
const slice = all.slice((page - 1) * perPage, page * perPage);
return send(200, { tree: slice, truncated: page * perPage < all.length, total_count: all.length, page });
}
if (req.method === 'POST' && u.pathname === '/api/v1/repos/o/r/contents') {
let body = '';
req.on('data', c => body += c);
req.on('end', () => {
const { files: ops } = JSON.parse(body);
if (failPath && ops.some(o => o.path === failPath)) return send(422, { message: 'kaputt' });
for (const o of ops) {
assert.strictEqual(o.operation, 'delete');
assert.strictEqual(o.sha, files.get(o.path));
files.delete(o.path);
}
commits.push(ops.length);
send(201, {});
});
return;
}
send(404, { message: 'object does not exist' });
});
return new Promise(r => server.listen(0, '127.0.0.1', () => r({ server, files, commits, url: `http://127.0.0.1:${server.address().port}` })));
}
test('Ordner wird paketweise gelöscht, Nachbarn bleiben', async () => {
const paths = [...Array.from({ length: 2500 }, (_, i) => `mobile/build/f${i}.dex`), 'mobile/build.gradle.kts', 'mobile/src/A.kt'];
const g = await fakeGitea(paths, { perPage: 1000 });
try {
const r = await deleteGiteaPathsBatched({ token: 't', url: g.url, owner: 'o', repo: 'r', prefix: 'mobile/build' });
assert.strictEqual(r.deleted, 2500);
assert.deepStrictEqual(g.commits, Array(25).fill(100));
assert.deepStrictEqual([...g.files.keys()].sort(), ['mobile/build.gradle.kts', 'mobile/src/A.kt']);
} finally { g.server.close(); }
});
test('eine fehlerhafte Datei blockiert nicht das ganze Paket', async () => {
const paths = Array.from({ length: 10 }, (_, i) => `x/f${i}`);
const g = await fakeGitea(paths, { failPath: 'x/f3' });
try {
const r = await deleteGiteaPathsBatched({ token: 't', url: g.url, owner: 'o', repo: 'r', paths });
assert.strictEqual(r.deleted, 9);
assert.deepStrictEqual(r.failed.map(f => f.path), ['x/f3']);
} finally { g.server.close(); }
});
+162
View File
@@ -0,0 +1,162 @@
const test = require('node:test');
const assert = require('node:assert');
const http = require('node:http');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
require('../src/git/gitBinary.js').useBundledGit();
const { registerFeatureIpc, parsePorcelainZ } = require('../src/features/featuresIpc.js');
const { scanForSecrets, checkName } = require('../src/features/secretScan.js');
// Minimaler Gitea-Nachbau für Diagnose, PRs/Issues und Backup
function fakeGitea() {
const calls = [];
const comments = [];
const server = http.createServer((req, res) => {
const u = new URL(req.url, 'http://x');
calls.push(`${req.method} ${u.pathname}`);
const send = (code, obj) => { res.statusCode = code; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(obj)); };
let body = '';
req.on('data', c => body += c);
req.on('end', () => {
const p = u.pathname;
if (p === '/api/v1/version') return send(200, { version: '1.24.0' });
if (p === '/api/v1/user') return send(200, { login: 'M_Viper' });
if (p === '/api/v1/user/repos') {
if (u.searchParams.get('page') && u.searchParams.get('page') !== '1') return send(200, []);
return send(200, [{ name: 'deskhub', owner: { login: 'M_Viper' }, default_branch: 'main', empty: false,
clone_url: `http://127.0.0.1:${server.address().port}/M_Viper/deskhub.git` }]);
}
if (p === '/api/v1/repos/M_Viper/deskhub/pulls') return send(200, [{ number: 3, title: 'Fix', state: 'open', user: { login: 'a' }, labels: [], head: { label: 'fix' }, base: { label: 'main' }, mergeable: true }]);
if (p === '/api/v1/repos/M_Viper/deskhub/issues' && req.method === 'GET') return send(200, [{ number: 5, title: 'Bug', state: 'open', labels: [{ name: 'bug', color: 'ff0000' }] }]);
if (p === '/api/v1/repos/M_Viper/deskhub/issues' && req.method === 'POST') return send(201, { number: 6, ...JSON.parse(body), state: 'open', labels: [] });
if (p === '/api/v1/repos/M_Viper/deskhub/issues/5/comments' && req.method === 'POST') { comments.push(JSON.parse(body).body); return send(201, {}); }
if (p === '/api/v1/repos/M_Viper/deskhub/issues/5/comments') return send(200, comments.map((b, i) => ({ id: i, body: b, user: { login: 'M_Viper' } })));
if (p === '/api/v1/repos/M_Viper/deskhub/issues/5') return send(200, { number: 5, title: 'Bug', state: 'open', labels: [] });
if (p === '/api/v1/repos/M_Viper/deskhub/pulls/3/merge') return send(200, {});
if (p === '/api/v1/repos/M_Viper/deskhub/archive/main.zip') {
res.statusCode = 200; res.setHeader('Content-Type', 'application/zip'); return res.end(Buffer.from('PK\u0003\u0004fake'));
}
send(404, { message: 'not found' });
});
});
return new Promise(r => server.listen(0, '127.0.0.1', () => r({ server, calls, comments, url: `http://127.0.0.1:${server.address().port}` })));
}
function setup(url) {
const handlers = {};
const userData = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-ud-'));
registerFeatureIpc({
ipcMain: { handle: (name, fn) => { handlers[name] = fn; } },
app: { getPath: () => userData },
readCredentials: () => ({ giteaURL: url, giteaToken: 'geheim123' }),
buildItemsFromPaths: async (paths) => ({
items: paths.map(p => ({ localFile: p, targetPath: path.basename(p) })), skipped: [], ignored: []
}),
clearGitTransportBlock: () => false
});
const call = (name, data) => handlers[name]({ sender: { send() {} } }, data);
return { call, userData };
}
test('Geheimnisse werden an Name und Inhalt erkannt, Vorlagen nicht', async () => {
assert.ok(checkName('google-services.json'));
assert.ok(checkName('.env'));
assert.ok(checkName('release.keystore'));
assert.strictEqual(checkName('.env.example'), null);
assert.strictEqual(checkName('README.md'), null);
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-sec-'));
const bot = path.join(dir, 'bot.js');
fs.writeFileSync(bot, 'const TOKEN = "123456789:AA' + 'b'.repeat(33) + '";');
const clean = path.join(dir, 'app.js');
fs.writeFileSync(clean, 'console.log("hallo")');
const found = await scanForSecrets([{ localFile: bot, size: fs.statSync(bot).size }, { localFile: clean, size: fs.statSync(clean).size }]);
assert.match(found.get(bot), /Telegram/);
assert.strictEqual(found.has(clean), false);
fs.rmSync(dir, { recursive: true, force: true });
});
test('git status -z wird korrekt gelesen (inkl. Umbenennung)', () => {
const files = parsePorcelainZ(' M src/a.js\0?? neu.txt\0R neu/name.js\0alt/name.js\0D weg.txt\0');
assert.deepStrictEqual(files.map(f => [f.code, f.path, f.from]), [['M', 'src/a.js', null], ['?', 'neu.txt', null], ['R', 'neu/name.js', 'alt/name.js'], ['D', 'weg.txt', null]]);
});
test('Lokale Änderungen: Status, Diff und Commit nur der ausgewählten Dateien', async () => {
const { call } = setup('http://127.0.0.1:1');
const repo = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-local-'));
const git = (...a) => spawnSync('git', ['-C', repo, '-c', 'user.name=t', '-c', 'user.email=t@t', ...a], { encoding: 'utf8' });
git('init', '-q');
fs.writeFileSync(path.join(repo, 'a.txt'), 'eins\n');
git('add', '.'); git('commit', '-qm', 'start');
fs.writeFileSync(path.join(repo, 'a.txt'), 'zwei\n');
fs.writeFileSync(path.join(repo, 'b.txt'), 'neu\n');
const st = await call('local-git', { action: 'status', folder: repo });
assert.strictEqual(st.ok, true);
assert.deepStrictEqual(st.files.map(f => f.path).sort(), ['a.txt', 'b.txt']);
const diff = await call('local-git', { action: 'diff', folder: repo, file: 'a.txt', code: 'M' });
assert.match(diff.diff, /-eins/);
assert.match(diff.diff, /\+zwei/);
const c = await call('local-git', { action: 'commit', folder: repo, files: ['a.txt'], message: 'nur a' });
assert.strictEqual(c.ok, true, c.error);
const after = await call('local-git', { action: 'status', folder: repo });
assert.deepStrictEqual(after.files.map(f => f.path), ['b.txt']);
const notRepo = await call('local-git', { action: 'status', folder: os.tmpdir() + path.sep + 'gm-gibtsnicht-' + Date.now() });
assert.strictEqual(notRepo.ok, false);
fs.rmSync(repo, { recursive: true, force: true });
});
test('Upload-Vorschau markiert Geheimnisse', async () => {
const { call } = setup('http://127.0.0.1:1');
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-prev-'));
const a = path.join(dir, 'main.kt'); fs.writeFileSync(a, 'fun main() {}');
const g = path.join(dir, 'google-services.json'); fs.writeFileSync(g, '{}');
const r = await call('preview-upload-paths', { paths: [a, g], destPath: '' });
assert.strictEqual(r.ok, true);
assert.strictEqual(r.secretCount, 1);
assert.ok(r.files.find(f => f.localFile === g).secret);
fs.rmSync(dir, { recursive: true, force: true });
});
test('Diagnose, PRs/Issues und Backup gegen einen nachgebauten Server', async () => {
const g = await fakeGitea();
const { call } = setup(g.url);
try {
const d = await call('run-server-diagnosis', {});
const byLabel = Object.fromEntries(d.checks.map(c => [c.label, c.status]));
assert.strictEqual(byLabel['Gitea-API'], 'ok');
assert.strictEqual(byLabel['Token'], 'ok');
assert.strictEqual(byLabel['Erreichbar über IPv4'], 'ok');
assert.ok(!JSON.stringify(d).includes('geheim123'), 'Token darf nicht in der Diagnose stehen');
const pulls = await call('gitea-collab', { action: 'listPulls', owner: 'M_Viper', repo: 'deskhub' });
assert.strictEqual(pulls.items[0].head, 'fix');
const issues = await call('gitea-collab', { action: 'listIssues', owner: 'M_Viper', repo: 'deskhub' });
assert.strictEqual(issues.items[0].labels[0].name, 'bug');
assert.strictEqual((await call('gitea-collab', { action: 'comment', owner: 'M_Viper', repo: 'deskhub', index: 5, body: 'Danke' })).ok, true);
const detail = await call('gitea-collab', { action: 'get', owner: 'M_Viper', repo: 'deskhub', index: 5 });
assert.strictEqual(detail.comments[0].body, 'Danke');
assert.strictEqual((await call('gitea-collab', { action: 'merge', owner: 'M_Viper', repo: 'deskhub', index: 3, style: 'squash' })).ok, true);
assert.strictEqual((await call('gitea-collab', { action: 'createIssue', owner: 'M_Viper', repo: 'deskhub', title: 'Neu' })).item.number, 6);
const target = fs.mkdtempSync(path.join(os.tmpdir(), 'gm-bk-'));
await call('repo-backup-set-config', { targetDir: target, interval: 'daily', keep: 2 });
for (let i = 0; i < 3; i++) {
const r = await call('repo-backup-run-now', {});
assert.strictEqual(r.summary.ok, 1, JSON.stringify(r));
await new Promise(res => setTimeout(res, 61000 / 60)); // eindeutige Zeitstempel
}
const zips = fs.readdirSync(path.join(target, 'M_Viper', 'deskhub-archiv'));
assert.ok(zips.length <= 3 && zips.length >= 1);
const state = await call('repo-backup-get-config', {});
assert.strictEqual(state.config.lastResult.total, 1);
fs.rmSync(target, { recursive: true, force: true });
} finally {
g.server.close();
}
});
+25
View File
@@ -0,0 +1,25 @@
const test = require('node:test');
const assert = require('node:assert');
const { listTemplates, buildGitignore } = require('../src/features/gitignoreTemplates.js');
test('listTemplates nennt Node, .NET und Electron', () => {
const keys = listTemplates().map(t => t.key);
assert.deepStrictEqual(keys, ['node', 'dotnet', 'electron']);
});
test('buildGitignore enthält immer den allgemeinen Teil', () => {
const out = buildGitignore([]);
assert.match(out, /\.env/);
assert.doesNotMatch(out, /node_modules/);
});
test('buildGitignore fügt gewählte Vorlagen genau einmal hinzu', () => {
const out = buildGitignore(['node', 'node', 'electron']);
assert.strictEqual(out.split('node_modules/').length - 1, 1);
assert.match(out, /dist\//);
assert.doesNotMatch(out, /\.vs\//);
});
test('buildGitignore ignoriert unbekannte Schlüssel', () => {
assert.doesNotThrow(() => buildGitignore(['gibt-es-nicht', '__proto__', null]));
});
+41
View File
@@ -0,0 +1,41 @@
const test = require('node:test');
const assert = require('node:assert');
const http = require('node:http');
const { bareHostname } = require('../src/utils/helpers.js');
const { checkGiteaConnection } = require('../src/git/apiHandler.js');
function listen(host) {
return new Promise((resolve, reject) => {
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ version: '1.22.0' }));
});
server.once('error', reject);
server.listen(0, host, () => resolve(server));
});
}
test('bareHostname entfernt Klammern nur bei IPv6-Literalen', () => {
assert.strictEqual(bareHostname(new URL('http://[2001:db8::1]:3000').hostname), '2001:db8::1');
assert.strictEqual(bareHostname('[::1]'), '::1');
assert.strictEqual(bareHostname('127.0.0.1'), '127.0.0.1');
assert.strictEqual(bareHostname('git.example.com'), 'git.example.com');
assert.strictEqual(bareHostname(undefined), '');
});
test('Gitea-Verbindung über IPv4', async () => {
const server = await listen('127.0.0.1');
try {
const r = await checkGiteaConnection({ url: `http://127.0.0.1:${server.address().port}` });
assert.strictEqual(r.ok, true);
} finally { server.close(); }
});
test('Gitea-Verbindung über IPv6', async (t) => {
let server;
try { server = await listen('::1'); } catch { return t.skip('IPv6-Loopback nicht verfügbar'); }
try {
const r = await checkGiteaConnection({ url: `http://[::1]:${server.address().port}` });
assert.strictEqual(r.ok, true);
} finally { server.close(); }
});
+76
View File
@@ -0,0 +1,76 @@
const test = require('node:test');
const assert = require('node:assert');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const { createPrefs, DEFAULTS } = require('../src/features/appPrefs.js');
const { useBundledGit, applyGitIdentity, commitIdentity } = require('../src/git/gitBinary.js');
const { createRepoBackup, excludeMatcher } = require('../src/backup/GiteaRepoBackup.js');
const tmp = (p) => fs.mkdtempSync(path.join(os.tmpdir(), p));
test('Einstellungen: Standardwerte, Bereinigung und ungültige E-Mail', () => {
const file = path.join(tmp('gm-prefs-'), 'app-settings.json');
const prefs = createPrefs(file);
assert.deepStrictEqual(prefs.get(), DEFAULTS);
const r = prefs.set({ zoom: 400, theme: 'pink', closeAction: 'tray', gitName: 'Max <x>\n', unbekannt: 1, uploadSecretScan: 0 });
assert.strictEqual(r.prefs.zoom, 150);
assert.strictEqual(r.prefs.theme, 'dark');
assert.strictEqual(r.prefs.closeAction, 'tray');
assert.strictEqual(r.prefs.gitName, 'Max x');
assert.strictEqual(r.prefs.uploadSecretScan, false);
assert.ok(!('unbekannt' in r.prefs));
const bad = prefs.set({ gitEmail: 'keine-mail' });
assert.deepStrictEqual(bad.rejected, ['gitEmail']);
assert.strictEqual(bad.prefs.gitEmail, '');
// nach dem Neuladen noch da
assert.strictEqual(createPrefs(file).get().closeAction, 'tray');
});
test('Git-Identität greift nur als Rückfallwert und verschwindet beim Leeren', () => {
useBundledGit();
const userData = tmp('gm-ud-');
const home = tmp('gm-home-');
const env = { ...process.env, HOME: home, USERPROFILE: home };
const ident = () => spawnSync('git', ['var', 'GIT_AUTHOR_IDENT'], { encoding: 'utf8', env: { ...env, GIT_CONFIG_SYSTEM: process.env.GIT_CONFIG_SYSTEM || '' } }).stdout;
assert.strictEqual(applyGitIdentity({ name: 'Test Name', email: 'test@example.com' }, userData), true);
assert.match(ident(), /^Test Name <test@example\.com>/);
// Eine globale Einstellung hat Vorrang
fs.writeFileSync(path.join(home, '.gitconfig'), '[user]\n\tname = Global\n\temail = global@example.com\n');
assert.match(ident(), /^Global <global@example\.com>/);
applyGitIdentity({ name: '', email: '' }, userData);
assert.strictEqual(process.env.GIT_CONFIG_SYSTEM, undefined);
assert.ok(!fs.existsSync(path.join(userData, 'git-system.gitconfig')));
assert.deepStrictEqual(commitIdentity({ gitName: '', gitEmail: '' }), { name: 'Git Manager GUI', email: 'gui@gitmanager.local' });
});
test('Backup: Ausschlussmuster und Zeitpunkt für automatische Backups', () => {
const m = excludeMatcher('test-*\nM_Viper/Alt?\n# Kommentar\nmy.repo');
assert.strictEqual(m('M_Viper/test-1'), true);
assert.strictEqual(m('M_Viper/Alt1'), true);
assert.strictEqual(m('M_Viper/Alt12'), false);
assert.strictEqual(m('x/my.repo'), true);
assert.strictEqual(m('x/myXrepo'), false);
const configPath = path.join(tmp('gm-bk-'), 'repo-backup.json');
const backup = createRepoBackup({ configPath, getContext() {}, giteaCall() {}, runGit() {}, isPackFailure() {}, redact: (s) => s });
backup.setConfig({ targetDir: 'X:/irgendwo', interval: 'daily', time: '03:00' });
const at = (s) => new Date(s);
// noch nie gelaufen: vor 03:00 nicht, danach schon
assert.strictEqual(backup.isDue(at('2026-10-22T02:59:00')), true, 'Slot von gestern 03:00 ist offen');
fs.writeFileSync(configPath, JSON.stringify({ ...JSON.parse(fs.readFileSync(configPath, 'utf8')), lastRun: '2026-10-22T03:05:00' }));
assert.strictEqual(backup.isDue(at('2026-10-22T20:00:00')), false, 'heute schon gelaufen');
assert.strictEqual(backup.isDue(at('2026-10-23T02:59:00')), false, 'vor 03:00 noch nicht');
assert.strictEqual(backup.isDue(at('2026-10-23T03:00:00')), true, 'ab 03:00 wieder fällig');
backup.setConfig({ time: '25:99' });
assert.strictEqual(backup.getState().config.time, '');
});
+201
View File
@@ -0,0 +1,201 @@
const test = require('node:test');
const assert = require('node:assert');
const http = require('node:http');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const archiver = require('archiver');
require('../src/git/gitBinary.js').useBundledGit();
const { registerFeatureIpc } = require('../src/features/featuresIpc.js');
const git = (cwd, ...a) => spawnSync('git', ['-c', 'user.name=t', '-c', 'user.email=t@t', ...a], { cwd, encoding: 'utf8' });
const tmp = (p) => fs.mkdtempSync(path.join(os.tmpdir(), p));
function makeZip(file, entries) {
return new Promise((resolve, reject) => {
const out = fs.createWriteStream(file);
const zip = archiver('zip');
out.on('close', resolve);
zip.on('error', reject);
zip.pipe(out);
for (const [name, content] of entries) zip.append(content, { name });
zip.finalize();
});
}
// Backup-Ordner wie von GiteaRepoBackup angelegt: Spiegel + ZIP-Stände
async function makeBackupDir() {
const work = tmp('gm-src-');
git(work, 'init', '-q', '-b', 'main');
fs.writeFileSync(path.join(work, 'a.txt'), 'hallo');
git(work, 'add', '.'); git(work, 'commit', '-qm', 'eins');
git(work, 'branch', 'feature'); git(work, 'tag', 'v1.0');
const dir = tmp('gm-bk-');
fs.mkdirSync(path.join(dir, 'M_Viper'));
git(dir, 'clone', '-q', '--mirror', work, path.join(dir, 'M_Viper', 'deskhub.git'));
const zipDir = path.join(dir, 'M_Viper', 'deskhub-archiv');
fs.mkdirSync(zipDir);
await makeZip(path.join(zipDir, 'deskhub-2026-10-01_10-00.zip'), [['deskhub/a.txt', 'alt'], ['deskhub/src/b.kt', 'fun b() {}']]);
await makeZip(path.join(zipDir, 'deskhub-2026-10-20_10-00.zip'), [['deskhub/a.txt', 'neu'], ['deskhub/src/b.kt', 'fun b() {}']]);
fs.utimesSync(path.join(zipDir, 'deskhub-2026-10-01_10-00.zip'), new Date('2026-10-01'), new Date('2026-10-01'));
fs.writeFileSync(path.join(dir, 'backup-protokoll.json'), '{}');
return { dir, work };
}
// Gitea-Nachbau: neue Repos zeigen auf echte lokale Bare-Repos, damit der Push wirklich läuft
function fakeGitea() {
const created = [];
const patches = [];
const repoRoot = tmp('gm-remote-');
const server = http.createServer((req, res) => {
const u = new URL(req.url, 'http://x');
const send = (code, obj) => { res.statusCode = code; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(obj)); };
let body = '';
req.on('data', c => body += c);
req.on('end', () => {
if (u.pathname === '/api/v1/user') return send(200, { login: 'M_Viper' });
if (u.pathname === '/api/v1/user/repos' && req.method === 'POST') {
const b = JSON.parse(body);
if (b.name === 'deskhub') return send(409, { message: 'repository already exists' });
const bare = path.join(repoRoot, `${b.name}.git`);
spawnSync('git', ['init', '-q', '--bare', '-b', 'main', bare]);
created.push(b);
return send(201, { name: b.name, full_name: `M_Viper/${b.name}`, owner: { login: 'M_Viper' }, clone_url: bare, html_url: `http://gitea/M_Viper/${b.name}`, default_branch: 'main' });
}
if (u.pathname.startsWith('/api/v1/repos/M_Viper/') && req.method === 'PATCH') { patches.push(JSON.parse(body)); return send(200, {}); }
send(404, { message: 'not found' });
});
});
return new Promise(r => server.listen(0, '127.0.0.1', () => r({ server, created, patches, repoRoot, url: `http://127.0.0.1:${server.address().port}` })));
}
function setup(url) {
const handlers = {};
const userData = tmp('gm-ud-');
registerFeatureIpc({
ipcMain: { handle: (name, fn) => { handlers[name] = fn; } },
app: { getPath: () => userData },
readCredentials: () => ({ giteaURL: url, giteaToken: 'geheim123' }),
buildItemsFromPaths: async () => ({ items: [], skipped: [], ignored: [] }),
clearGitTransportBlock: () => false
});
return (name, data) => handlers[name]({ sender: { send() {} } }, data);
}
test('Sicherungen werden gefunden: Spiegel und ZIP-Stände, neuester zuerst', async () => {
const { dir } = await makeBackupDir();
const call = setup('http://127.0.0.1:1');
const r = await call('repo-backup-list', { dir });
assert.strictEqual(r.ok, true, r.error);
assert.strictEqual(r.backups.length, 1);
const b = r.backups[0];
assert.deepStrictEqual([b.owner, b.repo], ['M_Viper', 'deskhub']);
assert.ok(b.mirror);
assert.deepStrictEqual(b.zips.map(z => z.file), ['deskhub-2026-10-20_10-00.zip', 'deskhub-2026-10-01_10-00.zip']);
});
test('Lokal: Spiegel wird zur Arbeitskopie mit allen Branches, ZIP ohne Oberordner entpackt', async () => {
const { dir } = await makeBackupDir();
const call = setup('http://127.0.0.1:1');
const { backups: [b] } = await call('repo-backup-list', { dir });
const dest1 = tmp('gm-dst-');
const m = await call('repo-restore-local', { kind: 'mirror', source: b.mirror.path, destParent: dest1, repo: 'deskhub' });
assert.strictEqual(m.ok, true, m.error);
assert.strictEqual(fs.readFileSync(path.join(dest1, 'deskhub', 'a.txt'), 'utf8'), 'hallo');
assert.match(git(path.join(dest1, 'deskhub'), 'branch', '-r').stdout, /feature/);
// Zweiter Versuch in denselben Ordner darf nichts überschreiben
const again = await call('repo-restore-local', { kind: 'mirror', source: b.mirror.path, destParent: dest1, repo: 'deskhub' });
assert.strictEqual(again.ok, false);
assert.match(again.error, /existiert bereits/);
const dest2 = tmp('gm-dst-');
const z = await call('repo-restore-local', { kind: 'zip', source: b.zips[0].path, destParent: dest2, repo: 'deskhub' });
assert.strictEqual(z.ok, true, z.error);
assert.strictEqual(z.files, 2);
assert.strictEqual(fs.readFileSync(path.join(dest2, 'deskhub', 'a.txt'), 'utf8'), 'neu');
assert.ok(fs.existsSync(path.join(dest2, 'deskhub', 'src', 'b.kt')));
});
// ZIP von Hand bauen: archiver entschärft "../" schon beim Erzeugen, ein echter Angreifer nicht.
function rawZip(file, entries) {
const zlib = require('node:zlib');
const locals = [];
const centrals = [];
let offset = 0;
for (const [name, content] of entries) {
const n = Buffer.from(name);
const data = Buffer.from(content);
const crc = zlib.crc32(data);
const lh = Buffer.alloc(30);
lh.writeUInt32LE(0x04034b50, 0); lh.writeUInt16LE(20, 4); lh.writeUInt32LE(crc, 14);
lh.writeUInt32LE(data.length, 18); lh.writeUInt32LE(data.length, 22); lh.writeUInt16LE(n.length, 26);
const ch = Buffer.alloc(46);
ch.writeUInt32LE(0x02014b50, 0); ch.writeUInt16LE(20, 4); ch.writeUInt16LE(20, 6); ch.writeUInt32LE(crc, 16);
ch.writeUInt32LE(data.length, 20); ch.writeUInt32LE(data.length, 24); ch.writeUInt16LE(n.length, 28); ch.writeUInt32LE(offset, 42);
locals.push(lh, n, data);
centrals.push(ch, n);
offset += lh.length + n.length + data.length;
}
const cd = Buffer.concat(centrals);
const end = Buffer.alloc(22);
end.writeUInt32LE(0x06054b50, 0); end.writeUInt16LE(entries.length, 8); end.writeUInt16LE(entries.length, 10);
end.writeUInt32LE(cd.length, 12); end.writeUInt32LE(offset, 16);
fs.writeFileSync(file, Buffer.concat([...locals, cd, end]));
}
test('Archive mit Pfaden außerhalb des Ziels werden abgewiesen', async () => {
const d = tmp('gm-evil-');
const zip = path.join(d, 'evil.zip');
rawZip(zip, [['deskhub/ok.txt', 'ok'], ['deskhub/../../boese.txt', 'x']]);
const unzipper = require('unzipper');
const names = (await unzipper.Open.file(zip)).files.map(f => f.path);
assert.ok(names.includes('deskhub/../../boese.txt'), 'Testarchiv muss den gefährlichen Pfad wirklich enthalten');
const call = setup('http://127.0.0.1:1');
const destParent = tmp('gm-dst-');
const r = await call('repo-restore-local', { kind: 'zip', source: zip, destParent, repo: 'x' });
assert.strictEqual(r.ok, false);
assert.match(r.error, /Unsicherer Pfad/);
assert.ok(!fs.existsSync(path.join(destParent, 'x', 'ok.txt')), 'auch harmlose Dateien dürfen dann nicht entpackt werden');
assert.ok(!fs.existsSync(path.join(destParent, 'boese.txt')));
});
test('Gitea: Spiegel und ZIP als neues Repo, Namenskonflikt und ZIP-Überschreiben werden abgefangen', async () => {
const { dir } = await makeBackupDir();
const g = await fakeGitea();
try {
const call = setup(g.url);
const { backups: [b] } = await call('repo-backup-list', { dir });
const m = await call('repo-restore-gitea', { kind: 'mirror', source: b.mirror.path, owner: 'M_Viper', repo: 'deskhub', mode: 'new', newName: 'deskhub-wieder', isPrivate: true });
assert.strictEqual(m.ok, true, m.error);
const bare = path.join(g.repoRoot, 'deskhub-wieder.git');
const refs = git(bare, 'for-each-ref', '--format=%(refname)').stdout;
assert.match(refs, /refs\/heads\/main/);
assert.match(refs, /refs\/heads\/feature/);
assert.match(refs, /refs\/tags\/v1\.0/);
assert.strictEqual(g.created[0].private, true);
const z = await call('repo-restore-gitea', { kind: 'zip', source: b.zips[0].path, owner: 'M_Viper', repo: 'deskhub', mode: 'new', newName: 'deskhub-zip' });
assert.strictEqual(z.ok, true, z.error);
assert.strictEqual(z.method, 'Git');
const files = git(path.join(g.repoRoot, 'deskhub-zip.git'), 'ls-tree', '-r', '--name-only', 'main').stdout.trim().split('\n');
assert.deepStrictEqual(files.sort(), ['a.txt', 'src/b.kt']);
const conflict = await call('repo-restore-gitea', { kind: 'mirror', source: b.mirror.path, owner: 'M_Viper', repo: 'deskhub', mode: 'new', newName: 'deskhub' });
assert.strictEqual(conflict.ok, false);
assert.match(conflict.error, /existiert bereits/);
const zipOverwrite = await call('repo-restore-gitea', { kind: 'zip', source: b.zips[0].path, owner: 'M_Viper', repo: 'deskhub', mode: 'overwrite' });
assert.strictEqual(zipOverwrite.ok, false);
assert.match(zipOverwrite.error, /nur mit einem Git-Spiegel/);
const badName = await call('repo-restore-gitea', { kind: 'zip', source: b.zips[0].path, owner: 'M_Viper', repo: 'deskhub', mode: 'new', newName: 'mit leerzeichen' });
assert.strictEqual(badName.ok, false);
} finally {
g.server.close();
}
});
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

+19
View File
@@ -0,0 +1,19 @@
<Application x:Class="GitManagerSetup.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- [0] wird je nach Hell/Dunkel ersetzt -->
<ResourceDictionary Source="Themes/Colors.Light.xaml"/>
<ResourceDictionary Source="Themes/Controls.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- Akzent wie in der App (Cyan → Blau) -->
<SolidColorBrush x:Key="AccentBrush" Color="#2E7FE0"/>
<SolidColorBrush x:Key="AccentHoverBrush" Color="#4590EA"/>
<SolidColorBrush x:Key="OnAccentBrush" Color="White"/>
<SolidColorBrush x:Key="AccentSubtleBrush" Color="#222E7FE0"/>
<SolidColorBrush x:Key="AccentSubtleStrokeBrush" Color="#552E7FE0"/>
</ResourceDictionary>
</Application.Resources>
</Application>
+99
View File
@@ -0,0 +1,99 @@
using System.IO;
using System.Windows;
using System.Windows.Media;
using Microsoft.Win32;
namespace GitManagerSetup;
public partial class App : Application
{
private static Mutex? _single;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
bool has(string arg) => e.Args.Any(a => a.Equals(arg, StringComparison.OrdinalIgnoreCase));
// Das Deinstallationsprogramm ist das Setup ohne angehängte App → ohne Anhang immer Deinstallation
bool uninstall = has("--uninstall") || !Payload.Exists;
bool silent = has("/S");
bool update = has("--update");
bool launch = has("/launch");
var dirArg = e.Args.FirstOrDefault(a => a.StartsWith("/D=", StringComparison.OrdinalIgnoreCase))?.Substring(3);
_single = new Mutex(true, "GitManagerGUI-Setup", out bool first);
if (!first)
{
Shutdown(0);
return;
}
// Stille Installation/Deinstallation für Skripte:
// Git-Manager-GUI-Setup.exe /S [/D=Ordner] [/launch] bzw. --uninstall /S
if (silent)
{
var progress = new Progress<(double, string)>(_ => { });
try
{
if (uninstall) Installer.Uninstall(removeData: false, progress);
else
{
var dir = dirArg ?? Installer.InstalledDir ?? Installer.DefaultDir;
Installer.Install(dir, desktopLink: Installer.InstalledDir is null || Installer.DesktopLinkExists,
progress, waitForExit: true);
if (launch) System.Diagnostics.Process.Start(Path.Combine(dir, Installer.ExeName));
}
Shutdown(0);
}
catch (Exception ex)
{
// ohne Oberfläche: Fehler für Skripte nachvollziehbar ablegen
try { File.WriteAllText(Path.Combine(Path.GetTempPath(), "Git-Manager-GUI-Setup.log"), $"[{DateTime.Now}] {ex}"); } catch { }
Shutdown(1);
}
return;
}
ApplyTheme();
var mode = uninstall ? SetupMode.Uninstall : update ? SetupMode.Update : SetupMode.Install;
new MainWindow(mode).Show();
}
protected override void OnExit(ExitEventArgs e)
{
try { _single?.ReleaseMutex(); } catch { }
base.OnExit(e);
}
/// <summary>Hell/Dunkel wie in Windows eingestellt.</summary>
private void ApplyTheme()
{
bool light = ReadDword(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme") != 0;
Resources.MergedDictionaries[0] = new ResourceDictionary
{
Source = new Uri($"pack://application:,,,/Themes/Colors.{(light ? "Light" : "Dark")}.xaml"),
};
if (!light)
{
// im Dunkeln das Cyan der App, damit Text und Fortschrittsbalken gut lesbar bleiben
var a = Color.FromRgb(0x4C, 0xB8, 0xF5);
Resources["AccentBrush"] = new SolidColorBrush(a);
Resources["AccentHoverBrush"] = new SolidColorBrush(Color.FromRgb(0x67, 0xC6, 0xF8));
Resources["OnAccentBrush"] = new SolidColorBrush(Color.FromRgb(0x04, 0x10, 0x1F));
Resources["AccentSubtleBrush"] = new SolidColorBrush(Color.FromArgb(0x30, a.R, a.G, a.B));
Resources["AccentSubtleStrokeBrush"] = new SolidColorBrush(Color.FromArgb(0x60, a.R, a.G, a.B));
}
}
private static int ReadDword(string key, string name)
{
try
{
using var k = Registry.CurrentUser.OpenSubKey(key);
return k?.GetValue(name) is int i ? i : -1;
}
catch { return -1; }
}
}
public enum SetupMode { Install, Update, Uninstall }
+46
View File
@@ -0,0 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<!-- .NET Framework 4.8 ist in jedem Windows 10/11 enthalten → der Installer läuft ohne Zusatzinstallation -->
<TargetFramework>net48</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<PlatformTarget>AnyCPU</PlatformTarget>
<Prefer32Bit>false</Prefer32Bit>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<AssemblyName>Git-Manager-GUI-Setup</AssemblyName>
<RootNamespace>GitManagerSetup</RootNamespace>
<ApplicationIcon>..\assets\icon.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Product>Git Manager GUI Setup</Product>
<AssemblyTitle>Git Manager GUI Setup</AssemblyTitle>
<Description>Installiert Git Manager GUI</Description>
<Company>M_Viper</Company>
<Authors>M_Viper</Authors>
<Copyright>Copyright (c) M_Viper</Copyright>
<NeutralLanguage>de-DE</NeutralLanguage>
<!-- Version kommt beim Bauen aus package.json (scripts/build-setup.js) -->
<Version Condition="'$(Version)' == ''">0.0.0</Version>
</PropertyGroup>
<ItemGroup>
<!-- WinForms nur für den Ordner-Dialog; nicht global, sonst Namenskonflikte mit WPF -->
<Using Remove="System.Windows.Forms" />
<Using Remove="System.Drawing" />
<Reference Include="Microsoft.VisualBasic" />
<Reference Include="System.IO.Compression" />
</ItemGroup>
<ItemGroup>
<!-- Themes\*.xaml bindet das SDK automatisch als Page ein -->
<Resource Include="..\assets\icon.ico" Link="app.ico" />
<Resource Include="..\assets\icon.png" Link="app.png" />
</ItemGroup>
<!--
Die eigentliche App (entpackter Electron-Ordner als ZIP) wird NICHT hier eingebettet,
sondern nach dem Bauen hinten an die .exe angehängt (scripts/build-setup.js, siehe Payload.cs).
So muss der Compiler keine ~150 MB als Ressource verarbeiten, und das Deinstallationsprogramm
ist einfach der vordere Teil der Datei ohne Anhang.
-->
</Project>
+501
View File
@@ -0,0 +1,501 @@
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Win32;
namespace GitManagerSetup;
/// <summary>Installation/Deinstallation – nur für den aktuellen Benutzer, ohne Administratorrechte.</summary>
public static class Installer
{
public const string AppName = "Git Manager GUI";
public const string Publisher = "M_Viper";
// productName aus package.json → so heißt die EXE im entpackten Electron-Ordner
public const string ExeName = "Git Manager GUI.exe";
private const string ProcessName = "Git Manager GUI";
// Gleicher Name wie beim früheren NSIS-Setup (electron-builder), damit eine alte Installation sauber ersetzt wird
public const string UninstallerName = "Uninstall Git Manager GUI.exe";
// wie "appId" in package.json – gleiche Taskleisten-/Benachrichtigungs-Zuordnung wie bisher
public const string AppUserModelId = "com.viper.gitmanager";
// Schlüssel vom alten electron-builder-Setup (Version 2.1.7) übernommen → in "Apps" bleibt es ein einziger Eintrag
private const string KeyId = "4156cc7f-a3e7-5b1d-9238-0af3e0f54ecd";
private const string UninstallKey = @"Software\Microsoft\Windows\CurrentVersion\Uninstall\" + KeyId;
private const string LegacyAppKey = @"Software\" + KeyId;
private const string RunKey = @"Software\Microsoft\Windows\CurrentVersion\Run";
private const string FileListName = "install-files.txt";
public static string Version
{
get
{
var info = typeof(Installer).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
if (!string.IsNullOrEmpty(info)) return info!.Split('+')[0];
var v = typeof(Installer).Assembly.GetName().Version!;
return $"{v.Major}.{v.Minor}.{v.Build}";
}
}
/// <summary>Pfad dieses Setups (bzw. des Deinstallationsprogramms).</summary>
public static string SelfPath => Assembly.GetExecutingAssembly().Location;
public static string DefaultDir =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", AppName);
/// <summary>App-Daten: Zugangsdaten (verschlüsselt), Einstellungen, Favoriten, Verlauf, Backup-Einstellung.</summary>
public static string DataDir =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "git-manager-gui");
private static string StartMenuLink =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Programs), AppName + ".lnk");
private static string DesktopLink =>
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), AppName + ".lnk");
// ---------- vorhandene Installation ----------
private static string? RegValue(string name)
{
using var k = Registry.CurrentUser.OpenSubKey(UninstallKey);
return k?.GetValue(name) as string;
}
/// <summary>Ordner einer vorhandenen Installation (dieses Setups oder des alten NSIS-Setups), oder null.</summary>
public static string? InstalledDir
{
get
{
var dir = RegValue("InstallLocation");
if (string.IsNullOrWhiteSpace(dir))
{
// altes NSIS-Setup trägt keinen InstallLocation ein → aus dem Deinstallationsbefehl ablesen
var m = Regex.Match(RegValue("UninstallString") ?? "", "^\"([^\"]+)\"");
dir = m.Success ? Path.GetDirectoryName(m.Groups[1].Value) : null;
}
return dir is not null && File.Exists(Path.Combine(dir, ExeName)) ? dir : null;
}
}
/// <summary>Stammt die vorhandene Installation noch vom alten NSIS-Setup?</summary>
public static bool IsLegacyInstall =>
InstalledDir is not null && (RegValue("UninstallString") ?? "").IndexOf("--uninstall", StringComparison.OrdinalIgnoreCase) < 0;
public static string? InstalledVersion => RegValue("DisplayVersion");
public static bool DesktopLinkExists => File.Exists(DesktopLink);
public static bool IsRunning(string? dir) => AppProcesses(dir, InstalledDir).Any();
// ---------- Installieren ----------
/// <param name="waitForExit">nach einem Update aus der App: ihr erst Zeit geben, sich selbst zu beenden</param>
public static void Install(string dir, bool desktopLink, IProgress<(double, string)> progress, bool waitForExit = false)
{
if (!Environment.Is64BitOperatingSystem)
throw new InvalidOperationException("Git Manager GUI benötigt ein 64-Bit-Windows (Windows 10 oder 11).");
var oldDir = InstalledDir;
progress.Report((0.02, "Git Manager GUI wird beendet …"));
CloseRunningApp(waitForExit ? 20000 : 0, dir, oldDir);
using var zip = Payload.OpenArchive();
var topLevel = TopLevelNames(zip);
progress.Report((0.05, "Alte Version wird entfernt …"));
Directory.CreateDirectory(dir);
RemoveAppFiles(dir, topLevel);
if (oldDir is not null && !SamePath(oldDir, dir))
{
// Installation wurde in einen anderen Ordner verlegt → alten Ordner aufräumen
var oldExe = Path.Combine(oldDir, ExeName);
DeleteIfPointsTo(StartMenuLink, oldExe);
DeleteIfPointsTo(DesktopLink, oldExe);
RemoveAppFiles(oldDir, topLevel);
try { Directory.Delete(oldDir); } catch { } // nur wenn leer
}
Extract(zip, dir, p => progress.Report((0.08 + p * 0.8, "Dateien werden kopiert …")));
progress.Report((0.9, "Deinstallationsprogramm wird angelegt …"));
var exe = Path.Combine(dir, ExeName);
var uninstaller = Path.Combine(dir, UninstallerName);
if (!SamePath(SelfPath, uninstaller))
{
MoveAside(uninstaller);
CopyStub(uninstaller);
}
File.WriteAllLines(Path.Combine(dir, FileListName), topLevel.Concat([UninstallerName, FileListName]));
progress.Report((0.94, "Verknüpfungen werden angelegt …"));
Shortcut.Create(StartMenuLink, exe, "Repositories auf Gitea und GitHub verwalten", AppUserModelId);
if (desktopLink) Shortcut.Create(DesktopLink, exe, "Repositories auf Gitea und GitHub verwalten", AppUserModelId);
else DeleteIfPointsTo(DesktopLink, exe);
progress.Report((0.97, "Windows wird eingerichtet …"));
Registry.CurrentUser.DeleteSubKeyTree(UninstallKey, throwOnMissingSubKey: false); // Reste des alten Setups
Registry.CurrentUser.DeleteSubKeyTree(LegacyAppKey, throwOnMissingSubKey: false);
using (var k = Registry.CurrentUser.CreateSubKey(UninstallKey))
{
long size = DirSize(dir) / 1024;
k.SetValue("DisplayName", AppName);
k.SetValue("DisplayVersion", Version);
k.SetValue("Publisher", Publisher);
k.SetValue("DisplayIcon", $"{exe},0");
k.SetValue("InstallLocation", dir);
k.SetValue("UninstallString", $"\"{uninstaller}\" --uninstall");
k.SetValue("QuietUninstallString", $"\"{uninstaller}\" --uninstall /S");
k.SetValue("URLInfoAbout", "https://git.viper.ipv64.net/M_Viper/Git-Manager-Gui");
k.SetValue("InstallDate", DateTime.Now.ToString("yyyyMMdd"));
k.SetValue("EstimatedSize", (int)Math.Min(int.MaxValue, size), RegistryValueKind.DWord);
k.SetValue("NoModify", 1, RegistryValueKind.DWord);
k.SetValue("NoRepair", 1, RegistryValueKind.DWord);
}
progress.Report((0.98, "Installation wird abgeschlossen …"));
Vorwaermen(exe);
progress.Report((1.0, "Fertig"));
}
/// <summary>
/// Startet die App einmal kurz mit "--gm-vorwaermen" – sie beendet sich
/// damit sofort wieder (siehe main.js). Windows Defender prüft eine neue,
/// noch unbekannte EXE beim ersten Start mehrere Sekunden lang (gemessen: ~8 s);
/// das passiert so während des Fortschrittsbalkens und nicht erst beim Klick
/// auf "Fertigstellen". Das Ergebnis merkt sich Windows, der echte Start ist
/// danach sofort da.
/// </summary>
private static void Vorwaermen(string exe)
{
try
{
using var p = Process.Start(new ProcessStartInfo(exe, "--gm-vorwaermen")
{
UseShellExecute = false,
CreateNoWindow = true,
WorkingDirectory = Path.GetDirectoryName(exe)!,
});
if (p != null && !p.WaitForExit(30000)) { try { p.Kill(); } catch { } }
}
catch { /* nur eine Beschleunigung – Fehler sind egal */ }
}
private static List<string> TopLevelNames(ZipArchive zip) =>
zip.Entries
.Select(e => e.FullName.Replace('\\', '/').Split('/')[0])
.Where(n => n.Length > 0)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
private static void Extract(ZipArchive zip, string dir, Action<double> report)
{
var root = Path.GetFullPath(dir).TrimEnd('\\') + "\\";
long total = Math.Max(1, zip.Entries.Sum(e => e.Length)), done = 0;
var buffer = new byte[1 << 20];
int lastPercent = -1;
foreach (var entry in zip.Entries)
{
var target = Path.GetFullPath(Path.Combine(dir, entry.FullName));
if (!target.StartsWith(root, StringComparison.OrdinalIgnoreCase)) continue; // nie außerhalb des Ordners schreiben
if (entry.Name.Length == 0)
{
Directory.CreateDirectory(target);
continue;
}
Directory.CreateDirectory(Path.GetDirectoryName(target)!);
long before = done;
Retry(target, () =>
{
done = before;
MoveAside(target);
using var src = entry.Open();
using var dst = File.Create(target);
int n;
while ((n = src.Read(buffer, 0, buffer.Length)) > 0)
{
dst.Write(buffer, 0, n);
done += n;
int percent = (int)(done * 100 / total);
if (percent != lastPercent)
{
lastPercent = percent;
report(Math.Min(1.0, (double)done / total));
}
}
});
}
report(1.0);
}
/// <summary>Setup ohne angehängte App als Deinstallationsprogramm ablegen (nur ein paar hundert KB).</summary>
private static void CopyStub(string path)
{
long length = Payload.StubLength;
using var src = File.OpenRead(SelfPath);
using var dst = File.Create(path);
var buffer = new byte[81920];
long left = length;
while (left > 0)
{
int n = src.Read(buffer, 0, (int)Math.Min(buffer.Length, left));
if (n <= 0) break;
dst.Write(buffer, 0, n);
left -= n;
}
}
// ---------- Deinstallieren ----------
public static void Uninstall(bool removeData, IProgress<(double, string)> progress)
{
// Nur im eingetragenen Installationsordner löschen – nie dort, wo das Setup zufällig liegt (z. B. Downloads)
var dir = InstalledDir;
var exe = dir is null ? "" : Path.Combine(dir, ExeName);
progress.Report((0.1, "Git Manager GUI wird beendet …"));
CloseRunningApp(0, dir);
progress.Report((0.3, "Verknüpfungen werden entfernt …"));
DeleteIfPointsTo(StartMenuLink, exe);
DeleteIfPointsTo(DesktopLink, exe);
progress.Report((0.45, "Windows-Einträge werden entfernt …"));
RemoveAutostart(exe);
Registry.CurrentUser.DeleteSubKeyTree(UninstallKey, throwOnMissingSubKey: false);
Registry.CurrentUser.DeleteSubKeyTree(LegacyAppKey, throwOnMissingSubKey: false);
// Name/Logo für Windows-Benachrichtigungen (legt Electron selbst an)
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\AppUserModelId\" + AppUserModelId, throwOnMissingSubKey: false);
if (removeData && Directory.Exists(DataDir))
{
progress.Report((0.6, "Zugangsdaten und Einstellungen werden in den Papierkorb gelegt …"));
try
{
Microsoft.VisualBasic.FileIO.FileSystem.DeleteDirectory(DataDir,
Microsoft.VisualBasic.FileIO.UIOption.OnlyErrorDialogs,
Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin);
}
catch { }
}
progress.Report((0.8, "Dateien werden entfernt …"));
if (dir is null) { progress.Report((1.0, "Fertig")); return; }
RemoveAppFiles(dir, null);
// Das laufende Deinstallationsprogramm kann sich nicht selbst löschen → kurz nach dem Beenden per cmd.
// rmdir ohne /s entfernt den Ordner nur, wenn er danach leer ist.
var self = SelfPath;
if (IsUnder(self, dir))
{
Process.Start(new ProcessStartInfo("cmd.exe",
$"/c ping 127.0.0.1 -n 3 > nul & del /f /q \"{self}\" & del /f /q \"{Path.Combine(dir, "*.old")}\" & rmdir \"{dir}\"")
{
CreateNoWindow = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden,
});
}
else
{
TryDelete(Path.Combine(dir, UninstallerName));
try { Directory.Delete(dir); } catch { } // nur wenn leer
}
progress.Report((1.0, "Fertig"));
}
/// <summary>Autostart-Einträge entfernen, die die App selbst gesetzt hat (Name vergibt Electron).</summary>
private static void RemoveAutostart(string exe)
{
if (exe.Length == 0) return;
using var run = Registry.CurrentUser.OpenSubKey(RunKey, writable: true);
if (run is null) return;
foreach (var name in run.GetValueNames())
{
if (run.GetValue(name) is string cmd && cmd.IndexOf(exe, StringComparison.OrdinalIgnoreCase) >= 0)
run.DeleteValue(name, throwOnMissingValue: false);
}
}
// ---------- Dateien ----------
/// <summary>
/// Entfernt die App-Dateien aus einem Installationsordner. Gelöscht wird nur, was nachweislich zur App gehört:
/// Einträge aus der Dateiliste der letzten Installation bzw. die Namen aus dem neuen Paket –
/// Ordner nur, wenn sie eindeutig von Electron stammen. Fremde Dateien im Ordner bleiben unangetastet.
/// </summary>
private static void RemoveAppFiles(string dir, IEnumerable<string>? extraNames)
{
if (!Directory.Exists(dir)) return;
CleanupOldFiles(dir);
var listFile = Path.Combine(dir, FileListName);
var fromList = File.Exists(listFile) ? File.ReadAllLines(listFile).Where(l => l.Trim().Length > 0).ToList() : [];
var names = fromList.Concat(extraNames ?? []).Concat([UninstallerName, FileListName])
.Distinct(StringComparer.OrdinalIgnoreCase);
foreach (var name in names)
{
if (name.IndexOfAny(['\\', '/', ':']) >= 0 || name is "." or "..") continue;
var path = Path.Combine(dir, name);
if (SamePath(path, SelfPath)) continue; // das laufende Deinstallationsprogramm räumt cmd weg
if (Directory.Exists(path))
{
bool ours = fromList.Contains(name, StringComparer.OrdinalIgnoreCase)
|| (name.Equals("resources", StringComparison.OrdinalIgnoreCase) && File.Exists(Path.Combine(path, "app.asar")))
|| (name.Equals("locales", StringComparison.OrdinalIgnoreCase) && File.Exists(Path.Combine(path, "en-US.pak")));
if (ours) Retry(path, () => Directory.Delete(path, recursive: true));
}
else if (File.Exists(path))
{
Retry(path, () => MoveAside(path));
}
}
}
/// <summary>
/// Längster Pfad im Paket. Windows erlaubt (ohne Sonderfreigabe) nur 259 Zeichen pro Pfad –
/// der Installationsordner darf deshalb höchstens <see cref="MaxDirLength"/> Zeichen lang sein.
/// </summary>
private static int? _longestEntry;
public static int MaxDirLength
{
get
{
if (_longestEntry is null)
{
try
{
using var zip = Payload.OpenArchive();
_longestEntry = zip.Entries.Count == 0 ? 0 : zip.Entries.Max(e => e.FullName.Length);
}
catch { _longestEntry = 0; }
}
return 259 - 1 - _longestEntry.Value;
}
}
private static void Retry(string path, Action action)
{
for (int attempt = 1; ; attempt++)
{
try
{
action();
return;
}
catch (PathTooLongException ex)
{
throw new IOException($"Der Installationsordner ist zu lang. Bitte einen kürzeren Ordner wählen (höchstens {MaxDirLength} Zeichen).", ex);
}
catch (Exception ex) when ((ex is IOException || ex is UnauthorizedAccessException) && attempt < 10)
{
Thread.Sleep(500);
}
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException)
{
throw new IOException($"„{Path.GetFileName(path)}“ wird noch verwendet. Bitte Git Manager GUI beenden " +
"(auch das Symbol im Infobereich neben der Uhr) und erneut versuchen.", ex);
}
}
}
/// <summary>
/// Vorhandene Datei löschen oder – falls sie noch geöffnet ist (Explorer, Virenscanner) – beiseite umbenennen.
/// Umbenennen klappt unter Windows auch bei geöffneten Dateien, überschreiben nicht.
/// </summary>
private static void MoveAside(string path)
{
if (!File.Exists(path)) return;
try { File.Delete(path); return; } catch { }
File.Move(path, $"{path}.{Guid.NewGuid():N}.old");
}
private static void CleanupOldFiles(string dir)
{
if (!Directory.Exists(dir)) return;
foreach (var f in Directory.GetFiles(dir, "*.old", SearchOption.AllDirectories))
try { File.Delete(f); } catch { }
}
private static void TryDelete(string path)
{
try { if (File.Exists(path)) File.Delete(path); } catch { }
}
private static void DeleteIfPointsTo(string link, string target)
{
if (!File.Exists(link) || target.Length == 0) return;
if (!SamePath(Shortcut.Target(link) ?? "", target)) return;
// Explorer/Indexdienst halten Verknüpfungen manchmal kurz fest → mehrmals versuchen
for (int i = 0; i < 10 && File.Exists(link); i++)
{
try { File.Delete(link); }
catch { Thread.Sleep(300); }
}
}
// ---------- Prozesse ----------
private static IEnumerable<Process> AppProcesses(params string?[] dirs)
{
var roots = dirs.Where(d => !string.IsNullOrEmpty(d)).Select(d => d!).ToList();
if (roots.Count == 0) yield break;
// die App (mehrere Electron-Prozesse) und das mitgelieferte Git, falls gerade ein Upload läuft
foreach (var p in Process.GetProcessesByName(ProcessName).Concat(Process.GetProcessesByName("git")))
{
string? file = null;
try { file = p.MainModule?.FileName; } catch { }
if (file is not null && roots.Any(r => IsUnder(file, r))) yield return p;
}
}
private static void CloseRunningApp(int waitMs, params string?[] dirs)
{
var until = DateTime.Now.AddMilliseconds(waitMs);
while (waitMs > 0 && DateTime.Now < until && AppProcesses(dirs).Any())
Thread.Sleep(300);
foreach (var p in AppProcesses(dirs).ToList())
{
try
{
p.Kill();
p.WaitForExit(10000);
}
catch { }
}
}
// ---------- Helfer ----------
private static bool SamePath(string a, string b)
{
try { return string.Equals(Path.GetFullPath(a).TrimEnd('\\'), Path.GetFullPath(b).TrimEnd('\\'), StringComparison.OrdinalIgnoreCase); }
catch { return false; }
}
private static bool IsUnder(string path, string dir) =>
Path.GetFullPath(path).StartsWith(Path.GetFullPath(dir).TrimEnd('\\') + "\\", StringComparison.OrdinalIgnoreCase);
private static long DirSize(string dir)
{
long sum = 0;
try
{
foreach (var f in Directory.EnumerateFiles(dir, "*", SearchOption.AllDirectories))
try { sum += new FileInfo(f).Length; } catch { }
}
catch { }
return sum;
}
public static long DataSize() => Directory.Exists(DataDir) ? DirSize(DataDir) : 0;
public static string FormatSize(long bytes) => bytes switch
{
< 1024 * 1024 => $"{Math.Max(1, bytes / 1024)} KB",
< 1024L * 1024 * 1024 => $"{bytes / 1024.0 / 1024:0.#} MB",
_ => $"{bytes / 1024.0 / 1024 / 1024:0.##} GB",
};
}
+352
View File
@@ -0,0 +1,352 @@
<Window x:Class="GitManagerSetup.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Git Manager GUI Setup" Icon="app.ico" Width="780" Height="520" ResizeMode="CanMinimize"
Background="{DynamicResource LayerBrush}" Foreground="{DynamicResource TextBrush}"
FontFamily="{DynamicResource UiFont}" FontSize="14"
TextOptions.TextFormattingMode="Display" UseLayoutRounding="True"
WindowStartupLocation="CenterScreen">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="36" ResizeBorderThickness="0" GlassFrameThickness="0,0,0,1"
CornerRadius="0" UseAeroCaptionButtons="False"/>
</WindowChrome.WindowChrome>
<Window.Resources>
<!-- Markenfarben der Seitenleiste (in Hell und Dunkel gleich, wie die App) -->
<SolidColorBrush x:Key="SideText" Color="#F5F8FF"/>
<SolidColorBrush x:Key="SideTextSecondary" Color="#AEBDD8"/>
<SolidColorBrush x:Key="SideTextMuted" Color="#7083A4"/>
<LinearGradientBrush x:Key="BrandGradient" StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#58D5FF" Offset="0"/>
<GradientStop Color="#5C87FF" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="PageTitle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{DynamicResource DisplayFont}"/>
<Setter Property="FontSize" Value="26"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Margin" Value="0,0,0,8"/>
</Style>
<Style x:Key="Body" TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="LineHeight" Value="21"/>
<Setter Property="Foreground" Value="{DynamicResource TextSecondaryBrush}"/>
</Style>
<Style x:Key="StepDot" TargetType="Border">
<Setter Property="Width" Value="26"/>
<Setter Property="Height" Value="26"/>
<Setter Property="CornerRadius" Value="13"/>
<Setter Property="BorderThickness" Value="1.5"/>
</Style>
<Style x:Key="StepNum" TargetType="TextBlock">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="StepLabel" TargetType="TextBlock">
<Setter Property="Margin" Value="12,0,0,0"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="FontSize" Value="13.5"/>
</Style>
<Style x:Key="StepLine" TargetType="Border">
<Setter Property="Width" Value="2"/>
<Setter Property="Height" Value="18"/>
<Setter Property="Margin" Value="12,3,0,3"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="CornerRadius" Value="1"/>
</Style>
<Style x:Key="FeatureIcon" TargetType="Border">
<Setter Property="Width" Value="38"/>
<Setter Property="Height" Value="38"/>
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Background" Value="{DynamicResource AccentSubtleBrush}"/>
<Setter Property="VerticalAlignment" Value="Top"/>
</Style>
<Style x:Key="FeatureGlyph" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{DynamicResource IconFont}"/>
<Setter Property="FontSize" Value="17"/>
<Setter Property="Foreground" Value="{DynamicResource AccentBrush}"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="FeatureTitle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="13.5"/>
</Style>
<Style x:Key="FeatureText" TargetType="TextBlock">
<Setter Property="FontSize" Value="12"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Margin" Value="0,2,0,0"/>
<Setter Property="Foreground" Value="{DynamicResource TextSecondaryBrush}"/>
</Style>
<Style x:Key="Card" TargetType="Border">
<Setter Property="Padding" Value="16,14"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Background" Value="{DynamicResource ControlFillBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="36"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ===== Seitenleiste im Look der App ===== -->
<Border Grid.RowSpan="3" ClipToBounds="True">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0.6,1">
<GradientStop Color="#07111F" Offset="0"/>
<GradientStop Color="#0D1729" Offset="0.5"/>
<GradientStop Color="#13305C" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Grid>
<!-- Lichtschein hinter dem Logo und unten -->
<Ellipse Width="320" Height="320" Margin="-120,-110,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" IsHitTestVisible="False">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#5558D5FF" Offset="0"/>
<GradientStop Color="#0058D5FF" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Width="300" Height="300" Margin="0,0,-150,-150" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsHitTestVisible="False">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="#445C87FF" Offset="0"/>
<GradientStop Color="#005C87FF" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<StackPanel Margin="30,64,24,0">
<Image Source="app.png" Width="68" Height="68" HorizontalAlignment="Left" RenderOptions.BitmapScalingMode="HighQuality">
<Image.Effect>
<DropShadowEffect Color="#58D5FF" BlurRadius="28" ShadowDepth="0" Opacity="0.6"/>
</Image.Effect>
</Image>
<TextBlock Text="Git Manager" FontFamily="{DynamicResource DisplayFont}" FontSize="26" FontWeight="SemiBold"
Foreground="{StaticResource SideText}" Margin="0,16,0,0"/>
<TextBlock x:Name="VersionText" Foreground="{StaticResource SideTextSecondary}" FontSize="12" Margin="0,2,0,0"/>
<StackPanel x:Name="Steps" Margin="0,38,0,0">
<StackPanel Orientation="Horizontal">
<Border x:Name="Dot0" Style="{StaticResource StepDot}"><TextBlock x:Name="Num0" Text="1" Style="{StaticResource StepNum}"/></Border>
<TextBlock x:Name="Label0" Text="Willkommen" Style="{StaticResource StepLabel}"/>
</StackPanel>
<Border x:Name="Line0" Style="{StaticResource StepLine}"/>
<StackPanel Orientation="Horizontal">
<Border x:Name="Dot1" Style="{StaticResource StepDot}"><TextBlock x:Name="Num1" Text="2" Style="{StaticResource StepNum}"/></Border>
<TextBlock x:Name="Label1" Text="Optionen" Style="{StaticResource StepLabel}"/>
</StackPanel>
<Border x:Name="Line1" Style="{StaticResource StepLine}"/>
<StackPanel Orientation="Horizontal">
<Border x:Name="Dot2" Style="{StaticResource StepDot}"><TextBlock x:Name="Num2" Text="3" Style="{StaticResource StepNum}"/></Border>
<TextBlock x:Name="Label2" Text="Installation" Style="{StaticResource StepLabel}"/>
</StackPanel>
</StackPanel>
</StackPanel>
<TextBlock Text="© M_Viper" FontSize="11" Foreground="{StaticResource SideTextMuted}"
VerticalAlignment="Bottom" Margin="30,0,0,20"/>
</Grid>
</Border>
<!-- Titelleiste -->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="14,0,0,0">
<Image Source="app.ico" Width="16" Height="16" RenderOptions.BitmapScalingMode="HighQuality"/>
<TextBlock x:Name="WindowTitle" Text="Git Manager GUI Setup" FontSize="12" Margin="10,0,0,0" VerticalAlignment="Center"
Foreground="{StaticResource SideTextSecondary}"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button Style="{StaticResource CaptionButton}" Content="&#xE921;" Click="Minimize_Click"
WindowChrome.IsHitTestVisibleInChrome="True"/>
<Button x:Name="CloseButton" Style="{StaticResource CloseCaptionButton}" Content="&#xE8BB;" Click="Cancel_Click"
WindowChrome.IsHitTestVisibleInChrome="True"/>
</StackPanel>
<!-- ===== Inhalt ===== -->
<Grid Grid.Row="1" Grid.Column="1" Margin="40,18,40,0">
<!-- 0: Willkommen -->
<StackPanel x:Name="PageWelcome">
<TextBlock Text="Willkommen beim Git Manager" Style="{StaticResource PageTitle}"/>
<TextBlock Style="{StaticResource Body}"
Text="Der Assistent richtet Git Manager GUI in wenigen Schritten ein – nur für dein Benutzerkonto und ohne Administratorrechte."/>
<Grid Margin="0,24,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="18"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DockPanel>
<Border Style="{StaticResource FeatureIcon}" DockPanel.Dock="Left"><TextBlock Text="&#xE753;" Style="{StaticResource FeatureGlyph}"/></Border>
<StackPanel Margin="12,0,0,0">
<TextBlock Text="Gitea &amp; GitHub" Style="{StaticResource FeatureTitle}"/>
<TextBlock Text="Repos, Dateien, Releases und Commits an einem Ort" Style="{StaticResource FeatureText}"/>
</StackPanel>
</DockPanel>
<DockPanel Grid.Column="2">
<Border Style="{StaticResource FeatureIcon}" DockPanel.Dock="Left"><TextBlock Text="&#xE943;" Style="{StaticResource FeatureGlyph}"/></Border>
<StackPanel Margin="12,0,0,0">
<TextBlock Text="Git eingebaut" Style="{StaticResource FeatureTitle}"/>
<TextBlock Text="Kein zusätzliches Programm nötig" Style="{StaticResource FeatureText}"/>
</StackPanel>
</DockPanel>
<DockPanel Grid.Row="2">
<Border Style="{StaticResource FeatureIcon}" DockPanel.Dock="Left"><TextBlock Text="&#xE8C8;" Style="{StaticResource FeatureGlyph}"/></Border>
<StackPanel Margin="12,0,0,0">
<TextBlock Text="PRs &amp; Issues" Style="{StaticResource FeatureTitle}"/>
<TextBlock Text="Ansehen, kommentieren und mergen" Style="{StaticResource FeatureText}"/>
</StackPanel>
</DockPanel>
<DockPanel Grid.Row="2" Grid.Column="2">
<Border Style="{StaticResource FeatureIcon}" DockPanel.Dock="Left"><TextBlock Text="&#xE777;" Style="{StaticResource FeatureGlyph}"/></Border>
<StackPanel Margin="12,0,0,0">
<TextBlock Text="Backup" Style="{StaticResource FeatureTitle}"/>
<TextBlock Text="Alle Repos sichern und wiederherstellen" Style="{StaticResource FeatureText}"/>
</StackPanel>
</DockPanel>
</Grid>
<Border x:Name="UpdateHint" Margin="0,26,0,0" Padding="14,10" CornerRadius="8" Visibility="Collapsed"
Background="{DynamicResource AccentSubtleBrush}" BorderBrush="{DynamicResource AccentSubtleStrokeBrush}" BorderThickness="1">
<DockPanel>
<TextBlock DockPanel.Dock="Left" Text="&#xE946;" FontFamily="{DynamicResource IconFont}" FontSize="16"
Foreground="{DynamicResource AccentBrush}" Margin="0,2,12,0" VerticalAlignment="Top"/>
<TextBlock x:Name="UpdateHintText" TextWrapping="Wrap" LineHeight="20" FontSize="13"/>
</DockPanel>
</Border>
<Border x:Name="RunningHint" Margin="0,10,0,0" Padding="14,10" CornerRadius="8" Visibility="Collapsed"
Background="{DynamicResource ControlFillBrush}" BorderBrush="{DynamicResource ControlStrokeBrush}" BorderThickness="1">
<DockPanel>
<TextBlock DockPanel.Dock="Left" Text="&#xE7BA;" FontFamily="{DynamicResource IconFont}" FontSize="16"
Foreground="{DynamicResource AccentBrush}" Margin="0,2,12,0" VerticalAlignment="Top"/>
<TextBlock TextWrapping="Wrap" LineHeight="20" FontSize="13"
Text="Git Manager GUI läuft gerade und wird für die Installation automatisch beendet. Laufende Uploads gehen dabei verloren."/>
</DockPanel>
</Border>
</StackPanel>
<!-- 1: Optionen -->
<StackPanel x:Name="PageOptions" Visibility="Collapsed">
<TextBlock Text="Optionen" Style="{StaticResource PageTitle}"/>
<TextBlock Style="{StaticResource Body}" Text="Wohin soll Git Manager GUI installiert werden?"/>
<Border Style="{StaticResource Card}" Margin="0,18,0,0">
<StackPanel>
<TextBlock Text="Installationsordner" FontWeight="SemiBold" FontSize="13" Margin="0,0,0,10"/>
<DockPanel>
<Button DockPanel.Dock="Right" Content="Ändern …" Margin="8,0,0,0" Click="ChangeDir_Click"/>
<TextBox x:Name="DirBox"/>
</DockPanel>
<TextBlock Style="{StaticResource Body}" FontSize="12" LineHeight="18" Margin="0,10,0,0"
Text="Benötigt ca. 450 MB. Zugangsdaten, Einstellungen und Favoriten liegen getrennt davon und bleiben bei Updates erhalten."/>
</StackPanel>
</Border>
<Border Style="{StaticResource Card}" Margin="0,12,0,0">
<StackPanel>
<CheckBox x:Name="DesktopLinkBox" Content="Verknüpfung auf dem Desktop" IsChecked="True"/>
</StackPanel>
</Border>
</StackPanel>
<!-- 2: Fortschritt / Fertig -->
<StackPanel x:Name="PageProgress" Visibility="Collapsed">
<Border x:Name="SuccessIcon" Width="64" Height="64" CornerRadius="32" HorizontalAlignment="Left" Margin="0,4,0,20"
Background="{StaticResource BrandGradient}" RenderTransformOrigin="0.5,0.5" Visibility="Collapsed">
<Border.RenderTransform><ScaleTransform x:Name="SuccessScale" ScaleX="1" ScaleY="1"/></Border.RenderTransform>
<Border.Effect><DropShadowEffect Color="#58D5FF" BlurRadius="24" ShadowDepth="0" Opacity="0.5"/></Border.Effect>
<TextBlock Text="&#xE73E;" FontFamily="{DynamicResource IconFont}" FontSize="26" Foreground="#04101F"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<TextBlock x:Name="ProgressTitle" Text="Git Manager GUI wird installiert …" Style="{StaticResource PageTitle}"/>
<StackPanel x:Name="ProgressBarPanel" Margin="0,18,0,0">
<TextBlock x:Name="PercentText" Text="0 %" FontFamily="{DynamicResource DisplayFont}" FontSize="44" FontWeight="SemiBold"
Foreground="{DynamicResource AccentBrush}"/>
<Border x:Name="ProgressTrack" SizeChanged="ProgressTrack_SizeChanged" Height="8" CornerRadius="4" Margin="0,10,0,0" Background="{DynamicResource SubtleSelectedBrush}">
<Border x:Name="ProgressFill" HorizontalAlignment="Left" Width="0" CornerRadius="4" Background="{StaticResource BrandGradient}"/>
</Border>
</StackPanel>
<TextBlock x:Name="ProgressText" Style="{StaticResource Body}" Margin="0,12,0,0" Text="Einen Moment bitte."/>
<StackPanel x:Name="DonePanel" Visibility="Collapsed">
<CheckBox x:Name="LaunchBox" Content="Git Manager GUI jetzt starten" IsChecked="True" Margin="0,24,0,0"/>
</StackPanel>
</StackPanel>
<!-- Deinstallation -->
<StackPanel x:Name="PageUninstall" Visibility="Collapsed">
<TextBlock Text="Git Manager GUI deinstallieren" Style="{StaticResource PageTitle}"/>
<TextBlock Style="{StaticResource Body}"
Text="Git Manager GUI wird von deinem PC entfernt: Programm, Verknüpfungen, Autostart und der Eintrag in den Windows-Einstellungen."/>
<Border Style="{StaticResource Card}" Margin="0,22,0,0">
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="&#xE72E;" FontFamily="{DynamicResource IconFont}" FontSize="15" Foreground="{DynamicResource AccentBrush}"
VerticalAlignment="Center"/>
<TextBlock Text="Deine Zugangsdaten und Einstellungen bleiben erhalten" FontWeight="SemiBold" Margin="10,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
<TextBlock x:Name="DataInfo" Style="{StaticResource Body}" FontSize="12.5" Margin="0,6,0,14"/>
<CheckBox x:Name="RemoveDataBox" Content="Auch Zugangsdaten, Einstellungen, Favoriten und Verlauf löschen"
Checked="RemoveDataBox_Click" Unchecked="RemoveDataBox_Click"/>
<TextBlock x:Name="RemoveDataWarning" Visibility="Collapsed" Margin="30,8,0,0" TextWrapping="Wrap" FontSize="12.5"
Foreground="{DynamicResource DangerBrush}"
Text="Die gespeicherten Tokens für Gitea und GitHub werden entfernt (sie landen im Papierkorb). Deine Repos auf dem Server, lokale Projektordner und Repo-Backups bleiben unangetastet."/>
</StackPanel>
</Border>
</StackPanel>
</Grid>
<!-- Fußleiste -->
<StackPanel Grid.Row="2" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,14,40,24">
<Button x:Name="BackButton" Content="Zurück" Width="110" Margin="0,0,8,0" Click="Back_Click"/>
<Button x:Name="NextButton" Content="Weiter" Width="140" Margin="0,0,8,0" Style="{StaticResource AccentButton}" IsDefault="True" Click="Next_Click"/>
<Button x:Name="CancelButton" Content="Abbrechen" Width="110" Click="Cancel_Click"/>
</StackPanel>
<!-- Eigene Rückfrage im Setup-Look statt Windows-Meldungsfenster (siehe Frage()) -->
<Grid x:Name="DialogOverlay" Grid.RowSpan="3" Grid.ColumnSpan="2" Visibility="Collapsed" Background="#99000000">
<Border x:Name="DialogCard" Width="420" HorizontalAlignment="Center" VerticalAlignment="Center"
Background="{DynamicResource LayerBrush}" BorderBrush="{DynamicResource ControlStrokeBrush}" BorderThickness="1"
CornerRadius="10" Padding="26,22,22,18" Effect="{StaticResource DialogShadow}" RenderTransformOrigin="0.5,0.5">
<Border.RenderTransform><ScaleTransform x:Name="DialogScale" ScaleX="1" ScaleY="1"/></Border.RenderTransform>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Border Width="34" Height="34" CornerRadius="17" Background="{DynamicResource AccentSubtleBrush}" VerticalAlignment="Top">
<TextBlock x:Name="DialogIcon" Text="&#xE7BA;" FontFamily="{DynamicResource IconFont}" FontSize="16"
Foreground="{DynamicResource AccentBrush}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<TextBlock x:Name="DialogTitle" FontFamily="{DynamicResource DisplayFont}" FontSize="18" FontWeight="SemiBold"
VerticalAlignment="Center" Margin="12,0,0,0" TextWrapping="Wrap" MaxWidth="320"/>
</StackPanel>
<TextBlock x:Name="DialogText" TextWrapping="Wrap" LineHeight="20" Margin="46,8,0,0"
Foreground="{DynamicResource TextSecondaryBrush}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,22,0,0">
<Button x:Name="DialogSecondary" MinWidth="120" Margin="0,0,8,0" Click="DialogSecondary_Click"/>
<Button x:Name="DialogPrimary" MinWidth="130" Style="{StaticResource AccentButton}" Click="DialogPrimary_Click"/>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Grid>
</Window>
+454
View File
@@ -0,0 +1,454 @@
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
namespace GitManagerSetup;
public partial class MainWindow : Window
{
private readonly SetupMode _mode;
private int _page;
private bool _busy;
private bool _done;
private string? _installedExe;
private const int PageNumOptions = 1;
private const int PageNumProgress = 2;
public MainWindow(SetupMode mode)
{
InitializeComponent();
_mode = mode;
VersionText.Text = $"Version {Installer.Version}";
var installed = Installer.InstalledDir;
DirBox.Text = installed ?? Installer.DefaultDir;
DesktopLinkBox.IsChecked = installed is null || Installer.DesktopLinkExists;
if (installed is not null)
{
UpdateHint.Visibility = Visibility.Visible;
UpdateHintText.Text = Installer.InstalledVersion == Installer.Version
? $"Git Manager GUI {Installer.Version} ist bereits installiert und wird neu installiert. Zugangsdaten und Einstellungen bleiben erhalten."
: $"Die vorhandene Installation{(Installer.InstalledVersion is { } v ? $" (Version {v})" : "")} wird durch Version {Installer.Version} ersetzt. Zugangsdaten und Einstellungen bleiben erhalten.";
}
if (Installer.IsRunning(installed)) RunningHint.Visibility = Visibility.Visible;
switch (mode)
{
case SetupMode.Uninstall:
Title = WindowTitle.Text = "Git Manager GUI deinstallieren";
Steps.Visibility = Visibility.Collapsed;
ShowOnly(PageUninstall);
NextButton.Content = "Deinstallieren";
BackButton.Visibility = Visibility.Collapsed;
LoadDataInfo();
break;
case SetupMode.Update:
// aus der App heraus: ohne Rückfragen direkt aktualisieren und danach wieder starten
Title = WindowTitle.Text = "Git Manager GUI wird aktualisiert";
Steps.Visibility = Visibility.Collapsed;
Loaded += async (_, _) => await RunInstall(DirBox.Text, DesktopLinkBox.IsChecked == true, update: true);
ShowOnly(PageProgress);
ProgressTitle.Text = "Git Manager GUI wird aktualisiert …";
BackButton.Visibility = Visibility.Hidden;
break;
default:
ShowPage(0);
break;
}
}
// ---------- Seiten ----------
private UIElement? _shownPage;
/// <summary>Seite wechseln – mit kurzem Einblenden von rechts.</summary>
private void ShowOnly(UIElement page)
{
foreach (var p in new UIElement[] { PageWelcome, PageOptions, PageProgress, PageUninstall })
p.Visibility = p == page ? Visibility.Visible : Visibility.Collapsed;
if (page == _shownPage) return;
_shownPage = page;
var ease = new CubicEase { EasingMode = EasingMode.EaseOut };
var slide = new TranslateTransform(18, 0);
page.RenderTransform = slide;
slide.BeginAnimation(TranslateTransform.XProperty, new DoubleAnimation(18, 0, TimeSpan.FromMilliseconds(260)) { EasingFunction = ease });
page.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(220)));
}
// Farben der Schritt-Anzeige in der (immer dunklen) Seitenleiste – Cyan wie in der App
private static readonly Brush StepDoneFill = Frozen(Color.FromRgb(0x58, 0xD5, 0xFF));
private static readonly Brush StepDoneGlyph = Frozen(Color.FromRgb(0x04, 0x10, 0x1F));
private static readonly Brush StepCurrentFill = Brushes.White;
private static readonly Brush StepCurrentText = Frozen(Color.FromRgb(0x13, 0x30, 0x5C));
private static readonly Brush StepUpcoming = Frozen(Color.FromRgb(0x70, 0x83, 0xA4));
private static readonly Brush StepUpcomingStroke = Frozen(Color.FromRgb(0x3A, 0x4E, 0x72));
private static readonly Brush StepDoneText = Frozen(Color.FromRgb(0xAE, 0xBD, 0xD8));
private static readonly Brush StepLineIdle = Frozen(Color.FromRgb(0x24, 0x36, 0x58));
private static Brush Frozen(Color c)
{
var b = new SolidColorBrush(c);
b.Freeze();
return b;
}
private void UpdateSteps(int page)
{
var dots = new[] { Dot0, Dot1, Dot2 };
var nums = new[] { Num0, Num1, Num2 };
var labels = new[] { Label0, Label1, Label2 };
var lines = new[] { Line0, Line1 };
var iconFont = (FontFamily)FindResource("IconFont");
var uiFont = (FontFamily)FindResource("UiFont");
for (int i = 0; i < dots.Length; i++)
{
bool done = i < page || (_done && i == page);
bool current = i == page && !done;
dots[i].Background = done ? StepDoneFill : current ? StepCurrentFill : Brushes.Transparent;
dots[i].BorderBrush = done ? StepDoneFill : current ? StepCurrentFill : StepUpcomingStroke;
nums[i].Text = done ? "" : (i + 1).ToString();
nums[i].FontFamily = done ? iconFont : uiFont;
nums[i].FontSize = done ? 11 : 12;
nums[i].Foreground = done ? StepDoneGlyph : current ? StepCurrentText : StepUpcoming;
labels[i].Foreground = current ? Brushes.White : done ? StepDoneText : StepUpcoming;
labels[i].FontWeight = current ? FontWeights.SemiBold : FontWeights.Normal;
}
for (int i = 0; i < lines.Length; i++)
lines[i].Background = i < page ? StepDoneFill : StepLineIdle;
}
private void ShowPage(int page)
{
_page = page;
ShowOnly(page switch { 0 => PageWelcome, PageNumOptions => PageOptions, _ => PageProgress });
UpdateSteps(page);
BackButton.Visibility = page == PageNumOptions ? Visibility.Visible : Visibility.Hidden;
NextButton.Content = page switch
{
PageNumOptions => "Installieren",
PageNumProgress => "Fertigstellen",
_ => "Weiter",
};
}
private void Back_Click(object sender, RoutedEventArgs e)
{
if (!_busy && _page > 0) ShowPage(_page - 1);
}
private async void Next_Click(object sender, RoutedEventArgs e)
{
if (_busy) return;
if (_mode == SetupMode.Uninstall)
{
if (_done) { Close(); return; }
await RunUninstall();
return;
}
if (_mode == SetupMode.Update)
{
Close(); // nur nach einem Fehler erreichbar
return;
}
switch (_page)
{
case 0: ShowPage(PageNumOptions); break;
case PageNumOptions:
var dir = DirBox.Text.Trim();
if (!IsFullPath(dir) || dir.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
{
await Frage("Ungültiger Ordner", "Bitte einen vollständigen Ordner angeben, z. B. C:\\Programme\\Git Manager GUI.", "OK");
return;
}
if (dir.TrimEnd('\\', '/').Length > Installer.MaxDirLength)
{
await Frage("Ordnerpfad zu lang",
$"Der Pfad hat {dir.TrimEnd('\\', '/').Length} Zeichen, Windows erlaubt hier höchstens {Installer.MaxDirLength}. " +
"Bitte einen kürzeren Ordner wählen.", "OK");
return;
}
await RunInstall(dir, DesktopLinkBox.IsChecked == true, update: false);
break;
case PageNumProgress:
// Start im Hintergrund: Process.Start kann blockieren, solange Windows
// die EXE prüft – das Fenster darf dabei nie einfrieren
if (LaunchBox.IsChecked == true)
{
_busy = true;
NextButton.IsEnabled = false;
NextButton.Content = "Wird gestartet …";
await Task.Run(StartApp);
_busy = false;
}
Close();
break;
}
}
private void ChangeDir_Click(object sender, RoutedEventArgs e)
{
using var dlg = new System.Windows.Forms.FolderBrowserDialog
{
Description = "Installationsordner wählen",
SelectedPath = Directory.Exists(DirBox.Text) ? DirBox.Text : Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
ShowNewFolderButton = true,
};
if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
var chosen = dlg.SelectedPath;
// wie bei üblichen Installern: Unterordner "Git Manager GUI" anhängen
DirBox.Text = Path.GetFileName(chosen.TrimEnd('\\')).Equals(Installer.AppName, StringComparison.OrdinalIgnoreCase)
? chosen : Path.Combine(chosen, Installer.AppName);
}
// ---------- Installation ----------
private async Task RunInstall(string dir, bool desktop, bool update)
{
_busy = true;
if (!update) ShowPage(PageNumProgress);
SetButtons(false);
var progress = new Progress<(double Value, string Text)>(p => SetProgress(p.Value, p.Text));
try
{
await Task.Run(() => Installer.Install(dir, desktop, progress, waitForExit: update));
_installedExe = Path.Combine(dir, Installer.ExeName);
_done = true;
if (update)
{
ShowSuccess("Update abgeschlossen", $"Git Manager GUI {Installer.Version} wird gestartet …");
StartApp();
_busy = false;
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1.5) };
timer.Tick += (_, _) => { timer.Stop(); Close(); };
timer.Start();
return;
}
ShowSuccess("Alles bereit!", "Git Manager GUI ist installiert. Du findest es im Startmenü" + (desktop ? " und auf dem Desktop." : "."));
DonePanel.Visibility = Visibility.Visible;
ShowPage(PageNumProgress);
}
catch (Exception ex)
{
ProgressTitle.Text = update ? "Update fehlgeschlagen" : "Installation fehlgeschlagen";
ProgressBarPanel.Visibility = Visibility.Collapsed;
ProgressText.Text = ex.Message;
ProgressText.Foreground = (Brush)FindResource("DangerBrush");
NextButton.Content = "Schließen";
_installedExe = null;
}
_busy = false;
NextButton.IsEnabled = true;
CloseButton.IsEnabled = true;
BackButton.Visibility = Visibility.Hidden;
CancelButton.Visibility = Visibility.Collapsed;
}
/// <summary>Fortschritt ausblenden und den Haken mit kurzem "Aufploppen" zeigen.</summary>
private void ShowSuccess(string title, string text)
{
ProgressBarPanel.Visibility = Visibility.Collapsed;
ProgressTitle.Text = title;
ProgressText.Text = text;
SuccessIcon.Visibility = Visibility.Visible;
var pop = new DoubleAnimation(0.4, 1, TimeSpan.FromMilliseconds(420)) { EasingFunction = new BackEase { EasingMode = EasingMode.EaseOut, Amplitude = 0.5 } };
SuccessScale.BeginAnimation(ScaleTransform.ScaleXProperty, pop);
SuccessScale.BeginAnimation(ScaleTransform.ScaleYProperty, pop);
SuccessIcon.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(200)));
}
private void StartApp()
{
if (_installedExe is null || !File.Exists(_installedExe)) return;
try
{
Process.Start(new ProcessStartInfo(_installedExe)
{
UseShellExecute = true,
WorkingDirectory = Path.GetDirectoryName(_installedExe)!,
});
}
catch { }
}
// ---------- Deinstallation ----------
private async void LoadDataInfo()
{
var root = Installer.DataDir;
if (!Directory.Exists(root))
{
DataInfo.Text = "Es wurden keine App-Daten gefunden.";
RemoveDataBox.IsEnabled = false;
return;
}
DataInfo.Text = $"Sie liegen in {root}. Größe wird berechnet …";
var size = await Task.Run(Installer.DataSize);
DataInfo.Text = $"Sie liegen in {root} ({Installer.FormatSize(size)}) und stehen wieder bereit, falls du Git Manager GUI später neu installierst.";
}
private void RemoveDataBox_Click(object sender, RoutedEventArgs e) =>
RemoveDataWarning.Visibility = RemoveDataBox.IsChecked == true ? Visibility.Visible : Visibility.Collapsed;
private async Task RunUninstall()
{
_busy = true;
bool removeData = RemoveDataBox.IsChecked == true;
ShowOnly(PageProgress);
ProgressTitle.Text = "Git Manager GUI wird entfernt …";
LaunchBox.Visibility = Visibility.Collapsed;
SetButtons(false);
var progress = new Progress<(double Value, string Text)>(p => SetProgress(p.Value, p.Text));
try
{
await Task.Run(() => Installer.Uninstall(removeData, progress));
ShowSuccess("Git Manager GUI wurde entfernt", removeData
? "Programm, Zugangsdaten und Einstellungen wurden entfernt (die Daten liegen im Papierkorb)."
: "Deine Zugangsdaten und Einstellungen liegen weiterhin in " + Installer.DataDir + " – falls du Git Manager GUI später wieder installierst.");
}
catch (Exception ex)
{
ProgressTitle.Text = "Deinstallation fehlgeschlagen";
ProgressBarPanel.Visibility = Visibility.Collapsed;
ProgressText.Text = ex.Message;
}
_done = true;
_busy = false;
CloseButton.IsEnabled = true;
NextButton.Content = "Schließen";
NextButton.IsEnabled = true;
CancelButton.Visibility = Visibility.Collapsed;
}
// ---------- Helfer ----------
private void SetButtons(bool enabled)
{
NextButton.IsEnabled = enabled;
BackButton.IsEnabled = enabled;
CancelButton.IsEnabled = enabled;
CloseButton.IsEnabled = enabled;
}
private void SetProgress(double value, string text)
{
if (_done) return;
ProgressText.Text = text;
PercentText.Text = $"{(int)Math.Round(value * 100)} %";
_progress = value;
AnimateProgress();
}
private double _progress;
private void AnimateProgress()
{
var target = Math.Max(0, ProgressTrack.ActualWidth * _progress);
ProgressFill.BeginAnimation(WidthProperty,
new DoubleAnimation(target, TimeSpan.FromMilliseconds(250)) { EasingFunction = new CubicEase() });
}
// Kommt der erste Wert, bevor die Seite fertig angeordnet ist (Breite 0), nachträglich richtig setzen
private void ProgressTrack_SizeChanged(object sender, SizeChangedEventArgs e) => AnimateProgress();
private static bool IsFullPath(string p) =>
p.Length >= 3 && char.IsLetter(p[0]) && p[1] == ':' && (p[2] == '\\' || p[2] == '/');
private void Minimize_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized;
private async void Cancel_Click(object sender, RoutedEventArgs e)
{
if (_busy || _dialog is not null) return;
if (!_done && _mode == SetupMode.Install && _page > 0)
{
bool abbrechen = await Frage("Installation abbrechen?",
"Git Manager GUI wird nicht installiert. Du kannst das Setup später jederzeit erneut starten.",
"Ja, abbrechen", "Weiter installieren", "\uE897");
if (!abbrechen) return;
}
Close();
}
// ---------- eigene Rückfragen im Setup-Look ----------
private TaskCompletionSource<bool>? _dialog;
/// <summary>
/// Zeigt eine Rückfrage über dem Fenster. Mit <paramref name="zurueck"/>: zwei Knöpfe –
/// der hervorgehobene ist der sichere Weg zurück (liefert false), der andere bestätigt (true).
/// Ohne: nur ein Hinweis mit einem Knopf (liefert true).
/// </summary>
private Task<bool> Frage(string titel, string text, string bestaetigen, string? zurueck = null, string symbol = "\uE7BA")
{
_dialog?.TrySetResult(false);
_dialog = new TaskCompletionSource<bool>();
DialogTitle.Text = titel;
DialogText.Text = text;
DialogIcon.Text = symbol;
if (zurueck is null)
{
DialogSecondary.Visibility = Visibility.Collapsed;
DialogPrimary.Content = bestaetigen;
}
else
{
DialogSecondary.Visibility = Visibility.Visible;
DialogSecondary.Content = bestaetigen;
DialogPrimary.Content = zurueck;
}
DialogOverlay.Visibility = Visibility.Visible;
var ein = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(160));
DialogOverlay.BeginAnimation(OpacityProperty, ein);
var groesse = new DoubleAnimation(0.94, 1, TimeSpan.FromMilliseconds(220)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } };
DialogScale.BeginAnimation(ScaleTransform.ScaleXProperty, groesse);
DialogScale.BeginAnimation(ScaleTransform.ScaleYProperty, groesse);
DialogPrimary.Focus();
return _dialog.Task;
}
private void SchliesseFrage(bool ergebnis)
{
if (_dialog is null) return;
var tcs = _dialog;
_dialog = null;
DialogOverlay.Visibility = Visibility.Collapsed;
tcs.TrySetResult(ergebnis);
}
// hervorgehobener Knopf: bei Rückfragen "zurück" (false), beim reinen Hinweis "OK" (true)
private void DialogPrimary_Click(object sender, RoutedEventArgs e) =>
SchliesseFrage(DialogSecondary.Visibility != Visibility.Visible);
private void DialogSecondary_Click(object sender, RoutedEventArgs e) => SchliesseFrage(true);
protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
// solange die Rückfrage offen ist: Enter = hervorgehobener Knopf, Esc = zurück
if (_dialog is not null)
{
if (e.Key == System.Windows.Input.Key.Escape) { SchliesseFrage(DialogSecondary.Visibility != Visibility.Visible); e.Handled = true; return; }
if (e.Key == System.Windows.Input.Key.Enter) { DialogPrimary_Click(this, new RoutedEventArgs()); e.Handled = true; return; }
}
base.OnPreviewKeyDown(e);
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
if (_busy) e.Cancel = true; // während der Installation nicht schließen
_dialog?.TrySetResult(false);
base.OnClosing(e);
}
}
+106
View File
@@ -0,0 +1,106 @@
using System.IO;
using System.IO.Compression;
using System.Text;
namespace GitManagerSetup;
/// <summary>
/// Die App liegt als ZIP hinten an der Setup-.exe angehängt:
/// [Setup.exe][ZIP][8 Byte: ZIP-Länge][8 Byte: "GITMGRPK"]
/// Windows ignoriert angehängte Daten beim Starten einer .exe.
/// </summary>
public static class Payload
{
private static readonly byte[] Magic = Encoding.ASCII.GetBytes("GITMGRPK");
private const int FooterSize = 16;
private static (long Offset, long Length)? _info;
private static bool _checked;
/// <summary>Position und Länge des ZIPs in dieser .exe, oder null (z. B. beim Deinstallationsprogramm).</summary>
public static (long Offset, long Length)? Info
{
get
{
if (_checked) return _info;
_checked = true;
try
{
using var f = File.OpenRead(Installer.SelfPath);
if (f.Length < FooterSize) return null;
f.Seek(-FooterSize, SeekOrigin.End);
var footer = new byte[FooterSize];
if (f.Read(footer, 0, FooterSize) != FooterSize) return null;
for (int i = 0; i < Magic.Length; i++)
if (footer[8 + i] != Magic[i]) return null;
long length = BitConverter.ToInt64(footer, 0);
long offset = f.Length - FooterSize - length;
if (length <= 0 || offset <= 0) return null;
_info = (offset, length);
}
catch { _info = null; }
return _info;
}
}
public static bool Exists => Info is not null;
/// <summary>Länge des eigentlichen Setup-Programms ohne Anhang.</summary>
public static long StubLength => Info?.Offset ?? new FileInfo(Installer.SelfPath).Length;
public static ZipArchive OpenArchive()
{
var info = Info ?? throw new InvalidOperationException("Die Installationsdaten fehlen in dieser Datei. Bitte das Setup neu herunterladen.");
var file = File.OpenRead(Installer.SelfPath);
return new ZipArchive(new SubStream(file, info.Offset, info.Length), ZipArchiveMode.Read, leaveOpen: false);
}
/// <summary>Nur-Lese-Ausschnitt einer Datei, damit ZipArchive den Anhang wie eine eigene Datei sieht.</summary>
private sealed class SubStream(Stream inner, long start, long length) : Stream
{
private long _pos;
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => length;
public override long Position
{
get => _pos;
set => _pos = Math.Max(0, Math.Min(value, length));
}
public override int Read(byte[] buffer, int offset, int count)
{
long left = length - _pos;
if (left <= 0) return 0;
if (count > left) count = (int)left;
inner.Position = start + _pos;
int n = inner.Read(buffer, offset, count);
_pos += n;
return n;
}
public override long Seek(long offset, SeekOrigin origin)
{
Position = origin switch
{
SeekOrigin.Begin => offset,
SeekOrigin.Current => _pos + offset,
_ => length + offset,
};
return _pos;
}
public override void Flush() { }
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
protected override void Dispose(bool disposing)
{
if (disposing) inner.Dispose();
base.Dispose(disposing);
}
}
}
+110
View File
@@ -0,0 +1,110 @@
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
namespace GitManagerSetup;
/// <summary>
/// Verknüpfungen (.lnk) über die Shell-Schnittstellen – inklusive AppUserModelID, damit
/// Taskleiste und Windows-Benachrichtigungen dem Git Manager wie bisher zuordnen (wie beim alten NSIS-Setup).
/// </summary>
public static class Shortcut
{
public static void Create(string link, string target, string description, string appUserModelId)
{
Directory.CreateDirectory(Path.GetDirectoryName(link)!);
var shellLink = (IShellLinkW)new CShellLink();
try
{
shellLink.SetPath(target);
shellLink.SetWorkingDirectory(Path.GetDirectoryName(target)!);
shellLink.SetIconLocation(target, 0);
shellLink.SetDescription(description);
var store = (IPropertyStore)shellLink;
var key = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 5); // PKEY_AppUserModel_ID
var value = new PropVariant { vt = 31 /* VT_LPWSTR */, p = Marshal.StringToCoTaskMemUni(appUserModelId) };
try
{
store.SetValue(ref key, ref value);
store.Commit();
}
finally { Marshal.FreeCoTaskMem(value.p); }
((IPersistFile)shellLink).Save(link, true);
}
finally { Marshal.ReleaseComObject(shellLink); }
}
/// <summary>Ziel einer vorhandenen Verknüpfung, oder null.</summary>
public static string? Target(string link)
{
if (!File.Exists(link)) return null;
var shellLink = (IShellLinkW)new CShellLink();
try
{
((IPersistFile)shellLink).Load(link, 0);
var sb = new StringBuilder(1024);
shellLink.GetPath(sb, sb.Capacity, IntPtr.Zero, 0);
return sb.ToString();
}
catch { return null; }
finally { Marshal.ReleaseComObject(shellLink); }
}
// ---------- COM ----------
[ComImport, Guid("00021401-0000-0000-C000-000000000046")]
private class CShellLink { }
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")]
private interface IShellLinkW
{
void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, IntPtr pfd, uint fFlags);
void GetIDList(out IntPtr ppidl);
void SetIDList(IntPtr pidl);
void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
void GetHotkey(out short pwHotkey);
void SetHotkey(short wHotkey);
void GetShowCmd(out int piShowCmd);
void SetShowCmd(int iShowCmd);
void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
void Resolve(IntPtr hwnd, uint fFlags);
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
private interface IPropertyStore
{
void GetCount(out uint cProps);
void GetAt(uint iProp, out PropertyKey pkey);
void GetValue(ref PropertyKey key, out PropVariant pv);
void SetValue(ref PropertyKey key, ref PropVariant pv);
void Commit();
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct PropertyKey(Guid fmtid, uint pid)
{
public Guid fmtid = fmtid;
public uint pid = pid;
}
// PROPVARIANT: 16 Byte (32 Bit) bzw. 24 Byte (64 Bit)
[StructLayout(LayoutKind.Sequential)]
private struct PropVariant
{
public ushort vt;
public ushort r1, r2, r3;
public IntPtr p;
public IntPtr p2;
}
}
+27
View File
@@ -0,0 +1,27 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="BaseBrush" Color="#202020"/>
<SolidColorBrush x:Key="LayerBrush" Color="#282828"/>
<SolidColorBrush x:Key="LayerStrokeBrush" Color="#1A1A1A"/>
<SolidColorBrush x:Key="SubtleHoverBrush" Color="#0FFFFFFF"/>
<SolidColorBrush x:Key="SubtlePressedBrush" Color="#0AFFFFFF"/>
<SolidColorBrush x:Key="SubtleSelectedBrush" Color="#14FFFFFF"/>
<SolidColorBrush x:Key="ControlFillBrush" Color="#2D2D2D"/>
<SolidColorBrush x:Key="ControlHoverBrush" Color="#323232"/>
<SolidColorBrush x:Key="ControlPressedBrush" Color="#272727"/>
<SolidColorBrush x:Key="ControlStrokeBrush" Color="#353535"/>
<SolidColorBrush x:Key="ControlStrongStrokeBrush" Color="#8A8A8A"/>
<SolidColorBrush x:Key="InputFocusBrush" Color="#1F1F1F"/>
<SolidColorBrush x:Key="TextBrush" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TextSecondaryBrush" Color="#C8C8C8"/>
<SolidColorBrush x:Key="TextTertiaryBrush" Color="#9A9A9A"/>
<SolidColorBrush x:Key="FlyoutBrush" Color="#2C2C2C"/>
<SolidColorBrush x:Key="FlyoutStrokeBrush" Color="#404040"/>
<SolidColorBrush x:Key="DialogFooterBrush" Color="#202020"/>
<SolidColorBrush x:Key="ScrollThumbBrush" Color="#9F9F9F"/>
<SolidColorBrush x:Key="OverlayBrush" Color="#66000000"/>
<SolidColorBrush x:Key="SuccessBrush" Color="#4CAF50"/>
<SolidColorBrush x:Key="DangerBrush" Color="#FF99A4"/>
<SolidColorBrush x:Key="FenceBrush" Color="#F21C1C1C"/>
<Color x:Key="ShadowColor">#000000</Color>
</ResourceDictionary>
+27
View File
@@ -0,0 +1,27 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="BaseBrush" Color="#F3F3F3"/>
<SolidColorBrush x:Key="LayerBrush" Color="#FAFAFA"/>
<SolidColorBrush x:Key="LayerStrokeBrush" Color="#E5E5E5"/>
<SolidColorBrush x:Key="SubtleHoverBrush" Color="#0A000000"/>
<SolidColorBrush x:Key="SubtlePressedBrush" Color="#06000000"/>
<SolidColorBrush x:Key="SubtleSelectedBrush" Color="#0F000000"/>
<SolidColorBrush x:Key="ControlFillBrush" Color="#FDFDFD"/>
<SolidColorBrush x:Key="ControlHoverBrush" Color="#F6F6F6"/>
<SolidColorBrush x:Key="ControlPressedBrush" Color="#F2F2F2"/>
<SolidColorBrush x:Key="ControlStrokeBrush" Color="#E3E3E3"/>
<SolidColorBrush x:Key="ControlStrongStrokeBrush" Color="#C4C4C4"/>
<SolidColorBrush x:Key="InputFocusBrush" Color="#FFFFFF"/>
<SolidColorBrush x:Key="TextBrush" Color="#1B1B1B"/>
<SolidColorBrush x:Key="TextSecondaryBrush" Color="#5D5D5D"/>
<SolidColorBrush x:Key="TextTertiaryBrush" Color="#8B8B8B"/>
<SolidColorBrush x:Key="FlyoutBrush" Color="#F9F9F9"/>
<SolidColorBrush x:Key="FlyoutStrokeBrush" Color="#DCDCDC"/>
<SolidColorBrush x:Key="DialogFooterBrush" Color="#F3F3F3"/>
<SolidColorBrush x:Key="ScrollThumbBrush" Color="#8A8A8A"/>
<SolidColorBrush x:Key="OverlayBrush" Color="#4D000000"/>
<SolidColorBrush x:Key="SuccessBrush" Color="#0F7B0F"/>
<SolidColorBrush x:Key="DangerBrush" Color="#C42B1C"/>
<SolidColorBrush x:Key="FenceBrush" Color="#F5F7F7F7"/>
<Color x:Key="ShadowColor">#000000</Color>
</ResourceDictionary>
+651
View File
@@ -0,0 +1,651 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Schriften: Windows 11 nutzt "Segoe UI Variable" / "Segoe Fluent Icons", Windows 10 fällt auf Segoe UI / MDL2 zurück -->
<FontFamily x:Key="UiFont">Segoe UI Variable Text, Segoe UI</FontFamily>
<FontFamily x:Key="DisplayFont">Segoe UI Variable Display, Segoe UI</FontFamily>
<FontFamily x:Key="IconFont">Segoe Fluent Icons, Segoe MDL2 Assets</FontFamily>
<DropShadowEffect x:Key="FlyoutShadow" BlurRadius="24" ShadowDepth="6" Direction="270" Opacity="0.18"
Color="Black"/>
<DropShadowEffect x:Key="DialogShadow" BlurRadius="40" ShadowDepth="12" Direction="270" Opacity="0.28"
Color="Black"/>
<!-- ===== Buttons ===== -->
<Style TargetType="Button">
<Setter Property="FontFamily" Value="{DynamicResource UiFont}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Background" Value="{DynamicResource ControlFillBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="14,5"/>
<Setter Property="MinHeight" Value="32"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4" Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center" RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource ControlHoverBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource ControlPressedBrush}"/>
<Setter Property="Opacity" Value="0.85"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource TextBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="AccentButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Foreground" Value="{DynamicResource OnAccentBrush}"/>
<Setter Property="Background" Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1" CornerRadius="4" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center" RecognizesAccessKey="True"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource AccentHoverBrush}"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource AccentHoverBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.8"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource TextBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Transparenter Button (Symbolleisten, Sidebar) -->
<Style x:Key="SubtleButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="9,6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}" CornerRadius="4" Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtlePressedBrush}"/>
<Setter Property="Opacity" Value="0.75"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.35"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Titelleisten-Buttons -->
<Style x:Key="CaptionButton" TargetType="Button">
<Setter Property="Width" Value="46"/>
<Setter Property="Height" Value="32"/>
<Setter Property="FontFamily" Value="{DynamicResource IconFont}"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtlePressedBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CloseCaptionButton" TargetType="Button" BasedOn="{StaticResource CaptionButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Bd" Background="Transparent">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#C42B1C"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Bd" Property="Background" Value="#C83C30"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== TextBox ===== -->
<Style TargetType="TextBox">
<Setter Property="FontFamily" Value="{DynamicResource UiFont}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="CaretBrush" Value="{DynamicResource TextBrush}"/>
<Setter Property="SelectionBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="Background" Value="{DynamicResource ControlFillBrush}"/>
<Setter Property="Padding" Value="10,6"/>
<Setter Property="MinHeight" Value="32"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Border x:Name="Bd" Background="{TemplateBinding Background}" CornerRadius="4"
BorderBrush="{DynamicResource ControlStrokeBrush}" BorderThickness="1"/>
<!-- Unterstrich wie bei Windows 11 -->
<Border x:Name="Line" Height="1" VerticalAlignment="Bottom" Margin="3,0" CornerRadius="0,0,4,4"
Background="{DynamicResource ControlStrongStrokeBrush}"/>
<ScrollViewer x:Name="PART_ContentHost" Margin="{TemplateBinding Padding}" VerticalAlignment="Center"
Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource ControlHoverBrush}"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource InputFocusBrush}"/>
<Setter TargetName="Line" Property="Height" Value="2"/>
<Setter TargetName="Line" Property="Margin" Value="1,0"/>
<Setter TargetName="Line" Property="Background" Value="{DynamicResource AccentBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== Scrollbar (schmal, wird beim Überfahren breiter) ===== -->
<Style x:Key="ScrollThumb" TargetType="Thumb">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Border Background="{DynamicResource ScrollThumbBrush}" CornerRadius="3"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="12"/>
<Setter Property="MinWidth" Value="12"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid Background="Transparent">
<Track x:Name="PART_Track" IsDirectionReversed="True">
<Track.Thumb>
<Thumb x:Name="Th" Style="{StaticResource ScrollThumb}" Width="3" HorizontalAlignment="Center" Opacity="0.7"/>
</Track.Thumb>
</Track>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Th" Property="Width" Value="6"/>
<Setter TargetName="Th" Property="Opacity" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
<Setter Property="Width" Value="Auto"/>
<Setter Property="MinWidth" Value="0"/>
<Setter Property="Height" Value="12"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid Background="Transparent">
<Track x:Name="PART_Track">
<Track.Thumb>
<Thumb x:Name="Th" Style="{StaticResource ScrollThumb}" Height="3" VerticalAlignment="Center" Opacity="0.7"/>
</Track.Thumb>
</Track>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Th" Property="Height" Value="6"/>
<Setter TargetName="Th" Property="Opacity" Value="1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<!-- ===== ToolTip ===== -->
<Style TargetType="ToolTip">
<Setter Property="FontFamily" Value="{DynamicResource UiFont}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="HasDropShadow" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Margin="8,4,8,12" Padding="9,6" CornerRadius="4" MaxWidth="320"
Background="{DynamicResource FlyoutBrush}" BorderBrush="{DynamicResource FlyoutStrokeBrush}" BorderThickness="1"
Effect="{StaticResource FlyoutShadow}">
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="TextBlock">
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== Kontextmenü ===== -->
<Style TargetType="ContextMenu">
<Setter Property="FontFamily" Value="{DynamicResource UiFont}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="HasDropShadow" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContextMenu">
<Border Margin="12,4,12,16" Padding="0,4" CornerRadius="8" MinWidth="200"
Background="{DynamicResource FlyoutBrush}" BorderBrush="{DynamicResource FlyoutStrokeBrush}" BorderThickness="1"
Effect="{StaticResource FlyoutShadow}">
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Cycle"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="Separator">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Separator">
<Border Height="1" Margin="0,4" Background="{DynamicResource FlyoutStrokeBrush}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="MenuItem">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuItem">
<Border x:Name="Bd" Background="Transparent" CornerRadius="4" Margin="4,1" Padding="11,0" Height="34">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="28"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter ContentSource="Icon" VerticalAlignment="Center" HorizontalAlignment="Left"
TextElement.FontFamily="{DynamicResource IconFont}" TextElement.FontSize="16"/>
<ContentPresenter Grid.Column="1" ContentSource="Header" VerticalAlignment="Center" RecognizesAccessKey="True"/>
<TextBlock x:Name="Gesture" Grid.Column="2" Text="{TemplateBinding InputGestureText}" FontSize="12"
VerticalAlignment="Center" Margin="24,0,0,0" Foreground="{DynamicResource TextTertiaryBrush}"/>
<TextBlock x:Name="Arrow" Grid.Column="2" Text="&#xE76C;" FontFamily="{DynamicResource IconFont}" FontSize="11"
VerticalAlignment="Center" Margin="24,0,0,0" Visibility="Collapsed"
Foreground="{DynamicResource TextSecondaryBrush}"/>
<Popup x:Name="PART_Popup" Placement="Right" HorizontalOffset="-4" VerticalOffset="-12"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
AllowsTransparency="True" Focusable="False" PopupAnimation="Fade">
<Border Margin="12,4,12,16" Padding="0,4" CornerRadius="8" MinWidth="180"
Background="{DynamicResource FlyoutBrush}" BorderBrush="{DynamicResource FlyoutStrokeBrush}"
BorderThickness="1" Effect="{StaticResource FlyoutShadow}">
<ScrollViewer MaxHeight="420" VerticalScrollBarVisibility="Auto">
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Cycle"/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="Role" Value="SubmenuHeader">
<Setter TargetName="Arrow" Property="Visibility" Value="Visible"/>
<Setter TargetName="Gesture" Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== Listen ===== -->
<Style TargetType="ListBox">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<ScrollViewer Focusable="False" Padding="{TemplateBinding Padding}">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Navigationseintrag in der Seitenleiste -->
<Style x:Key="NavItem" TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Height" Value="38"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Margin="4,1" Background="Transparent">
<Border x:Name="Bd" CornerRadius="4" BorderThickness="1" BorderBrush="Transparent" Background="Transparent"/>
<Rectangle x:Name="Pill" Width="3" Height="16" RadiusX="1.5" RadiusY="1.5" HorizontalAlignment="Left"
Fill="{DynamicResource AccentBrush}" Visibility="Collapsed"/>
<ContentPresenter Margin="14,0,12,0" VerticalAlignment="Center"/>
<!-- Einfügelinie beim Umsortieren -->
<Border x:Name="InsertTop" Height="2" CornerRadius="1" VerticalAlignment="Top" Margin="6,-2,6,0"
Background="{DynamicResource AccentBrush}" Visibility="Collapsed"/>
<Border x:Name="InsertBottom" Height="2" CornerRadius="1" VerticalAlignment="Bottom" Margin="6,0,6,-2"
Background="{DynamicResource AccentBrush}" Visibility="Collapsed"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleSelectedBrush}"/>
<Setter TargetName="Pill" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="Tag" Value="before">
<Setter TargetName="InsertTop" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="Tag" Value="after">
<Setter TargetName="InsertBottom" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="Tag" Value="drop">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource AccentSubtleBrush}"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Icon-Kachel -->
<Style x:Key="TileItem" TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Bd" Margin="2" CornerRadius="6" BorderThickness="1" BorderBrush="Transparent" Background="Transparent">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource AccentSubtleBrush}"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource AccentSubtleStrokeBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== Listenansicht-Zeile ===== -->
<Style x:Key="RowItem" TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid Margin="0,1">
<Border x:Name="Bd" CornerRadius="4" Background="Transparent"/>
<Rectangle x:Name="Pill" Width="3" Height="16" RadiusX="1.5" RadiusY="1.5" HorizontalAlignment="Left"
Fill="{DynamicResource AccentBrush}" Visibility="Collapsed"/>
<ContentPresenter/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource AccentSubtleBrush}"/>
<Setter TargetName="Pill" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== Karte (Einstellungen) ===== -->
<Style x:Key="Card" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource ControlFillBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="6"/>
<Setter Property="Padding" Value="18,14"/>
<Setter Property="Margin" Value="0,0,0,4"/>
</Style>
<Style x:Key="SectionTitle" TargetType="TextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Margin" Value="2,24,0,8"/>
</Style>
<!-- ===== Kippschalter (Windows 11) ===== -->
<Style x:Key="ToggleSwitch" TargetType="CheckBox">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock x:Name="State" Text="Aus" VerticalAlignment="Center" Margin="0,0,12,0" MinWidth="24" TextAlignment="Right"/>
<Grid Width="40" Height="20">
<Border x:Name="Track" CornerRadius="10" BorderThickness="1"
Background="{DynamicResource SubtleSelectedBrush}" BorderBrush="{DynamicResource ControlStrongStrokeBrush}"/>
<Ellipse x:Name="Knob" Width="12" Height="12" HorizontalAlignment="Left" Margin="4,0,0,0"
Fill="{DynamicResource TextSecondaryBrush}"/>
</Grid>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Track" Property="Background" Value="{DynamicResource AccentBrush}"/>
<Setter TargetName="Track" Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter TargetName="Knob" Property="Fill" Value="{DynamicResource OnAccentBrush}"/>
<Setter TargetName="Knob" Property="HorizontalAlignment" Value="Right"/>
<Setter TargetName="Knob" Property="Margin" Value="0,0,4,0"/>
<Setter TargetName="State" Property="Text" Value="Ein"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Knob" Property="Width" Value="14"/>
<Setter TargetName="Knob" Property="Height" Value="14"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== Kontrollkästchen ===== -->
<Style TargetType="CheckBox">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="FontFamily" Value="{DynamicResource UiFont}"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<StackPanel Orientation="Horizontal" Background="Transparent">
<Border x:Name="Box" Width="20" Height="20" CornerRadius="4" BorderThickness="1" VerticalAlignment="Center"
Background="{DynamicResource ControlFillBrush}" BorderBrush="{DynamicResource ControlStrongStrokeBrush}">
<TextBlock x:Name="Check" Text="&#xE73E;" FontFamily="{DynamicResource IconFont}" FontSize="12"
Foreground="{DynamicResource OnAccentBrush}" HorizontalAlignment="Center" VerticalAlignment="Center"
Visibility="Collapsed"/>
</Border>
<ContentPresenter Margin="10,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Box" Property="Background" Value="{DynamicResource AccentBrush}"/>
<Setter TargetName="Box" Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter TargetName="Check" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Box" Property="Opacity" Value="0.85"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- ===== Segment-Auswahl (z. B. Hell | Dunkel | System) ===== -->
<Style x:Key="SegmentRadio" TargetType="RadioButton">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Padding" Value="14,6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border x:Name="Bd" CornerRadius="4" Padding="{TemplateBinding Padding}" Margin="2" Background="Transparent">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource AccentBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource OnAccentBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SegmentGroup" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource SubtlePressedBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ControlStrokeBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="6"/>
<Setter Property="Padding" Value="1"/>
</Style>
<!-- ===== Farb- und Symbolauswahl ===== -->
<Style x:Key="SwatchRadio" TargetType="RadioButton">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Grid Width="34" Height="34" Margin="0,0,6,6" Background="Transparent">
<Ellipse x:Name="Ring" Stroke="{DynamicResource TextBrush}" StrokeThickness="2" Visibility="Collapsed"/>
<Ellipse Margin="5" Fill="{TemplateBinding Background}" Stroke="{DynamicResource ControlStrokeBrush}"/>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Ring" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="GlyphRadio" TargetType="RadioButton">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="FontFamily" Value="{DynamicResource IconFont}"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border x:Name="Bd" Width="36" Height="36" Margin="0,0,4,4" CornerRadius="4" BorderThickness="1"
BorderBrush="Transparent" Background="Transparent">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource SubtleHoverBrush}"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Bd" Property="Background" Value="{DynamicResource AccentSubtleBrush}"/>
<Setter TargetName="Bd" Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="GitManager.Setup"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- Installation nur für den aktuellen Benutzer → keine Administratorrechte -->
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>
@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
Binary file not shown.
+77
View File
@@ -0,0 +1,77 @@
#pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "D722851FC43B542A95C365A4D89BC7E17AC3C32D"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms.Integration;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace GitManagerSetup {
/// <summary>
/// App
/// </summary>
public partial class App : System.Windows.Application {
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/Git-Manager-GUI-Setup;V0.0.0.0;component/app.xaml", System.UriKind.Relative);
#line 1 "..\..\..\App.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
public static void Main() {
GitManagerSetup.App app = new GitManagerSetup.App();
app.InitializeComponent();
app.Run();
}
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
@@ -0,0 +1,20 @@
Git-Manager-GUI-Setup
0.0.0.0
winexe
C#
.cs
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Debug\net48\
GitManagerSetup
none
false
TRACE;DEBUG;NETFRAMEWORK;NET48;NET30_OR_GREATER;NET35_OR_GREATER;NET40_OR_GREATER;NET45_OR_GREATER;NET451_OR_GREATER;NET452_OR_GREATER;NET46_OR_GREATER;NET461_OR_GREATER;NET462_OR_GREATER;NET47_OR_GREATER;NET471_OR_GREATER;NET472_OR_GREATER;NET48_OR_GREATER
C:\Users\Viper\Desktop\git-manager-gui\installer\App.xaml
41549299691
8-482891414
23-602304815
MainWindow.xaml;Themes\Colors.Dark.xaml;Themes\Colors.Light.xaml;Themes\Controls.xaml;
False
@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("M_Viper")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyCopyrightAttribute("Copyright (c) M_Viper")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("Installiert Git Manager GUI")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("0.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("0.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("Git Manager GUI Setup")]
[assembly: System.Reflection.AssemblyTitleAttribute("Git Manager GUI Setup")]
[assembly: System.Reflection.AssemblyVersionAttribute("0.0.0.0")]
[assembly: System.Resources.NeutralResourcesLanguageAttribute("de-DE")]
// Von der MSBuild WriteCodeFragment-Klasse generiert.
@@ -0,0 +1 @@
9c3aaae1d47c807c810117538379b6f2752577cee8cc71a0a6017da12833e788
@@ -0,0 +1,14 @@
is_global = true
build_property.ApplicationManifest = app.manifest
build_property.StartupObject =
build_property.ApplicationDefaultFont =
build_property.ApplicationHighDpiMode =
build_property.ApplicationUseCompatibleTextRendering =
build_property.ApplicationVisualStyles =
build_property.RootNamespace = GitManagerSetup
build_property.ProjectDir = C:\Users\Viper\Desktop\git-manager-gui\installer\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle =
build_property.EnableCodeStyleSeverity =
@@ -0,0 +1,6 @@
// <auto-generated/>
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
Binary file not shown.
+676
View File
@@ -0,0 +1,676 @@
#pragma checksum "..\..\..\MainWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "248163D303017091F6C4A571FD0B5DF4D5DBF414"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms.Integration;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace GitManagerSetup {
/// <summary>
/// MainWindow
/// </summary>
public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
#line 140 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock VersionText;
#line default
#line hidden
#line 142 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel Steps;
#line default
#line hidden
#line 144 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Dot0;
#line default
#line hidden
#line 144 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Num0;
#line default
#line hidden
#line 145 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Label0;
#line default
#line hidden
#line 147 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Line0;
#line default
#line hidden
#line 149 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Dot1;
#line default
#line hidden
#line 149 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Num1;
#line default
#line hidden
#line 150 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Label1;
#line default
#line hidden
#line 152 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Line1;
#line default
#line hidden
#line 154 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Dot2;
#line default
#line hidden
#line 154 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Num2;
#line default
#line hidden
#line 155 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Label2;
#line default
#line hidden
#line 168 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock WindowTitle;
#line default
#line hidden
#line 174 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button CloseButton;
#line default
#line hidden
#line 182 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageWelcome;
#line default
#line hidden
#line 229 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border UpdateHint;
#line default
#line hidden
#line 234 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock UpdateHintText;
#line default
#line hidden
#line 237 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border RunningHint;
#line default
#line hidden
#line 249 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageOptions;
#line default
#line hidden
#line 258 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBox DirBox;
#line default
#line hidden
#line 267 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox DesktopLinkBox;
#line default
#line hidden
#line 273 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageProgress;
#line default
#line hidden
#line 274 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border SuccessIcon;
#line default
#line hidden
#line 276 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Media.ScaleTransform SuccessScale;
#line default
#line hidden
#line 281 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock ProgressTitle;
#line default
#line hidden
#line 283 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel ProgressBarPanel;
#line default
#line hidden
#line 284 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock PercentText;
#line default
#line hidden
#line 286 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border ProgressTrack;
#line default
#line hidden
#line 287 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border ProgressFill;
#line default
#line hidden
#line 290 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock ProgressText;
#line default
#line hidden
#line 292 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel DonePanel;
#line default
#line hidden
#line 293 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox LaunchBox;
#line default
#line hidden
#line 298 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageUninstall;
#line default
#line hidden
#line 309 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DataInfo;
#line default
#line hidden
#line 310 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox RemoveDataBox;
#line default
#line hidden
#line 312 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock RemoveDataWarning;
#line default
#line hidden
#line 322 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button BackButton;
#line default
#line hidden
#line 323 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button NextButton;
#line default
#line hidden
#line 324 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button CancelButton;
#line default
#line hidden
#line 328 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Grid DialogOverlay;
#line default
#line hidden
#line 329 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border DialogCard;
#line default
#line hidden
#line 332 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Media.ScaleTransform DialogScale;
#line default
#line hidden
#line 336 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DialogIcon;
#line default
#line hidden
#line 339 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DialogTitle;
#line default
#line hidden
#line 342 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DialogText;
#line default
#line hidden
#line 345 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button DialogSecondary;
#line default
#line hidden
#line 346 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button DialogPrimary;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/Git-Manager-GUI-Setup;V0.0.0.0;component/mainwindow.xaml", System.UriKind.Relative);
#line 1 "..\..\..\MainWindow.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.VersionText = ((System.Windows.Controls.TextBlock)(target));
return;
case 2:
this.Steps = ((System.Windows.Controls.StackPanel)(target));
return;
case 3:
this.Dot0 = ((System.Windows.Controls.Border)(target));
return;
case 4:
this.Num0 = ((System.Windows.Controls.TextBlock)(target));
return;
case 5:
this.Label0 = ((System.Windows.Controls.TextBlock)(target));
return;
case 6:
this.Line0 = ((System.Windows.Controls.Border)(target));
return;
case 7:
this.Dot1 = ((System.Windows.Controls.Border)(target));
return;
case 8:
this.Num1 = ((System.Windows.Controls.TextBlock)(target));
return;
case 9:
this.Label1 = ((System.Windows.Controls.TextBlock)(target));
return;
case 10:
this.Line1 = ((System.Windows.Controls.Border)(target));
return;
case 11:
this.Dot2 = ((System.Windows.Controls.Border)(target));
return;
case 12:
this.Num2 = ((System.Windows.Controls.TextBlock)(target));
return;
case 13:
this.Label2 = ((System.Windows.Controls.TextBlock)(target));
return;
case 14:
this.WindowTitle = ((System.Windows.Controls.TextBlock)(target));
return;
case 15:
#line 172 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.Minimize_Click);
#line default
#line hidden
return;
case 16:
this.CloseButton = ((System.Windows.Controls.Button)(target));
#line 174 "..\..\..\MainWindow.xaml"
this.CloseButton.Click += new System.Windows.RoutedEventHandler(this.Cancel_Click);
#line default
#line hidden
return;
case 17:
this.PageWelcome = ((System.Windows.Controls.StackPanel)(target));
return;
case 18:
this.UpdateHint = ((System.Windows.Controls.Border)(target));
return;
case 19:
this.UpdateHintText = ((System.Windows.Controls.TextBlock)(target));
return;
case 20:
this.RunningHint = ((System.Windows.Controls.Border)(target));
return;
case 21:
this.PageOptions = ((System.Windows.Controls.StackPanel)(target));
return;
case 22:
#line 257 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.ChangeDir_Click);
#line default
#line hidden
return;
case 23:
this.DirBox = ((System.Windows.Controls.TextBox)(target));
return;
case 24:
this.DesktopLinkBox = ((System.Windows.Controls.CheckBox)(target));
return;
case 25:
this.PageProgress = ((System.Windows.Controls.StackPanel)(target));
return;
case 26:
this.SuccessIcon = ((System.Windows.Controls.Border)(target));
return;
case 27:
this.SuccessScale = ((System.Windows.Media.ScaleTransform)(target));
return;
case 28:
this.ProgressTitle = ((System.Windows.Controls.TextBlock)(target));
return;
case 29:
this.ProgressBarPanel = ((System.Windows.Controls.StackPanel)(target));
return;
case 30:
this.PercentText = ((System.Windows.Controls.TextBlock)(target));
return;
case 31:
this.ProgressTrack = ((System.Windows.Controls.Border)(target));
#line 286 "..\..\..\MainWindow.xaml"
this.ProgressTrack.SizeChanged += new System.Windows.SizeChangedEventHandler(this.ProgressTrack_SizeChanged);
#line default
#line hidden
return;
case 32:
this.ProgressFill = ((System.Windows.Controls.Border)(target));
return;
case 33:
this.ProgressText = ((System.Windows.Controls.TextBlock)(target));
return;
case 34:
this.DonePanel = ((System.Windows.Controls.StackPanel)(target));
return;
case 35:
this.LaunchBox = ((System.Windows.Controls.CheckBox)(target));
return;
case 36:
this.PageUninstall = ((System.Windows.Controls.StackPanel)(target));
return;
case 37:
this.DataInfo = ((System.Windows.Controls.TextBlock)(target));
return;
case 38:
this.RemoveDataBox = ((System.Windows.Controls.CheckBox)(target));
#line 311 "..\..\..\MainWindow.xaml"
this.RemoveDataBox.Checked += new System.Windows.RoutedEventHandler(this.RemoveDataBox_Click);
#line default
#line hidden
#line 311 "..\..\..\MainWindow.xaml"
this.RemoveDataBox.Unchecked += new System.Windows.RoutedEventHandler(this.RemoveDataBox_Click);
#line default
#line hidden
return;
case 39:
this.RemoveDataWarning = ((System.Windows.Controls.TextBlock)(target));
return;
case 40:
this.BackButton = ((System.Windows.Controls.Button)(target));
#line 322 "..\..\..\MainWindow.xaml"
this.BackButton.Click += new System.Windows.RoutedEventHandler(this.Back_Click);
#line default
#line hidden
return;
case 41:
this.NextButton = ((System.Windows.Controls.Button)(target));
#line 323 "..\..\..\MainWindow.xaml"
this.NextButton.Click += new System.Windows.RoutedEventHandler(this.Next_Click);
#line default
#line hidden
return;
case 42:
this.CancelButton = ((System.Windows.Controls.Button)(target));
#line 324 "..\..\..\MainWindow.xaml"
this.CancelButton.Click += new System.Windows.RoutedEventHandler(this.Cancel_Click);
#line default
#line hidden
return;
case 43:
this.DialogOverlay = ((System.Windows.Controls.Grid)(target));
return;
case 44:
this.DialogCard = ((System.Windows.Controls.Border)(target));
return;
case 45:
this.DialogScale = ((System.Windows.Media.ScaleTransform)(target));
return;
case 46:
this.DialogIcon = ((System.Windows.Controls.TextBlock)(target));
return;
case 47:
this.DialogTitle = ((System.Windows.Controls.TextBlock)(target));
return;
case 48:
this.DialogText = ((System.Windows.Controls.TextBlock)(target));
return;
case 49:
this.DialogSecondary = ((System.Windows.Controls.Button)(target));
#line 345 "..\..\..\MainWindow.xaml"
this.DialogSecondary.Click += new System.Windows.RoutedEventHandler(this.DialogSecondary_Click);
#line default
#line hidden
return;
case 50:
this.DialogPrimary = ((System.Windows.Controls.Button)(target));
#line 346 "..\..\..\MainWindow.xaml"
this.DialogPrimary.Click += new System.Windows.RoutedEventHandler(this.DialogPrimary_Click);
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,59 @@
{
"format": 1,
"restore": {
"C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\GitManagerSetup.csproj": {}
},
"projects": {
"C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\GitManagerSetup.csproj": {
"version": "0.0.0",
"restore": {
"projectUniqueName": "C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\GitManagerSetup.csproj",
"projectName": "Git-Manager-GUI-Setup",
"projectPath": "C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\GitManagerSetup.csproj",
"packagesPath": "C:\\Users\\Viper\\.nuget\\packages\\",
"outputPath": "C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Viper\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net48"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net48": {
"targetAlias": "net48",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
},
"frameworks": {
"net48": {
"targetAlias": "net48",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies": {
"suppressParent": "All",
"target": "Package",
"version": "[1.0.3, )",
"autoReferenced": true
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.113\\RuntimeIdentifierGraph.json"
}
}
}
}
}
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\Viper\.nuget\packages\</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">7.0.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\Viper\.nuget\packages\" />
</ItemGroup>
</Project>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)microsoft.netframework.referenceassemblies.net48\1.0.3\build\Microsoft.NETFramework.ReferenceAssemblies.net48.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.netframework.referenceassemblies.net48\1.0.3\build\Microsoft.NETFramework.ReferenceAssemblies.net48.targets')" />
</ImportGroup>
</Project>
@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
Binary file not shown.
+77
View File
@@ -0,0 +1,77 @@
#pragma checksum "..\..\..\App.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "D722851FC43B542A95C365A4D89BC7E17AC3C32D"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms.Integration;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace GitManagerSetup {
/// <summary>
/// App
/// </summary>
public partial class App : System.Windows.Application {
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/Git-Manager-GUI-Setup;component/app.xaml", System.UriKind.Relative);
#line 1 "..\..\..\App.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
/// <summary>
/// Application Entry Point.
/// </summary>
[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
public static void Main() {
GitManagerSetup.App app = new GitManagerSetup.App();
app.InitializeComponent();
app.Run();
}
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
@@ -0,0 +1,20 @@
Git-Manager-GUI-Setup
winexe
C#
.cs
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\
GitManagerSetup
none
false
TRACE;RELEASE;NETFRAMEWORK;NET48;NET30_OR_GREATER;NET35_OR_GREATER;NET40_OR_GREATER;NET45_OR_GREATER;NET451_OR_GREATER;NET452_OR_GREATER;NET46_OR_GREATER;NET461_OR_GREATER;NET462_OR_GREATER;NET47_OR_GREATER;NET471_OR_GREATER;NET472_OR_GREATER;NET48_OR_GREATER
C:\Users\Viper\Desktop\git-manager-gui\installer\App.xaml
41549299691
6-1705775420
23-602304815
MainWindow.xaml;Themes\Colors.Dark.xaml;Themes\Colors.Light.xaml;Themes\Controls.xaml;
False
@@ -0,0 +1,25 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("M_Viper")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyCopyrightAttribute("Copyright (c) M_Viper")]
[assembly: System.Reflection.AssemblyDescriptionAttribute("Installiert Git Manager GUI")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("2.2.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("2.2.0")]
[assembly: System.Reflection.AssemblyProductAttribute("Git Manager GUI Setup")]
[assembly: System.Reflection.AssemblyTitleAttribute("Git Manager GUI Setup")]
[assembly: System.Reflection.AssemblyVersionAttribute("2.2.0.0")]
[assembly: System.Resources.NeutralResourcesLanguageAttribute("de-DE")]
// Von der MSBuild WriteCodeFragment-Klasse generiert.
@@ -0,0 +1 @@
62f4b9ac7b1430e3a52ef9dfe2e8422ccd7cc5a7e41145550122532f56db4abe
@@ -0,0 +1,14 @@
is_global = true
build_property.ApplicationManifest = app.manifest
build_property.StartupObject =
build_property.ApplicationDefaultFont =
build_property.ApplicationHighDpiMode =
build_property.ApplicationUseCompatibleTextRendering =
build_property.ApplicationVisualStyles =
build_property.RootNamespace = GitManagerSetup
build_property.ProjectDir = C:\Users\Viper\Desktop\git-manager-gui\installer\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.CsWinRTUseWindowsUIXamlProjections = false
build_property.EffectiveAnalysisLevelStyle =
build_property.EnableCodeStyleSeverity =
@@ -0,0 +1,6 @@
// <auto-generated/>
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading;
global using System.Threading.Tasks;
@@ -0,0 +1 @@
4e41dc5e237f26559d3c4bd8208c813ba09bdba804615d78813773d6b0be3d1d
@@ -0,0 +1,19 @@
C:\Users\Viper\AppData\Local\Temp\claude\G--\bba0d154-b599-43ca-80e6-538e01f4f870\scratchpad\setupbuild\Git-Manager-GUI-Setup.exe.config
C:\Users\Viper\AppData\Local\Temp\claude\G--\bba0d154-b599-43ca-80e6-538e01f4f870\scratchpad\setupbuild\Git-Manager-GUI-Setup.exe
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\GitManagerSetup.csproj.AssemblyReference.cache
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\MainWindow.baml
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\Themes\Colors.Dark.baml
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\Themes\Colors.Light.baml
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\Themes\Controls.baml
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\App.baml
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\MainWindow.g.cs
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\App.g.cs
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\Git-Manager-GUI-Setup_MarkupCompile.cache
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\Git-Manager-GUI-Setup.g.resources
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\GitManagerSetup.GeneratedMSBuildEditorConfig.editorconfig
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\GitManagerSetup.AssemblyInfoInputs.cache
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\GitManagerSetup.AssemblyInfo.cs
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\GitManagerSetup.csproj.CoreCompileInputs.cache
C:\Users\Viper\Desktop\git-manager-gui\installer\obj\Release\net48\Git-Manager-GUI-Setup.exe
C:\Users\Viper\Desktop\git-manager-gui\dist\.setup\stub\Git-Manager-GUI-Setup.exe.config
C:\Users\Viper\Desktop\git-manager-gui\dist\.setup\stub\Git-Manager-GUI-Setup.exe
Binary file not shown.
+676
View File
@@ -0,0 +1,676 @@
#pragma checksum "..\..\..\MainWindow.xaml" "{ff1816ec-aa5e-4d10-87f7-6f4963833460}" "248163D303017091F6C4A571FD0B5DF4D5DBF414"
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Controls.Ribbon;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms.Integration;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Media.TextFormatting;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace GitManagerSetup {
/// <summary>
/// MainWindow
/// </summary>
public partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector {
#line 140 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock VersionText;
#line default
#line hidden
#line 142 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel Steps;
#line default
#line hidden
#line 144 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Dot0;
#line default
#line hidden
#line 144 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Num0;
#line default
#line hidden
#line 145 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Label0;
#line default
#line hidden
#line 147 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Line0;
#line default
#line hidden
#line 149 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Dot1;
#line default
#line hidden
#line 149 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Num1;
#line default
#line hidden
#line 150 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Label1;
#line default
#line hidden
#line 152 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Line1;
#line default
#line hidden
#line 154 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border Dot2;
#line default
#line hidden
#line 154 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Num2;
#line default
#line hidden
#line 155 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock Label2;
#line default
#line hidden
#line 168 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock WindowTitle;
#line default
#line hidden
#line 174 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button CloseButton;
#line default
#line hidden
#line 182 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageWelcome;
#line default
#line hidden
#line 229 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border UpdateHint;
#line default
#line hidden
#line 234 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock UpdateHintText;
#line default
#line hidden
#line 237 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border RunningHint;
#line default
#line hidden
#line 249 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageOptions;
#line default
#line hidden
#line 258 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBox DirBox;
#line default
#line hidden
#line 267 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox DesktopLinkBox;
#line default
#line hidden
#line 273 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageProgress;
#line default
#line hidden
#line 274 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border SuccessIcon;
#line default
#line hidden
#line 276 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Media.ScaleTransform SuccessScale;
#line default
#line hidden
#line 281 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock ProgressTitle;
#line default
#line hidden
#line 283 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel ProgressBarPanel;
#line default
#line hidden
#line 284 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock PercentText;
#line default
#line hidden
#line 286 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border ProgressTrack;
#line default
#line hidden
#line 287 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border ProgressFill;
#line default
#line hidden
#line 290 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock ProgressText;
#line default
#line hidden
#line 292 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel DonePanel;
#line default
#line hidden
#line 293 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox LaunchBox;
#line default
#line hidden
#line 298 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.StackPanel PageUninstall;
#line default
#line hidden
#line 309 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DataInfo;
#line default
#line hidden
#line 310 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.CheckBox RemoveDataBox;
#line default
#line hidden
#line 312 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock RemoveDataWarning;
#line default
#line hidden
#line 322 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button BackButton;
#line default
#line hidden
#line 323 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button NextButton;
#line default
#line hidden
#line 324 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button CancelButton;
#line default
#line hidden
#line 328 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Grid DialogOverlay;
#line default
#line hidden
#line 329 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Border DialogCard;
#line default
#line hidden
#line 332 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Media.ScaleTransform DialogScale;
#line default
#line hidden
#line 336 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DialogIcon;
#line default
#line hidden
#line 339 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DialogTitle;
#line default
#line hidden
#line 342 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.TextBlock DialogText;
#line default
#line hidden
#line 345 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button DialogSecondary;
#line default
#line hidden
#line 346 "..\..\..\MainWindow.xaml"
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
internal System.Windows.Controls.Button DialogPrimary;
#line default
#line hidden
private bool _contentLoaded;
/// <summary>
/// InitializeComponent
/// </summary>
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater = new System.Uri("/Git-Manager-GUI-Setup;component/mainwindow.xaml", System.UriKind.Relative);
#line 1 "..\..\..\MainWindow.xaml"
System.Windows.Application.LoadComponent(this, resourceLocater);
#line default
#line hidden
}
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "10.0.13.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
this.VersionText = ((System.Windows.Controls.TextBlock)(target));
return;
case 2:
this.Steps = ((System.Windows.Controls.StackPanel)(target));
return;
case 3:
this.Dot0 = ((System.Windows.Controls.Border)(target));
return;
case 4:
this.Num0 = ((System.Windows.Controls.TextBlock)(target));
return;
case 5:
this.Label0 = ((System.Windows.Controls.TextBlock)(target));
return;
case 6:
this.Line0 = ((System.Windows.Controls.Border)(target));
return;
case 7:
this.Dot1 = ((System.Windows.Controls.Border)(target));
return;
case 8:
this.Num1 = ((System.Windows.Controls.TextBlock)(target));
return;
case 9:
this.Label1 = ((System.Windows.Controls.TextBlock)(target));
return;
case 10:
this.Line1 = ((System.Windows.Controls.Border)(target));
return;
case 11:
this.Dot2 = ((System.Windows.Controls.Border)(target));
return;
case 12:
this.Num2 = ((System.Windows.Controls.TextBlock)(target));
return;
case 13:
this.Label2 = ((System.Windows.Controls.TextBlock)(target));
return;
case 14:
this.WindowTitle = ((System.Windows.Controls.TextBlock)(target));
return;
case 15:
#line 172 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.Minimize_Click);
#line default
#line hidden
return;
case 16:
this.CloseButton = ((System.Windows.Controls.Button)(target));
#line 174 "..\..\..\MainWindow.xaml"
this.CloseButton.Click += new System.Windows.RoutedEventHandler(this.Cancel_Click);
#line default
#line hidden
return;
case 17:
this.PageWelcome = ((System.Windows.Controls.StackPanel)(target));
return;
case 18:
this.UpdateHint = ((System.Windows.Controls.Border)(target));
return;
case 19:
this.UpdateHintText = ((System.Windows.Controls.TextBlock)(target));
return;
case 20:
this.RunningHint = ((System.Windows.Controls.Border)(target));
return;
case 21:
this.PageOptions = ((System.Windows.Controls.StackPanel)(target));
return;
case 22:
#line 257 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).Click += new System.Windows.RoutedEventHandler(this.ChangeDir_Click);
#line default
#line hidden
return;
case 23:
this.DirBox = ((System.Windows.Controls.TextBox)(target));
return;
case 24:
this.DesktopLinkBox = ((System.Windows.Controls.CheckBox)(target));
return;
case 25:
this.PageProgress = ((System.Windows.Controls.StackPanel)(target));
return;
case 26:
this.SuccessIcon = ((System.Windows.Controls.Border)(target));
return;
case 27:
this.SuccessScale = ((System.Windows.Media.ScaleTransform)(target));
return;
case 28:
this.ProgressTitle = ((System.Windows.Controls.TextBlock)(target));
return;
case 29:
this.ProgressBarPanel = ((System.Windows.Controls.StackPanel)(target));
return;
case 30:
this.PercentText = ((System.Windows.Controls.TextBlock)(target));
return;
case 31:
this.ProgressTrack = ((System.Windows.Controls.Border)(target));
#line 286 "..\..\..\MainWindow.xaml"
this.ProgressTrack.SizeChanged += new System.Windows.SizeChangedEventHandler(this.ProgressTrack_SizeChanged);
#line default
#line hidden
return;
case 32:
this.ProgressFill = ((System.Windows.Controls.Border)(target));
return;
case 33:
this.ProgressText = ((System.Windows.Controls.TextBlock)(target));
return;
case 34:
this.DonePanel = ((System.Windows.Controls.StackPanel)(target));
return;
case 35:
this.LaunchBox = ((System.Windows.Controls.CheckBox)(target));
return;
case 36:
this.PageUninstall = ((System.Windows.Controls.StackPanel)(target));
return;
case 37:
this.DataInfo = ((System.Windows.Controls.TextBlock)(target));
return;
case 38:
this.RemoveDataBox = ((System.Windows.Controls.CheckBox)(target));
#line 311 "..\..\..\MainWindow.xaml"
this.RemoveDataBox.Checked += new System.Windows.RoutedEventHandler(this.RemoveDataBox_Click);
#line default
#line hidden
#line 311 "..\..\..\MainWindow.xaml"
this.RemoveDataBox.Unchecked += new System.Windows.RoutedEventHandler(this.RemoveDataBox_Click);
#line default
#line hidden
return;
case 39:
this.RemoveDataWarning = ((System.Windows.Controls.TextBlock)(target));
return;
case 40:
this.BackButton = ((System.Windows.Controls.Button)(target));
#line 322 "..\..\..\MainWindow.xaml"
this.BackButton.Click += new System.Windows.RoutedEventHandler(this.Back_Click);
#line default
#line hidden
return;
case 41:
this.NextButton = ((System.Windows.Controls.Button)(target));
#line 323 "..\..\..\MainWindow.xaml"
this.NextButton.Click += new System.Windows.RoutedEventHandler(this.Next_Click);
#line default
#line hidden
return;
case 42:
this.CancelButton = ((System.Windows.Controls.Button)(target));
#line 324 "..\..\..\MainWindow.xaml"
this.CancelButton.Click += new System.Windows.RoutedEventHandler(this.Cancel_Click);
#line default
#line hidden
return;
case 43:
this.DialogOverlay = ((System.Windows.Controls.Grid)(target));
return;
case 44:
this.DialogCard = ((System.Windows.Controls.Border)(target));
return;
case 45:
this.DialogScale = ((System.Windows.Media.ScaleTransform)(target));
return;
case 46:
this.DialogIcon = ((System.Windows.Controls.TextBlock)(target));
return;
case 47:
this.DialogTitle = ((System.Windows.Controls.TextBlock)(target));
return;
case 48:
this.DialogText = ((System.Windows.Controls.TextBlock)(target));
return;
case 49:
this.DialogSecondary = ((System.Windows.Controls.Button)(target));
#line 345 "..\..\..\MainWindow.xaml"
this.DialogSecondary.Click += new System.Windows.RoutedEventHandler(this.DialogSecondary_Click);
#line default
#line hidden
return;
case 50:
this.DialogPrimary = ((System.Windows.Controls.Button)(target));
#line 346 "..\..\..\MainWindow.xaml"
this.DialogPrimary.Click += new System.Windows.RoutedEventHandler(this.DialogPrimary_Click);
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
+471
View File
@@ -0,0 +1,471 @@
{
"version": 3,
"targets": {
".NETFramework,Version=v4.8": {
"Microsoft.NETFramework.ReferenceAssemblies/1.0.3": {
"type": "package",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies.net48": "1.0.3"
}
},
"Microsoft.NETFramework.ReferenceAssemblies.net48/1.0.3": {
"type": "package",
"build": {
"build/Microsoft.NETFramework.ReferenceAssemblies.net48.targets": {}
}
}
}
},
"libraries": {
"Microsoft.NETFramework.ReferenceAssemblies/1.0.3": {
"sha512": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==",
"type": "package",
"path": "microsoft.netframework.referenceassemblies/1.0.3",
"files": [
".nupkg.metadata",
".signature.p7s",
"microsoft.netframework.referenceassemblies.1.0.3.nupkg.sha512",
"microsoft.netframework.referenceassemblies.nuspec"
]
},
"Microsoft.NETFramework.ReferenceAssemblies.net48/1.0.3": {
"sha512": "zMk4D+9zyiEWByyQ7oPImPN/Jhpj166Ky0Nlla4eXlNL8hI/BtSJsgR8Inldd4NNpIAH3oh8yym0W2DrhXdSLQ==",
"type": "package",
"path": "microsoft.netframework.referenceassemblies.net48/1.0.3",
"files": [
".nupkg.metadata",
".signature.p7s",
"build/.NETFramework/v4.8/Accessibility.dll",
"build/.NETFramework/v4.8/Accessibility.xml",
"build/.NETFramework/v4.8/CustomMarshalers.dll",
"build/.NETFramework/v4.8/CustomMarshalers.xml",
"build/.NETFramework/v4.8/Facades/Microsoft.Win32.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.AppContext.dll",
"build/.NETFramework/v4.8/Facades/System.Collections.Concurrent.dll",
"build/.NETFramework/v4.8/Facades/System.Collections.NonGeneric.dll",
"build/.NETFramework/v4.8/Facades/System.Collections.Specialized.dll",
"build/.NETFramework/v4.8/Facades/System.Collections.dll",
"build/.NETFramework/v4.8/Facades/System.ComponentModel.Annotations.dll",
"build/.NETFramework/v4.8/Facades/System.ComponentModel.EventBasedAsync.dll",
"build/.NETFramework/v4.8/Facades/System.ComponentModel.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.ComponentModel.TypeConverter.dll",
"build/.NETFramework/v4.8/Facades/System.ComponentModel.dll",
"build/.NETFramework/v4.8/Facades/System.Console.dll",
"build/.NETFramework/v4.8/Facades/System.Data.Common.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.Contracts.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.Debug.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.FileVersionInfo.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.Process.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.StackTrace.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.TextWriterTraceListener.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.Tools.dll",
"build/.NETFramework/v4.8/Facades/System.Diagnostics.TraceSource.dll",
"build/.NETFramework/v4.8/Facades/System.Drawing.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.Dynamic.Runtime.dll",
"build/.NETFramework/v4.8/Facades/System.Globalization.Calendars.dll",
"build/.NETFramework/v4.8/Facades/System.Globalization.Extensions.dll",
"build/.NETFramework/v4.8/Facades/System.Globalization.dll",
"build/.NETFramework/v4.8/Facades/System.IO.Compression.ZipFile.dll",
"build/.NETFramework/v4.8/Facades/System.IO.FileSystem.DriveInfo.dll",
"build/.NETFramework/v4.8/Facades/System.IO.FileSystem.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.IO.FileSystem.Watcher.dll",
"build/.NETFramework/v4.8/Facades/System.IO.FileSystem.dll",
"build/.NETFramework/v4.8/Facades/System.IO.IsolatedStorage.dll",
"build/.NETFramework/v4.8/Facades/System.IO.MemoryMappedFiles.dll",
"build/.NETFramework/v4.8/Facades/System.IO.Pipes.dll",
"build/.NETFramework/v4.8/Facades/System.IO.UnmanagedMemoryStream.dll",
"build/.NETFramework/v4.8/Facades/System.IO.dll",
"build/.NETFramework/v4.8/Facades/System.Linq.Expressions.dll",
"build/.NETFramework/v4.8/Facades/System.Linq.Parallel.dll",
"build/.NETFramework/v4.8/Facades/System.Linq.Queryable.dll",
"build/.NETFramework/v4.8/Facades/System.Linq.dll",
"build/.NETFramework/v4.8/Facades/System.Net.Http.Rtc.dll",
"build/.NETFramework/v4.8/Facades/System.Net.NameResolution.dll",
"build/.NETFramework/v4.8/Facades/System.Net.NetworkInformation.dll",
"build/.NETFramework/v4.8/Facades/System.Net.Ping.dll",
"build/.NETFramework/v4.8/Facades/System.Net.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.Net.Requests.dll",
"build/.NETFramework/v4.8/Facades/System.Net.Security.dll",
"build/.NETFramework/v4.8/Facades/System.Net.Sockets.dll",
"build/.NETFramework/v4.8/Facades/System.Net.WebHeaderCollection.dll",
"build/.NETFramework/v4.8/Facades/System.Net.WebSockets.Client.dll",
"build/.NETFramework/v4.8/Facades/System.Net.WebSockets.dll",
"build/.NETFramework/v4.8/Facades/System.ObjectModel.dll",
"build/.NETFramework/v4.8/Facades/System.Reflection.Emit.ILGeneration.dll",
"build/.NETFramework/v4.8/Facades/System.Reflection.Emit.Lightweight.dll",
"build/.NETFramework/v4.8/Facades/System.Reflection.Emit.dll",
"build/.NETFramework/v4.8/Facades/System.Reflection.Extensions.dll",
"build/.NETFramework/v4.8/Facades/System.Reflection.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.Reflection.dll",
"build/.NETFramework/v4.8/Facades/System.Resources.Reader.dll",
"build/.NETFramework/v4.8/Facades/System.Resources.ResourceManager.dll",
"build/.NETFramework/v4.8/Facades/System.Resources.Writer.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.CompilerServices.VisualC.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.Extensions.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.Handles.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.InteropServices.RuntimeInformation.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.InteropServices.WindowsRuntime.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.InteropServices.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.Numerics.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Formatters.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Json.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.Serialization.Xml.dll",
"build/.NETFramework/v4.8/Facades/System.Runtime.dll",
"build/.NETFramework/v4.8/Facades/System.Security.Claims.dll",
"build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Algorithms.dll",
"build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Csp.dll",
"build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Encoding.dll",
"build/.NETFramework/v4.8/Facades/System.Security.Cryptography.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.Security.Cryptography.X509Certificates.dll",
"build/.NETFramework/v4.8/Facades/System.Security.Principal.dll",
"build/.NETFramework/v4.8/Facades/System.Security.SecureString.dll",
"build/.NETFramework/v4.8/Facades/System.ServiceModel.Duplex.dll",
"build/.NETFramework/v4.8/Facades/System.ServiceModel.Http.dll",
"build/.NETFramework/v4.8/Facades/System.ServiceModel.NetTcp.dll",
"build/.NETFramework/v4.8/Facades/System.ServiceModel.Primitives.dll",
"build/.NETFramework/v4.8/Facades/System.ServiceModel.Security.dll",
"build/.NETFramework/v4.8/Facades/System.Text.Encoding.Extensions.dll",
"build/.NETFramework/v4.8/Facades/System.Text.Encoding.dll",
"build/.NETFramework/v4.8/Facades/System.Text.RegularExpressions.dll",
"build/.NETFramework/v4.8/Facades/System.Threading.Overlapped.dll",
"build/.NETFramework/v4.8/Facades/System.Threading.Tasks.Parallel.dll",
"build/.NETFramework/v4.8/Facades/System.Threading.Tasks.dll",
"build/.NETFramework/v4.8/Facades/System.Threading.Thread.dll",
"build/.NETFramework/v4.8/Facades/System.Threading.ThreadPool.dll",
"build/.NETFramework/v4.8/Facades/System.Threading.Timer.dll",
"build/.NETFramework/v4.8/Facades/System.Threading.dll",
"build/.NETFramework/v4.8/Facades/System.ValueTuple.dll",
"build/.NETFramework/v4.8/Facades/System.Xml.ReaderWriter.dll",
"build/.NETFramework/v4.8/Facades/System.Xml.XDocument.dll",
"build/.NETFramework/v4.8/Facades/System.Xml.XPath.XDocument.dll",
"build/.NETFramework/v4.8/Facades/System.Xml.XPath.dll",
"build/.NETFramework/v4.8/Facades/System.Xml.XmlDocument.dll",
"build/.NETFramework/v4.8/Facades/System.Xml.XmlSerializer.dll",
"build/.NETFramework/v4.8/Facades/netstandard.dll",
"build/.NETFramework/v4.8/ISymWrapper.dll",
"build/.NETFramework/v4.8/ISymWrapper.xml",
"build/.NETFramework/v4.8/Microsoft.Activities.Build.dll",
"build/.NETFramework/v4.8/Microsoft.Activities.Build.xml",
"build/.NETFramework/v4.8/Microsoft.Build.Conversion.v4.0.dll",
"build/.NETFramework/v4.8/Microsoft.Build.Conversion.v4.0.xml",
"build/.NETFramework/v4.8/Microsoft.Build.Engine.dll",
"build/.NETFramework/v4.8/Microsoft.Build.Engine.xml",
"build/.NETFramework/v4.8/Microsoft.Build.Framework.dll",
"build/.NETFramework/v4.8/Microsoft.Build.Framework.xml",
"build/.NETFramework/v4.8/Microsoft.Build.Tasks.v4.0.dll",
"build/.NETFramework/v4.8/Microsoft.Build.Tasks.v4.0.xml",
"build/.NETFramework/v4.8/Microsoft.Build.Utilities.v4.0.dll",
"build/.NETFramework/v4.8/Microsoft.Build.Utilities.v4.0.xml",
"build/.NETFramework/v4.8/Microsoft.Build.dll",
"build/.NETFramework/v4.8/Microsoft.Build.xml",
"build/.NETFramework/v4.8/Microsoft.CSharp.dll",
"build/.NETFramework/v4.8/Microsoft.CSharp.xml",
"build/.NETFramework/v4.8/Microsoft.JScript.dll",
"build/.NETFramework/v4.8/Microsoft.JScript.xml",
"build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.Data.dll",
"build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.Data.xml",
"build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.dll",
"build/.NETFramework/v4.8/Microsoft.VisualBasic.Compatibility.xml",
"build/.NETFramework/v4.8/Microsoft.VisualBasic.dll",
"build/.NETFramework/v4.8/Microsoft.VisualBasic.xml",
"build/.NETFramework/v4.8/Microsoft.VisualC.STLCLR.dll",
"build/.NETFramework/v4.8/Microsoft.VisualC.STLCLR.xml",
"build/.NETFramework/v4.8/Microsoft.VisualC.dll",
"build/.NETFramework/v4.8/Microsoft.VisualC.xml",
"build/.NETFramework/v4.8/PermissionSets/FullTrust.xml",
"build/.NETFramework/v4.8/PermissionSets/Internet.xml",
"build/.NETFramework/v4.8/PermissionSets/LocalIntranet.xml",
"build/.NETFramework/v4.8/PresentationBuildTasks.dll",
"build/.NETFramework/v4.8/PresentationBuildTasks.xml",
"build/.NETFramework/v4.8/PresentationCore.dll",
"build/.NETFramework/v4.8/PresentationCore.xml",
"build/.NETFramework/v4.8/PresentationFramework.Aero.dll",
"build/.NETFramework/v4.8/PresentationFramework.Aero.xml",
"build/.NETFramework/v4.8/PresentationFramework.Aero2.dll",
"build/.NETFramework/v4.8/PresentationFramework.Aero2.xml",
"build/.NETFramework/v4.8/PresentationFramework.AeroLite.dll",
"build/.NETFramework/v4.8/PresentationFramework.AeroLite.xml",
"build/.NETFramework/v4.8/PresentationFramework.Classic.dll",
"build/.NETFramework/v4.8/PresentationFramework.Classic.xml",
"build/.NETFramework/v4.8/PresentationFramework.Luna.dll",
"build/.NETFramework/v4.8/PresentationFramework.Luna.xml",
"build/.NETFramework/v4.8/PresentationFramework.Royale.dll",
"build/.NETFramework/v4.8/PresentationFramework.Royale.xml",
"build/.NETFramework/v4.8/PresentationFramework.dll",
"build/.NETFramework/v4.8/PresentationFramework.xml",
"build/.NETFramework/v4.8/ReachFramework.dll",
"build/.NETFramework/v4.8/ReachFramework.xml",
"build/.NETFramework/v4.8/RedistList/FrameworkList.xml",
"build/.NETFramework/v4.8/System.Activities.Core.Presentation.dll",
"build/.NETFramework/v4.8/System.Activities.Core.Presentation.xml",
"build/.NETFramework/v4.8/System.Activities.DurableInstancing.dll",
"build/.NETFramework/v4.8/System.Activities.DurableInstancing.xml",
"build/.NETFramework/v4.8/System.Activities.Presentation.dll",
"build/.NETFramework/v4.8/System.Activities.Presentation.xml",
"build/.NETFramework/v4.8/System.Activities.dll",
"build/.NETFramework/v4.8/System.Activities.xml",
"build/.NETFramework/v4.8/System.AddIn.Contract.dll",
"build/.NETFramework/v4.8/System.AddIn.Contract.xml",
"build/.NETFramework/v4.8/System.AddIn.dll",
"build/.NETFramework/v4.8/System.AddIn.xml",
"build/.NETFramework/v4.8/System.ComponentModel.Composition.Registration.dll",
"build/.NETFramework/v4.8/System.ComponentModel.Composition.Registration.xml",
"build/.NETFramework/v4.8/System.ComponentModel.Composition.dll",
"build/.NETFramework/v4.8/System.ComponentModel.Composition.xml",
"build/.NETFramework/v4.8/System.ComponentModel.DataAnnotations.dll",
"build/.NETFramework/v4.8/System.ComponentModel.DataAnnotations.xml",
"build/.NETFramework/v4.8/System.Configuration.Install.dll",
"build/.NETFramework/v4.8/System.Configuration.Install.xml",
"build/.NETFramework/v4.8/System.Configuration.dll",
"build/.NETFramework/v4.8/System.Configuration.xml",
"build/.NETFramework/v4.8/System.Core.dll",
"build/.NETFramework/v4.8/System.Core.xml",
"build/.NETFramework/v4.8/System.Data.DataSetExtensions.dll",
"build/.NETFramework/v4.8/System.Data.DataSetExtensions.xml",
"build/.NETFramework/v4.8/System.Data.Entity.Design.dll",
"build/.NETFramework/v4.8/System.Data.Entity.Design.xml",
"build/.NETFramework/v4.8/System.Data.Entity.dll",
"build/.NETFramework/v4.8/System.Data.Entity.xml",
"build/.NETFramework/v4.8/System.Data.Linq.dll",
"build/.NETFramework/v4.8/System.Data.Linq.xml",
"build/.NETFramework/v4.8/System.Data.OracleClient.dll",
"build/.NETFramework/v4.8/System.Data.OracleClient.xml",
"build/.NETFramework/v4.8/System.Data.Services.Client.dll",
"build/.NETFramework/v4.8/System.Data.Services.Client.xml",
"build/.NETFramework/v4.8/System.Data.Services.Design.dll",
"build/.NETFramework/v4.8/System.Data.Services.Design.xml",
"build/.NETFramework/v4.8/System.Data.Services.dll",
"build/.NETFramework/v4.8/System.Data.Services.xml",
"build/.NETFramework/v4.8/System.Data.SqlXml.dll",
"build/.NETFramework/v4.8/System.Data.SqlXml.xml",
"build/.NETFramework/v4.8/System.Data.dll",
"build/.NETFramework/v4.8/System.Data.xml",
"build/.NETFramework/v4.8/System.Deployment.dll",
"build/.NETFramework/v4.8/System.Deployment.xml",
"build/.NETFramework/v4.8/System.Design.dll",
"build/.NETFramework/v4.8/System.Design.xml",
"build/.NETFramework/v4.8/System.Device.dll",
"build/.NETFramework/v4.8/System.Device.xml",
"build/.NETFramework/v4.8/System.Diagnostics.Tracing.dll",
"build/.NETFramework/v4.8/System.Diagnostics.Tracing.xml",
"build/.NETFramework/v4.8/System.DirectoryServices.AccountManagement.dll",
"build/.NETFramework/v4.8/System.DirectoryServices.AccountManagement.xml",
"build/.NETFramework/v4.8/System.DirectoryServices.Protocols.dll",
"build/.NETFramework/v4.8/System.DirectoryServices.Protocols.xml",
"build/.NETFramework/v4.8/System.DirectoryServices.dll",
"build/.NETFramework/v4.8/System.DirectoryServices.xml",
"build/.NETFramework/v4.8/System.Drawing.Design.dll",
"build/.NETFramework/v4.8/System.Drawing.Design.xml",
"build/.NETFramework/v4.8/System.Drawing.dll",
"build/.NETFramework/v4.8/System.Drawing.xml",
"build/.NETFramework/v4.8/System.Dynamic.dll",
"build/.NETFramework/v4.8/System.EnterpriseServices.Thunk.dll",
"build/.NETFramework/v4.8/System.EnterpriseServices.Wrapper.dll",
"build/.NETFramework/v4.8/System.EnterpriseServices.dll",
"build/.NETFramework/v4.8/System.EnterpriseServices.xml",
"build/.NETFramework/v4.8/System.IO.Compression.FileSystem.dll",
"build/.NETFramework/v4.8/System.IO.Compression.FileSystem.xml",
"build/.NETFramework/v4.8/System.IO.Compression.dll",
"build/.NETFramework/v4.8/System.IO.Compression.xml",
"build/.NETFramework/v4.8/System.IO.Log.dll",
"build/.NETFramework/v4.8/System.IO.Log.xml",
"build/.NETFramework/v4.8/System.IdentityModel.Selectors.dll",
"build/.NETFramework/v4.8/System.IdentityModel.Selectors.xml",
"build/.NETFramework/v4.8/System.IdentityModel.Services.dll",
"build/.NETFramework/v4.8/System.IdentityModel.Services.xml",
"build/.NETFramework/v4.8/System.IdentityModel.dll",
"build/.NETFramework/v4.8/System.IdentityModel.xml",
"build/.NETFramework/v4.8/System.Linq.xml",
"build/.NETFramework/v4.8/System.Management.Instrumentation.dll",
"build/.NETFramework/v4.8/System.Management.Instrumentation.xml",
"build/.NETFramework/v4.8/System.Management.dll",
"build/.NETFramework/v4.8/System.Management.xml",
"build/.NETFramework/v4.8/System.Messaging.dll",
"build/.NETFramework/v4.8/System.Messaging.xml",
"build/.NETFramework/v4.8/System.Net.Http.WebRequest.dll",
"build/.NETFramework/v4.8/System.Net.Http.WebRequest.xml",
"build/.NETFramework/v4.8/System.Net.Http.dll",
"build/.NETFramework/v4.8/System.Net.Http.xml",
"build/.NETFramework/v4.8/System.Net.dll",
"build/.NETFramework/v4.8/System.Net.xml",
"build/.NETFramework/v4.8/System.Numerics.dll",
"build/.NETFramework/v4.8/System.Numerics.xml",
"build/.NETFramework/v4.8/System.Printing.dll",
"build/.NETFramework/v4.8/System.Printing.xml",
"build/.NETFramework/v4.8/System.Reflection.Context.dll",
"build/.NETFramework/v4.8/System.Reflection.Context.xml",
"build/.NETFramework/v4.8/System.Runtime.Caching.dll",
"build/.NETFramework/v4.8/System.Runtime.Caching.xml",
"build/.NETFramework/v4.8/System.Runtime.DurableInstancing.dll",
"build/.NETFramework/v4.8/System.Runtime.DurableInstancing.xml",
"build/.NETFramework/v4.8/System.Runtime.Remoting.dll",
"build/.NETFramework/v4.8/System.Runtime.Remoting.xml",
"build/.NETFramework/v4.8/System.Runtime.Serialization.Formatters.Soap.dll",
"build/.NETFramework/v4.8/System.Runtime.Serialization.Formatters.Soap.xml",
"build/.NETFramework/v4.8/System.Runtime.Serialization.dll",
"build/.NETFramework/v4.8/System.Runtime.Serialization.xml",
"build/.NETFramework/v4.8/System.Security.dll",
"build/.NETFramework/v4.8/System.Security.xml",
"build/.NETFramework/v4.8/System.ServiceModel.Activation.dll",
"build/.NETFramework/v4.8/System.ServiceModel.Activation.xml",
"build/.NETFramework/v4.8/System.ServiceModel.Activities.dll",
"build/.NETFramework/v4.8/System.ServiceModel.Activities.xml",
"build/.NETFramework/v4.8/System.ServiceModel.Channels.dll",
"build/.NETFramework/v4.8/System.ServiceModel.Channels.xml",
"build/.NETFramework/v4.8/System.ServiceModel.Discovery.dll",
"build/.NETFramework/v4.8/System.ServiceModel.Discovery.xml",
"build/.NETFramework/v4.8/System.ServiceModel.Routing.dll",
"build/.NETFramework/v4.8/System.ServiceModel.Routing.xml",
"build/.NETFramework/v4.8/System.ServiceModel.Web.dll",
"build/.NETFramework/v4.8/System.ServiceModel.Web.xml",
"build/.NETFramework/v4.8/System.ServiceModel.dll",
"build/.NETFramework/v4.8/System.ServiceModel.xml",
"build/.NETFramework/v4.8/System.ServiceProcess.dll",
"build/.NETFramework/v4.8/System.ServiceProcess.xml",
"build/.NETFramework/v4.8/System.Speech.dll",
"build/.NETFramework/v4.8/System.Speech.xml",
"build/.NETFramework/v4.8/System.Threading.Tasks.Dataflow.xml",
"build/.NETFramework/v4.8/System.Transactions.dll",
"build/.NETFramework/v4.8/System.Transactions.xml",
"build/.NETFramework/v4.8/System.Web.Abstractions.dll",
"build/.NETFramework/v4.8/System.Web.ApplicationServices.dll",
"build/.NETFramework/v4.8/System.Web.ApplicationServices.xml",
"build/.NETFramework/v4.8/System.Web.DataVisualization.Design.dll",
"build/.NETFramework/v4.8/System.Web.DataVisualization.dll",
"build/.NETFramework/v4.8/System.Web.DataVisualization.xml",
"build/.NETFramework/v4.8/System.Web.DynamicData.Design.dll",
"build/.NETFramework/v4.8/System.Web.DynamicData.Design.xml",
"build/.NETFramework/v4.8/System.Web.DynamicData.dll",
"build/.NETFramework/v4.8/System.Web.DynamicData.xml",
"build/.NETFramework/v4.8/System.Web.Entity.Design.dll",
"build/.NETFramework/v4.8/System.Web.Entity.Design.xml",
"build/.NETFramework/v4.8/System.Web.Entity.dll",
"build/.NETFramework/v4.8/System.Web.Entity.xml",
"build/.NETFramework/v4.8/System.Web.Extensions.Design.dll",
"build/.NETFramework/v4.8/System.Web.Extensions.Design.xml",
"build/.NETFramework/v4.8/System.Web.Extensions.dll",
"build/.NETFramework/v4.8/System.Web.Extensions.xml",
"build/.NETFramework/v4.8/System.Web.Mobile.dll",
"build/.NETFramework/v4.8/System.Web.Mobile.xml",
"build/.NETFramework/v4.8/System.Web.RegularExpressions.dll",
"build/.NETFramework/v4.8/System.Web.RegularExpressions.xml",
"build/.NETFramework/v4.8/System.Web.Routing.dll",
"build/.NETFramework/v4.8/System.Web.Services.dll",
"build/.NETFramework/v4.8/System.Web.Services.xml",
"build/.NETFramework/v4.8/System.Web.dll",
"build/.NETFramework/v4.8/System.Web.xml",
"build/.NETFramework/v4.8/System.Windows.Controls.Ribbon.dll",
"build/.NETFramework/v4.8/System.Windows.Controls.Ribbon.xml",
"build/.NETFramework/v4.8/System.Windows.Forms.DataVisualization.Design.dll",
"build/.NETFramework/v4.8/System.Windows.Forms.DataVisualization.dll",
"build/.NETFramework/v4.8/System.Windows.Forms.DataVisualization.xml",
"build/.NETFramework/v4.8/System.Windows.Forms.dll",
"build/.NETFramework/v4.8/System.Windows.Forms.xml",
"build/.NETFramework/v4.8/System.Windows.Input.Manipulations.dll",
"build/.NETFramework/v4.8/System.Windows.Input.Manipulations.xml",
"build/.NETFramework/v4.8/System.Windows.Presentation.dll",
"build/.NETFramework/v4.8/System.Windows.Presentation.xml",
"build/.NETFramework/v4.8/System.Windows.dll",
"build/.NETFramework/v4.8/System.Workflow.Activities.dll",
"build/.NETFramework/v4.8/System.Workflow.Activities.xml",
"build/.NETFramework/v4.8/System.Workflow.ComponentModel.dll",
"build/.NETFramework/v4.8/System.Workflow.ComponentModel.xml",
"build/.NETFramework/v4.8/System.Workflow.Runtime.dll",
"build/.NETFramework/v4.8/System.Workflow.Runtime.xml",
"build/.NETFramework/v4.8/System.WorkflowServices.dll",
"build/.NETFramework/v4.8/System.WorkflowServices.xml",
"build/.NETFramework/v4.8/System.Xaml.dll",
"build/.NETFramework/v4.8/System.Xaml.xml",
"build/.NETFramework/v4.8/System.Xml.Linq.dll",
"build/.NETFramework/v4.8/System.Xml.Linq.xml",
"build/.NETFramework/v4.8/System.Xml.Serialization.dll",
"build/.NETFramework/v4.8/System.Xml.dll",
"build/.NETFramework/v4.8/System.Xml.xml",
"build/.NETFramework/v4.8/System.dll",
"build/.NETFramework/v4.8/System.xml",
"build/.NETFramework/v4.8/UIAutomationClient.dll",
"build/.NETFramework/v4.8/UIAutomationClient.xml",
"build/.NETFramework/v4.8/UIAutomationClientsideProviders.dll",
"build/.NETFramework/v4.8/UIAutomationClientsideProviders.xml",
"build/.NETFramework/v4.8/UIAutomationProvider.dll",
"build/.NETFramework/v4.8/UIAutomationProvider.xml",
"build/.NETFramework/v4.8/UIAutomationTypes.dll",
"build/.NETFramework/v4.8/UIAutomationTypes.xml",
"build/.NETFramework/v4.8/WindowsBase.dll",
"build/.NETFramework/v4.8/WindowsBase.xml",
"build/.NETFramework/v4.8/WindowsFormsIntegration.dll",
"build/.NETFramework/v4.8/WindowsFormsIntegration.xml",
"build/.NETFramework/v4.8/XamlBuildTask.dll",
"build/.NETFramework/v4.8/XamlBuildTask.xml",
"build/.NETFramework/v4.8/mscorlib.dll",
"build/.NETFramework/v4.8/mscorlib.xml",
"build/.NETFramework/v4.8/namespaces.xml",
"build/.NETFramework/v4.8/sysglobl.dll",
"build/.NETFramework/v4.8/sysglobl.xml",
"build/Microsoft.NETFramework.ReferenceAssemblies.net48.targets",
"microsoft.netframework.referenceassemblies.net48.1.0.3.nupkg.sha512",
"microsoft.netframework.referenceassemblies.net48.nuspec"
]
}
},
"projectFileDependencyGroups": {
".NETFramework,Version=v4.8": [
"Microsoft.NETFramework.ReferenceAssemblies >= 1.0.3"
]
},
"packageFolders": {
"C:\\Users\\Viper\\.nuget\\packages\\": {}
},
"project": {
"version": "0.0.0",
"restore": {
"projectUniqueName": "C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\GitManagerSetup.csproj",
"projectName": "Git-Manager-GUI-Setup",
"projectPath": "C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\GitManagerSetup.csproj",
"packagesPath": "C:\\Users\\Viper\\.nuget\\packages\\",
"outputPath": "C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\obj\\",
"projectStyle": "PackageReference",
"configFilePaths": [
"C:\\Users\\Viper\\AppData\\Roaming\\NuGet\\NuGet.Config"
],
"originalTargetFrameworks": [
"net48"
],
"sources": {
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net48": {
"targetAlias": "net48",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "direct"
},
"SdkAnalysisLevel": "10.0.100"
},
"frameworks": {
"net48": {
"targetAlias": "net48",
"dependencies": {
"Microsoft.NETFramework.ReferenceAssemblies": {
"suppressParent": "All",
"target": "Package",
"version": "[1.0.3, )",
"autoReferenced": true
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.113\\RuntimeIdentifierGraph.json"
}
}
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"version": 2,
"dgSpecHash": "5on68f3wDDM=",
"success": true,
"projectFilePath": "C:\\Users\\Viper\\Desktop\\git-manager-gui\\installer\\GitManagerSetup.csproj",
"expectedPackageFiles": [
"C:\\Users\\Viper\\.nuget\\packages\\microsoft.netframework.referenceassemblies\\1.0.3\\microsoft.netframework.referenceassemblies.1.0.3.nupkg.sha512",
"C:\\Users\\Viper\\.nuget\\packages\\microsoft.netframework.referenceassemblies.net48\\1.0.3\\microsoft.netframework.referenceassemblies.net48.1.0.3.nupkg.sha512"
],
"logs": []
}
+7 -7
View File
@@ -490,13 +490,13 @@
<!-- Features -->
<section class="section" id="features">
<h2 class="section-title">Warum Git Manager Pro?</h2>
<p class="section-desc">Alles was du brauchst um deine Repositories effizient zu verwalten.</p>
<p class="section-desc">Alles, was du brauchst, um deine Repositories effizient zu verwalten.</p>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">🌐</div>
<h3>Gitea & GitHub</h3>
<p>Unterstützt beide Plattformen seamless — alle Repositories an einem Ort.</p>
<p>Unterstützt beide Plattformen nahtlos — alle Repositories an einem Ort.</p>
</div>
<div class="feature-card">
<div class="feature-icon">📂</div>
@@ -535,16 +535,16 @@
</div>
<div class="feature-card">
<div class="feature-icon">📥</div>
<h3>Ein-Klick Migration</h3>
<h3>Ein-Klick-Migration</h3>
<p>Migriere Repos zwischen Services — mit kompletter History.</p>
</div>
</div>
<div class="demo-section">
<h3 style="color: var(--accent2); margin-bottom: 16px;">🎥 Demo (baldiger Update)</h3>
<h3 style="color: var(--accent2); margin-bottom: 16px;">🎥 Demo (baldiges Update)</h3>
<div class="demo-mockup">
Screenshot-Bereich — Demo und UI-Preview kommen bald!<br><br>
<em>Starte die App mit npm start um einen Live-Demo zu sehen</em>
Screenshot-Bereich — Demo und UI-Vorschau kommen bald!<br><br>
<em>Starte die App mit npm start, um eine Live-Demo zu sehen</em>
</div>
</div>
</section>
@@ -603,7 +603,7 @@
<div class="links-section">
<div class="link-card">
<h3>📖 Benutzerhandbuch</h3>
<p>Vollständiges Handbuch mit Screenshots und Schritt-für-Schritt Anleitungen.</p>
<p>Vollständiges Handbuch mit Screenshots und Schritt-für-Schritt-Anleitungen.</p>
<a href="HANDBUCH.html" target="_blank">Zum Handbuch →</a>
</div>
<div class="link-card">
+1174 -149
View File
File diff suppressed because it is too large Load Diff
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../@electron/asar/bin/asar.js" "$@"
else
exec node "$basedir/../@electron/asar/bin/asar.js" "$@"
fi
Generated Vendored
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@electron\asar\bin\asar.js" %*
Generated Vendored
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../@electron/asar/bin/asar.js" $args
} else {
& "$basedir/node$exe" "$basedir/../@electron/asar/bin/asar.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../@electron/asar/bin/asar.js" $args
} else {
& "node$exe" "$basedir/../@electron/asar/bin/asar.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../crc-32/bin/crc32.njs" "$@"
else
exec node "$basedir/../crc-32/bin/crc32.njs" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\crc-32\bin\crc32.njs" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
} else {
& "$basedir/node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
} else {
& "node$exe" "$basedir/../crc-32/bin/crc32.njs" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../ejs/bin/cli.js" "$@"
else
exec node "$basedir/../ejs/bin/cli.js" "$@"
fi
Generated Vendored
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\ejs\bin\cli.js" %*
Generated Vendored
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../ejs/bin/cli.js" $args
} else {
& "$basedir/node$exe" "$basedir/../ejs/bin/cli.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../ejs/bin/cli.js" $args
} else {
& "node$exe" "$basedir/../ejs/bin/cli.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
Generated Vendored
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../electron/cli.js" "$@"
else
exec node "$basedir/../electron/cli.js" "$@"
fi
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../electron-builder/cli.js" "$@"
else
exec node "$basedir/../electron-builder/cli.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\electron-builder\cli.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../electron-builder/cli.js" $args
} else {
& "$basedir/node$exe" "$basedir/../electron-builder/cli.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../electron-builder/cli.js" $args
} else {
& "node$exe" "$basedir/../electron-builder/cli.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../@electron/fuses/dist/bin.js" "$@"
else
exec node "$basedir/../@electron/fuses/dist/bin.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@electron\fuses\dist\bin.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../@electron/fuses/dist/bin.js" $args
} else {
& "$basedir/node$exe" "$basedir/../@electron/fuses/dist/bin.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../@electron/fuses/dist/bin.js" $args
} else {
& "node$exe" "$basedir/../@electron/fuses/dist/bin.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../@electron/osx-sign/bin/electron-osx-flat.js" "$@"
else
exec node "$basedir/../@electron/osx-sign/bin/electron-osx-flat.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@electron\osx-sign\bin\electron-osx-flat.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-flat.js" $args
} else {
& "$basedir/node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-flat.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-flat.js" $args
} else {
& "node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-flat.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../@electron/osx-sign/bin/electron-osx-sign.js" "$@"
else
exec node "$basedir/../@electron/osx-sign/bin/electron-osx-sign.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@electron\osx-sign\bin\electron-osx-sign.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-sign.js" $args
} else {
& "$basedir/node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-sign.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-sign.js" $args
} else {
& "node$exe" "$basedir/../@electron/osx-sign/bin/electron-osx-sign.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../@electron/rebuild/lib/cli.js" "$@"
else
exec node "$basedir/../@electron/rebuild/lib/cli.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@electron\rebuild\lib\cli.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../@electron/rebuild/lib/cli.js" $args
} else {
& "$basedir/node$exe" "$basedir/../@electron/rebuild/lib/cli.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../@electron/rebuild/lib/cli.js" $args
} else {
& "node$exe" "$basedir/../@electron/rebuild/lib/cli.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../@electron/windows-sign/bin/electron-windows-sign.js" "$@"
else
exec node "$basedir/../@electron/windows-sign/bin/electron-windows-sign.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\@electron\windows-sign\bin\electron-windows-sign.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../@electron/windows-sign/bin/electron-windows-sign.js" $args
} else {
& "$basedir/node$exe" "$basedir/../@electron/windows-sign/bin/electron-windows-sign.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../@electron/windows-sign/bin/electron-windows-sign.js" $args
} else {
& "node$exe" "$basedir/../@electron/windows-sign/bin/electron-windows-sign.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\electron\cli.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../electron/cli.js" $args
} else {
& "$basedir/node$exe" "$basedir/../electron/cli.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../electron/cli.js" $args
} else {
& "node$exe" "$basedir/../electron/cli.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../electron-builder/install-app-deps.js" "$@"
else
exec node "$basedir/../electron-builder/install-app-deps.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\electron-builder\install-app-deps.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../electron-builder/install-app-deps.js" $args
} else {
& "$basedir/node$exe" "$basedir/../electron-builder/install-app-deps.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../electron-builder/install-app-deps.js" $args
} else {
& "node$exe" "$basedir/../electron-builder/install-app-deps.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret
+16
View File
@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../electron/install.js" "$@"
else
exec node "$basedir/../electron/install.js" "$@"
fi
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\electron\install.js" %*
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../electron/install.js" $args
} else {
& "$basedir/node$exe" "$basedir/../electron/install.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../electron/install.js" $args
} else {
& "node$exe" "$basedir/../electron/install.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

Some files were not shown because too many files have changed in this diff Show More