Compare commits

...
Author SHA1 Message Date
tdgao 14cb379f7d feat: add shift click to toggle file selection 2026-07-13 14:33:06 -07:00
Prospector 3ac3b9539d changelog 2026-07-13 12:00:48 -07:00
Robin 73b3871e72 feat: add norisk client source support (#6707)
Signed-off-by: Robin <me@orb1n.dev>
2026-07-13 18:51:07 +00:00
3 changed files with 31 additions and 6 deletions
@@ -657,6 +657,7 @@ static DOWNLOAD_SOURCE_PATTERNS: LazyLock<Vec<(Regex, DownloadSourcePattern)>> =
(r"^mrpack4server", P::Named("mrpack4server")),
(r"^DawnLauncher/", P::Named("Dawn")),
(r"^Complementary-Installer", P::Named("Complementary Installer")),
(r"^noriskclient-launcher-v3/", P::Named("NoRisk Client")),
(
r"^(Mozilla/|Chrome/|Chromium/|Firefox/|Safari/|AppleWebKit/|Edg/|OPR/)",
P::Website,
+6
View File
@@ -10,6 +10,12 @@ export type VersionEntry = {
}
const VERSIONS: VersionEntry[] = [
{
date: `2026-07-13T19:00:42+00:00`,
product: 'web',
body: `## Changed
- Updated translations`,
},
{
date: `2026-07-10T17:38:17+00:00`,
product: 'app',
@@ -65,6 +65,7 @@ const assignableEntries = ref<AssignableFileEntry[]>([])
const searchQuery = ref('')
const searchInputRef = ref<{ focus: () => void } | null>(null)
const selectedSha1s = ref<Set<string>>(new Set())
const selectionAnchorSha1 = ref<string | null>(null)
const filteredEntries = computed(() => {
const q = searchQuery.value.trim().toLowerCase()
@@ -85,18 +86,35 @@ function isFileSelected(sha1: string) {
return selectedSha1s.value.has(sha1)
}
function toggleFileSelection(sha1: string) {
function toggleFileSelection(sha1: string, event: MouseEvent) {
const next = new Set(selectedSha1s.value)
if (next.has(sha1)) {
next.delete(sha1)
} else {
next.add(sha1)
const shouldSelect = !next.has(sha1)
const entryIndex = filteredEntries.value.findIndex((entry) => entry.sha1 === sha1)
const anchorIndex = filteredEntries.value.findIndex(
(entry) => entry.sha1 === selectionAnchorSha1.value,
)
const sha1sToToggle =
event.shiftKey && entryIndex !== -1 && anchorIndex !== -1
? filteredEntries.value
.slice(Math.min(entryIndex, anchorIndex), Math.max(entryIndex, anchorIndex) + 1)
.map((entry) => entry.sha1)
: [sha1]
for (const sha1ToToggle of sha1sToToggle) {
if (shouldSelect) {
next.add(sha1ToToggle)
} else {
next.delete(sha1ToToggle)
}
}
selectedSha1s.value = next
selectionAnchorSha1.value = sha1
}
function clearSelectedFiles() {
selectedSha1s.value = new Set()
selectionAnchorSha1.value = null
}
function focusSearchOnOpen() {
@@ -208,7 +226,7 @@ defineExpose({ show, hide })
class="w-full text-left p-3 flex flex-col gap-1 appearance-none bg-transparent 3 transition-colors disabled:opacity-50"
:disabled="pending"
:aria-pressed="isFileSelected(entry.sha1)"
@click="toggleFileSelection(entry.sha1)"
@click="toggleFileSelection(entry.sha1, $event)"
>
<span class="flex gap-2 font-medium">
<span