Skip to content

Commit

Permalink
Merge pull request #4 from SuboptimalEng/fuzzy-search
Browse files Browse the repository at this point in the history
Add fuzzy search and highlight query in filename.
  • Loading branch information
SuboptimalEng authored Oct 24, 2021
2 parents 3b6c320 + e213f65 commit 89d6d2d
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 9 deletions.
78 changes: 76 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
"dateformat": "^5.0.1",
"electron-is-dev": "^2.0.0",
"electron-store": "^8.0.1",
"fastest-levenshtein": "^1.0.12",
"fluent-ffmpeg": "^2.1.2",
"glob": "^7.2.0",
"hotkeys-js": "^3.8.7",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-highlight-words": "^0.17.0",
"react-infinite-scroll-component": "^6.1.0",
"react-redux": "^7.2.4",
"react-scripts": "4.0.3",
Expand Down Expand Up @@ -86,6 +88,7 @@
"@types/node": "^14.14.33",
"@types/react": "^17.0.21",
"@types/react-dom": "^17.0.9",
"@types/react-highlight-words": "^0.16.3",
"@types/react-redux": "^7.1.18",
"autoprefixer": "^9.8.6",
"concurrently": "^6.2.1",
Expand Down
11 changes: 9 additions & 2 deletions src/renderer/components/Editor/Explorer/ImageCard.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { IFile } from '../../../types';
import { useAppSelector } from '../../../store/hooks';
import Hightlighter from 'react-highlight-words';

