feat:游戏启动自动置顶+聚焦
Some checks failed
Axolotl desktop CI / guardrails (push) Has been cancelled
Axolotl desktop CI / desktop (macos-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (ubuntu-latest) (push) Has been cancelled
Axolotl desktop CI / desktop (windows-latest) (push) Has been cancelled
Axolotl desktop CI / website (push) Has been cancelled
Repository checks / typos (push) Has been cancelled
Repository checks / tombi (push) Has been cancelled
Rust checks / shear (push) Has been cancelled
Sync source to CNB / Sync Git ref (push) Has been cancelled

This commit is contained in:
2026-09-13 13:41:58 +08:00
parent 9b704919cf
commit 567184b061
9 changed files with 68 additions and 1574 deletions

View File

@ -5,8 +5,7 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "pnpm contributors:sync && vue-tsc --noEmit && vite build", "build": "vue-tsc --noEmit && vite build",
"contributors:sync": "node ../../scripts/axolotl/sync-contributors.mjs",
"tsc:check": "vue-tsc --noEmit", "tsc:check": "vue-tsc --noEmit",
"lint": "eslint . && prettier --check .", "lint": "eslint . && prettier --check .",
"fix": "eslint . --fix && prettier --write .", "fix": "eslint . --fix && prettier --write .",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
import contributorsData from './contributors.json' import contributorsData from './contributors.json'
import teamData from './team.json' import teamData from './team.json'
@ -10,7 +11,7 @@ export interface TeamMember {
export interface Contributor { export interface Contributor {
name: string name: string
avatarUrl: string avatar: string
url: string url: string
contributions: number contributions: number
} }
@ -26,4 +27,9 @@ export const teamMembers: (TeamMember & { avatarUrl: string })[] = teamData.map(
avatarUrl: teamAvatarModules[`./avatars/${member.avatar}`], avatarUrl: teamAvatarModules[`./avatars/${member.avatar}`],
})) }))
export const contributors = contributorsData as Contributor[] export const contributors: (Contributor & { avatarUrl: string })[] = (
contributorsData as Contributor[]
).map((contributor) => ({
...contributor,
avatarUrl: teamAvatarModules[`./avatars/${contributor.avatar}`],
}))

View File

@ -26,7 +26,10 @@
"core:window:allow-set-effects", "core:window:allow-set-effects",
"core:window:allow-set-cursor-grab", "core:window:allow-set-cursor-grab",
"core:window:allow-set-cursor-visible", "core:window:allow-set-cursor-visible",
"core:window:allow-start-dragging", "core:window:allow-start-dragging",
"core:window:allow-set-always-on-top",
"core:window:allow-set-focus",
"core:webview:allow-set-webview-zoom" "core:webview:allow-set-webview-zoom"
] ]
} }

View File

