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
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:
@ -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 .",
|
||||||
|
|||||||
BIN
apps/app-frontend/src/data/about/avatars/xiao-no-love.png
Normal file
BIN
apps/app-frontend/src/data/about/avatars/xiao-no-love.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
File diff suppressed because it is too large
Load Diff
@ -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}`],
|
||||||
|
}))
|
||||||
|
|||||||
@ -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"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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
28
tools/icon_work/fix_fg.py
Normal 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]}")
|
||||||
22
tools/icon_work/fix_pkg.py
Normal file
22
tools/icon_work/fix_pkg.py
Normal 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]}")
|
||||||
Reference in New Issue
Block a user