export default function ImageCard({ path }: IFile) {
const folder = useAppSelector((state) => state.folder);
const { query } = useAppSelector((state) => state.explorer);

const getReadablePath = (): string => {
return path.substr(folder.path.length);
return path.substr(folder.path.length + 1);
};

return (
Expand All @@ -20,7 +22,12 @@ export default function ImageCard({ path }: IFile) {
</div>

<div className="absolute text-sm px-1 bottom-2 left-0 max-w-full bg-editor-bg text-editor-fg place-items-center">
<div className="truncate">{getReadablePath()}</div>
<div className="truncate">
<Hightlighter
searchWords={[query]}
textToHighlight={getReadablePath()}
/>
</div>
</div>
</div>
);
Expand Down
17 changes: 16 additions & 1 deletion src/renderer/components/Editor/Explorer/MediaGallery.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useState, DragEvent } from 'react';
import InfiniteScroll from 'react-infinite-scroll-component';
import { distance } from 'fastest-levenshtein';

import { IFile } from '../../../types';
import { isVideoFile } from '../../../../common/mediaExtensions';
Expand Down Expand Up @@ -27,7 +28,21 @@ export default function MediaGallery() {
const [infiniteFiles, setInfiniteFiles] = useState<Array<IFile>>([]);

useEffect(() => {
const searchResults = files.filter((file) => file.path.includes(query));
const MAX_DISTANCE = 1;
// NOTE: This method updates the list of files to show in the media gallery.
const searchResults = files.filter((file) => {
// NOTE: The total distance between the query and filename can be very large
// if the query is really short, or the user does not specify anything. To
// adjust for this, we need to calculate another distance based on the query.
const totalDistance = distance(
query.toLowerCase(),
file.name.toLowerCase()
);
const adjustedDistance =
totalDistance - (file.name.length - query.length);
return adjustedDistance <= MAX_DISTANCE;
});

dispatch(setFilteredFiles(searchResults));

const initialFiles: Array<IFile> = [];
Expand Down
13 changes: 11 additions & 2 deletions src/renderer/components/Editor/Explorer/VideoCard.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { MouseEvent, SyntheticEvent, useState } from 'react';
import Hightlighter from 'react-highlight-words';

import { IFile } from '../../../types';
import { useAppSelector } from '../../../store/hooks';

export default function VideoCard({ path }: IFile) {
let videoWidth = 10000;
let boundingClientLeft = 0;

const folder = useAppSelector((state) => state.folder);
const { query } = useAppSelector((state) => state.explorer);

const [duration, setDuration] = useState<number>(0);

const setDurationOnLoad = (e: SyntheticEvent<HTMLVideoElement>) => {
Expand Down Expand Up @@ -46,7 +50,7 @@ export default function VideoCard({ path }: IFile) {
};

const getReadablePath = (): string => {
return path.substr(folder.path.length);
return path.substr(folder.path.length + 1);
};

return (
Expand All @@ -69,7 +73,12 @@ export default function VideoCard({ path }: IFile) {
</div>

<div className="absolute text-sm px-1 bottom-2 left-0 max-w-full bg-editor-bg text-editor-fg place-items-center">
<div className="truncate">{getReadablePath()}</div>
<div className="truncate">
<Hightlighter
searchWords={[query]}
textToHighlight={getReadablePath()}
/>
</div>
</div>
</div>
);
Expand Down
35 changes: 33 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2026,6 +2026,13 @@
dependencies:
"@types/react" "*"

"@types/react-highlight-words@^0.16.3":
"integrity" "sha512-ZarU4+/R593xctDXy/SkyWeS/dg5sG8TxZ2DATd2EdDKHlfqCPnOYzHEo/7XaYpCoSCgk5Sp1sVNhnOzC/ezJg=="
"resolved" "https://registry.npmjs.org/@types/react-highlight-words/-/react-highlight-words-0.16.3.tgz"
"version" "0.16.3"
dependencies:
"@types/react" "*"

"@types/react-redux@^7.1.16", "@types/react-redux@^7.1.18":
"integrity" "sha512-9iwAsPyJ9DLTRH+OFeIrm9cAbIj1i2ANL3sKQFATqnPWRbg+jEFXyZOKHiQK/N86pNRXbb4HRxAxo0SIX1XwzQ=="
"resolved" "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.18.tgz"
Expand Down Expand Up @@ -5796,6 +5803,11 @@
"resolved" "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
"version" "2.0.6"

"fastest-levenshtein@^1.0.12":
"integrity" "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow=="
"resolved" "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz"
"version" "1.0.12"

"fastq@^1.6.0":
"integrity" "sha512-AWuv6Ery3pM+dY7LYS8YIaCiQvUaos9OB1RyNgaOWnaX+Tik7Onvcsf8x8c+YtDeT0maYLniBip2hox5KtEXXA=="
"resolved" "https://registry.npmjs.org/fastq/-/fastq-1.10.1.tgz"
Expand Down Expand Up @@ -6470,6 +6482,11 @@
"resolved" "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz"
"version" "1.1.0"

"highlight-words-core@^1.2.0":
"integrity" "sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg=="
"resolved" "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz"
"version" "1.2.2"

"hmac-drbg@^1.0.1":
"integrity" "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE="
"resolved" "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz"
Expand Down Expand Up @@ -8317,6 +8334,11 @@
"resolved" "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
"version" "0.3.0"

"memoize-one@^4.0.0":
"integrity" "sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw=="
"resolved" "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz"
"version" "4.0.3"

"memory-fs@^0.4.1":
"integrity" "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI="
"resolved" "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz"
Expand Down Expand Up @@ -10210,7 +10232,7 @@
"kleur" "^3.0.3"
"sisteransi" "^1.0.5"

"prop-types@^15.7.2":
"prop-types@^15.5.8", "prop-types@^15.7.2":
"integrity" "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ=="
"resolved" "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz"
"version" "15.7.2"
Expand Down Expand Up @@ -10467,6 +10489,15 @@
"resolved" "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz"
"version" "6.0.9"

"react-highlight-words@^0.17.0":
"integrity" "sha512-uX1Qh5IGjnLuJT0Zok234QDwRC8h4hcVMnB99Cb7aquB1NlPPDiWKm0XpSZOTdSactvnClCk8LOmVlP+75dgHA=="
"resolved" "https://registry.npmjs.org/react-highlight-words/-/react-highlight-words-0.17.0.tgz"
"version" "0.17.0"
dependencies:
"highlight-words-core" "^1.2.0"
"memoize-one" "^4.0.0"
"prop-types" "^15.5.8"

"react-infinite-scroll-component@^6.1.0":
"integrity" "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ=="
"resolved" "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz"
Expand Down Expand Up @@ -10567,7 +10598,7 @@
optionalDependencies:
"fsevents" "^2.1.3"

"react@^17.0.2":
"react@^0.14.0 || ^15.0.0 || ^16.0.0-0 || ^17.0.0-0", "react@^17.0.2":
"integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA=="
"resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz"
"version" "17.0.2"
Expand Down

0 comments on commit 89d6d2d

Please sign in to comment.