@ -354,7 +354,7 @@ unsafe extern "system" fn maximize_if_owned_by_process(
_: windows::Win32::Foundation::LPARAM, _: windows::Win32::Foundation::LPARAM,
) -> windows::core::BOOL { ) -> windows::core::BOOL {
use windows::Win32::UI::WindowsAndMessaging::{ use windows::Win32::UI::WindowsAndMessaging::{
GetWindowThreadProcessId, IsWindowVisible, SW_MAXIMIZE, ShowWindow, GetWindowThreadProcessId, IsWindowVisible, SW_MAXIMIZE, SetForegroundWindow, ShowWindow,
}; };
use windows::core::BOOL; use windows::core::BOOL;
@ -363,6 +363,7 @@ unsafe extern "system" fn maximize_if_owned_by_process(
if window_pid == MAXIMIZE_PROCESS_ID.load(Ordering::Relaxed) if window_pid == MAXIMIZE_PROCESS_ID.load(Ordering::Relaxed)
&& unsafe { IsWindowVisible(hwnd).as_bool() } && unsafe { IsWindowVisible(hwnd).as_bool() }
{ {
let _ = unsafe { SetForegroundWindow(hwnd) };
let _ = unsafe { ShowWindow(hwnd, SW_MAXIMIZE) }; let _ = unsafe { ShowWindow(hwnd, SW_MAXIMIZE) };
MAXIMIZE_WINDOW_FOUND.store(true, Ordering::Relaxed); MAXIMIZE_WINDOW_FOUND.store(true, Ordering::Relaxed);
return BOOL(0); return BOOL(0);

View File

@ -1,114 +0,0 @@
import fs from 'node:fs/promises'
import { existsSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
const REPOSITORY = 'Mystic-Stars/Axolotl'
const PER_PAGE = 100
const MAX_PAGES = 10
const OUTPUT_PATH = fileURLToPath(
new URL('../../apps/app-frontend/src/data/about/contributors.json', import.meta.url),
)
function requestHeaders() {
const headers = {
Accept: 'application/vnd.github+json',
'User-Agent': 'Axolotl-Launcher-Contributors-Sync',
}
const token = process.env.AXOLOTL_GITHUB_TOKEN || process.env.GITHUB_TOKEN
if (token) {
headers.Authorization = `Bearer ${token}`
}
return headers
}
async function fetchPage(page) {
const url = new URL(`https://api.github.com/repos/${REPOSITORY}/contributors`)
url.searchParams.set('per_page', String(PER_PAGE))
url.searchParams.set('page', String(page))
let failure
for (let attempt = 1; attempt <= 3; attempt++) {
try {
const response = await fetch(url, {
headers: requestHeaders(),
signal: AbortSignal.timeout(30_000),
})
if (!response.ok) throw new Error(`HTTP ${response.status}`)
return await response.json()
} catch (error) {
failure = error
if (attempt < 3) await new Promise((resolve) => setTimeout(resolve, attempt * 1_000))
}
}
throw new Error(`Unable to fetch contributors from ${url}`, { cause: failure })
}
function normalizeContributor(contributor) {
if (!contributor || typeof contributor !== 'object' || Array.isArray(contributor))
return undefined
if (typeof contributor.login !== 'string' || !contributor.login) return undefined
if (typeof contributor.html_url !== 'string' || !contributor.html_url) return undefined
if (typeof contributor.avatar_url !== 'string' || !contributor.avatar_url) return undefined
if (!Number.isInteger(contributor.contributions) || contributor.contributions < 1)
return undefined
const avatarUrl = new URL(contributor.avatar_url)
avatarUrl.searchParams.set('s', '96')
return {
name: contributor.login,
avatarUrl: avatarUrl.toString(),
url: contributor.html_url,
contributions: contributor.contributions,
}
}
async function fetchContributors() {
const pages = []
for (let page = 1; page <= MAX_PAGES; page++) {
const contributors = await fetchPage(page)
if (!Array.isArray(contributors)) throw new Error(`Page ${page} did not contain an array`)
pages.push(contributors)
if (contributors.length < PER_PAGE) break
}
const contributors = pages
.flat()
.map(normalizeContributor)
.filter((contributor) => contributor !== undefined)
.sort(
(left, right) =>
right.contributions - left.contributions || left.name.localeCompare(right.name),
)
if (contributors.length === 0)
throw new Error('The contributors response did not contain any people')
return contributors
}
async function main() {
let contributors
try {
contributors = await fetchContributors()
} catch (error) {
if (existsSync(OUTPUT_PATH)) {
console.warn(
`Unable to refresh contributors, keeping the existing snapshot: ${error.message}`,
)
return
}
throw error
}
const nextText = `${JSON.stringify(contributors, null, '\t')}\n`
const currentText = existsSync(OUTPUT_PATH) ? await fs.readFile(OUTPUT_PATH, 'utf8') : ''
if (currentText === nextText) {
console.log(`Contributors are up to date (${contributors.length} people).`)
return
}
await fs.writeFile(OUTPUT_PATH, nextText)
console.log(`Synchronized ${contributors.length} contributors from ${REPOSITORY}.`)
}
await main()

28
tools/icon_work/fix_fg.py Normal file
View File

@ -0,0 +1,28 @@
p = r"D:\Project\Starlight_Lancher\apps\app\src\lightweight_mode.rs"
t = open(p, encoding="utf-8").read()
# 1) import 加 SetForegroundWindow
old_import = """ use windows::Win32::UI::WindowsAndMessaging::{
GetWindowThreadProcessId, IsWindowVisible, SW_MAXIMIZE, ShowWindow,
};"""
new_import = """ use windows::Win32::UI::WindowsAndMessaging::{
GetWindowThreadProcessId, IsWindowVisible, SW_MAXIMIZE, SetForegroundWindow, ShowWindow,
};"""
assert old_import in t, "找不到 import 块"
t = t.replace(old_import, new_import, 1)
# 2) 最大化前先聚焦到前台
old_show = " let _ = unsafe { ShowWindow(hwnd, SW_MAXIMIZE) };"
new_show = (
" let _ = unsafe { SetForegroundWindow(hwnd) };\n"
" let _ = unsafe { ShowWindow(hwnd, SW_MAXIMIZE) };"
)
assert old_show in t, "找不到 ShowWindow 行"
t = t.replace(old_show, new_show, 1)
open(p, "w", encoding="utf-8", newline="\n").write(t)
print("done")
l = t.split("\n")
for i in range(354, 372):
print(f"{i+1}: {l[i]}")

View File

@ -0,0 +1,22 @@
p = r"D:\Project\Starlight_Lancher\apps\app-frontend\package.json"
t = open(p, encoding="utf-8").read()
# 1) build 去掉 contributors:sync
t = t.replace(
'"build": "pnpm contributors:sync && vue-tsc --noEmit && vite build",',
'"build": "vue-tsc --noEmit && vite build",',
)
# 2) 删除 contributors:sync 那一行
t = t.replace(
'\t\t"contributors:sync": "node ../../scripts/axolotl/sync-contributors.mjs",\n',
"",
)
open(p, "w", encoding="utf-8", newline="\n").write(t)
import json
json.load(open(p, encoding="utf-8")) # 校验合法
print("done")
l = t.split("\n")
for i in range(5, 13):
print(f"{i+1}: {l[i]}")