diff --git a/.github/workflows/cfc.yml b/.github/workflows/cfc.yml index 8c4f1673..b2baeda6 100644 --- a/.github/workflows/cfc.yml +++ b/.github/workflows/cfc.yml @@ -30,20 +30,13 @@ jobs: poetry env use "3.11" poetry install --no-interaction - - name: Restore GPAC Cache - uses: actions/cache/restore@v3 - with: - path: /tmp/gpac - key: ${{ runner.os }}-gpac- - restore-keys: ${{ runner.os }}-gpac- - - - name: Setup MP4Box + - name: Install GPAC run: | + wget -O /tmp/gpac.deb https://download.tsi.telecom-paristech.fr/gpac/new_builds/gpac_latest_head_linux64.deb + sudo apt update + sudo apt install -y /tmp/gpac.deb mkdir -p $HOME/.gpac - mkdir -p $HOME/.local/bin touch $HOME/.gpac/creds.key - cp -r /tmp/gpac/ $HOME/.local/bin - echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Configure GitHub handle run: | diff --git a/.github/workflows/chores.yml b/.github/workflows/chores.yml index 45e6a885..c5769ea0 100644 --- a/.github/workflows/chores.yml +++ b/.github/workflows/chores.yml @@ -6,36 +6,6 @@ on: - cron: "0 0 * * *" jobs: - gpac: - name: Build GPAC - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - repository: gpac/gpac - - - name: Get latest commit - id: get-latest-commit - run: | - echo "latest-commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - - - name: GPAC Cache - id: gpac-cache - uses: actions/cache@v3 - with: - path: /tmp/gpac - key: ${{ runner.os }}-gpac-${{ steps.get-latest-commit.outputs.latest-commit }} - - - name: GPAC Build - if: steps.gpac-cache.outputs.cache-hit != 'true' - run: | - sudo apt-get install -y build-essential pkg-config git zlib1g-dev - ./configure --static-bin - make -j$(nproc) - mkdir -p /tmp/gpac - cp -r bin/gcc/ /tmp/gpac - lfscache: name: Keep LFS Cache Warm runs-on: ubuntu-latest diff --git a/conformance-search/src/components/BoxComponent.tsx b/conformance-search/src/components/BoxComponent.tsx index 00387d99..5d4e3c35 100644 --- a/conformance-search/src/components/BoxComponent.tsx +++ b/conformance-search/src/components/BoxComponent.tsx @@ -92,7 +92,7 @@ export default function BoxComponent({ box }: { box: SearchResultRefined }) return (
0 && "border-l-4 border-yellow-400", box.count === 0 && "border-l-4 !border-red-400 opacity-40" diff --git a/conformance-search/src/components/Drawer.tsx b/conformance-search/src/components/Drawer.tsx index 909bb594..f4e4b84f 100644 --- a/conformance-search/src/components/Drawer.tsx +++ b/conformance-search/src/components/Drawer.tsx @@ -28,7 +28,7 @@ export default function Drawer({ if (hidden) return null; return ( -
+
diff --git a/conformance-search/src/components/FeatureComponent.tsx b/conformance-search/src/components/FeatureComponent.tsx index b4bf28ce..87f24c98 100644 --- a/conformance-search/src/components/FeatureComponent.tsx +++ b/conformance-search/src/components/FeatureComponent.tsx @@ -12,7 +12,7 @@ export default function FeatureComponent({ feature }: { feature: SearchResultRef return (
0 && "border-l-4 border-yellow-400", feature.count === 0 && "border-l-4 border-red-400 opacity-40" diff --git a/conformance-search/src/components/FileComponent.tsx b/conformance-search/src/components/FileComponent.tsx index 3f713105..c8488937 100644 --- a/conformance-search/src/components/FileComponent.tsx +++ b/conformance-search/src/components/FileComponent.tsx @@ -277,7 +277,7 @@ export default function FileComponent({ file }: { file: FileSearchResult }) { > {file.item.published ? "Published" : "Under Consideration"} - {file.matches.slice(0, 8).map((match) => { + {file.matches.slice(0, 4).map((match) => { return ( ); })} - {file.matches.length > 8 && ( + {file.matches.length > 4 && ( - +{file.matches.length - 6} more + +{file.matches.length - 4} more )}
diff --git a/conformance-search/src/components/Input/Dropdown.tsx b/conformance-search/src/components/Input/Dropdown.tsx index 598bb381..ea81e1f4 100644 --- a/conformance-search/src/components/Input/Dropdown.tsx +++ b/conformance-search/src/components/Input/Dropdown.tsx @@ -1,25 +1,25 @@ -import clsx from "clsx"; import Fuse from "fuse.js"; -import { useEffect, useRef, useState } from "react"; +import React, { forwardRef, useEffect, useState } from "react"; import { useEvent, useIntersection } from "react-use"; import { normalizeResultScores } from "@/utils"; import { Chip } from "@/components"; import { FuseSearchWithScore } from "@/types"; -export default function Dropdown({ - query, - fuse, - parseValue, - hidden -}: { - query: string; - fuse: { - fourccs: Fuse; - types: Fuse; - }; - parseValue: (value: string) => Promise; - hidden: boolean; -}) { +function Dropdown( + { + query, + fuse, + parseValue + }: { + query: string; + fuse: { + fourccs: Fuse; + types: Fuse; + }; + parseValue: (value: string) => Promise; + }, + ref: React.ForwardedRef +) { const [activeIndex, setActiveIndex] = useState(-1); const [results, setResults] = useState<{ fourccs: FuseSearchWithScore[]; @@ -30,8 +30,7 @@ export default function Dropdown({ }); // Check if the dropdown is visible - const ref = useRef(null); - const intersection = useIntersection(ref, { + const intersection = useIntersection(ref as React.MutableRefObject, { root: null, rootMargin: "0px", threshold: 0.1 @@ -142,12 +141,7 @@ export default function Dropdown({ return ( ); } + +export default forwardRef(Dropdown); diff --git a/conformance-search/src/components/Input/Input.tsx b/conformance-search/src/components/Input/Input.tsx index 1376ee8b..340295cf 100644 --- a/conformance-search/src/components/Input/Input.tsx +++ b/conformance-search/src/components/Input/Input.tsx @@ -23,13 +23,13 @@ export default function Input({ return ( ) => updateFilter(index, (e.target as HTMLInputElement).value) } placeholder={placeholder} - type="text" + type="search" value={filter.value} /> ); diff --git a/conformance-search/src/components/Input/variants/ContainerInput.tsx b/conformance-search/src/components/Input/variants/ContainerInput.tsx index 7de21c4f..9b1a5b99 100644 --- a/conformance-search/src/components/Input/variants/ContainerInput.tsx +++ b/conformance-search/src/components/Input/variants/ContainerInput.tsx @@ -5,6 +5,7 @@ import { useClickAway } from "react-use"; import Search from "@/lib/search"; import { Chip } from "@/components"; import { Filter } from "@/types"; +import { Popper } from "@mui/material"; import Dropdown from "../Dropdown"; import stripSpecialChars from "../helpers"; @@ -95,14 +96,17 @@ export default function ContainerInput({ updateFuse(search); }, [parsed, search]); + // Focus the input when the parsed value changes + const inputRef = useRef(null); + useEffect(() => { + if (parsed.length > 0) inputRef.current?.focus(); + }, [parsed]); + // Dropdown menu + const dropdownContainerRef = useRef(null); const dropdownRef = useRef(null); const [open, setOpen] = useState(false); - const handleClickOutside = () => { - setOpen(false); - }; - // Capture delete key const onKeyDown = async (e: React.KeyboardEvent) => { if (e.key === "Backspace") { @@ -119,7 +123,15 @@ export default function ContainerInput({ } }; - useClickAway(dropdownRef, handleClickOutside); + useClickAway( + dropdownContainerRef, + (e: MouseEvent) => { + const target = e.target as HTMLElement; + if (dropdownRef.current?.contains(target)) return; + setOpen(false); + }, + ["mouseup"] + ); return (
@@ -159,25 +171,38 @@ export default function ContainerInput({ ))}
-
+
) => - setQuery((e.target as HTMLInputElement).value) - } + ref={inputRef} + autoCapitalize="off" + autoComplete="off" + autoCorrect="off" + className="w-fit bg-transparent focus:outline-none xs:w-full" + onChange={(e: React.ChangeEvent) => { + setQuery((e.target as HTMLInputElement).value); + setOpen(true); + }} onClick={() => setOpen(true)} onKeyDown={onKeyDown} placeholder={placeholder} - type="text" + spellCheck="false" + type="search" value={query} /> {fuse && ( -
diff --git a/conformance-search/src/components/SearchComponent/SearchComponent.tsx b/conformance-search/src/components/SearchComponent/SearchComponent.tsx index f23efae1..e396f380 100644 --- a/conformance-search/src/components/SearchComponent/SearchComponent.tsx +++ b/conformance-search/src/components/SearchComponent/SearchComponent.tsx @@ -16,7 +16,7 @@ export default function SearchComponent({ onResult }: { className?: string; - onResult: (boxes: SearchResult[], features: SearchResult[]) => Promise; + onResult: (boxes: SearchResult[], features: SearchResult[]) => void; }) { const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); @@ -52,7 +52,7 @@ export default function SearchComponent({ // Update URL setQueryParams(query, filters); const { boxes, features } = await search.search(query, filters); - await onResult(boxes, features); + onResult(boxes, features); setLoading(false); }, 250, @@ -63,6 +63,10 @@ export default function SearchComponent({ useEffect(() => { const newState = filters.length > 0 && open; setOpen(newState); + + // If open, disable scroll + if (newState) document.body.style.overflow = "hidden"; + else document.body.style.overflow = "auto"; }, [open, filters]); return ( @@ -82,7 +86,7 @@ export default function SearchComponent({ autoCapitalize="off" autoComplete="off" autoCorrect="off" - className="h-16 min-w-0 grow rounded-md px-5 text-sm focus:outline-none disabled:bg-transparent" + className="h-16 min-w-0 grow rounded-tl-md bg-transparent px-5 text-lg only:rounded-t-md focus:outline-none disabled:bg-gray-100" disabled={!ready} onChange={(e: React.ChangeEvent) => { setQuery((e.target as HTMLInputElement).value); @@ -93,23 +97,20 @@ export default function SearchComponent({ type="text" value={query} /> - + {ready && !loading && (query || filters.length > 0) && ( + + )} + {(!ready || loading) && (
@@ -122,7 +123,7 @@ export default function SearchComponent({ filters.map((filter: Filter, index: number) => (