Skip to content

Commit

Permalink
fix: reduce flickering when searching for results (#30)
Browse files Browse the repository at this point in the history
* fix: reduce flickering

Related to #25.

Search results flickers because of three things (IMO):

- `handleInput` resets the `results` array, which immediately dropping
  list with `#if` directive in `SearchResult` component
- Changing styles on `focus` and `blur` are not immediate operation, that's why another
  kind of flickering is a transition between focused and non-focused
  state (gray background)
- `getIcon` function is another "bottleneck"; preservation of space for
  upcomming <img> tag is a key for rescue

Most "ugly" part of this code is manipulating with classes. Changing
classes through Svelte's `class:` binding leads to focus lost.

Unfortunately, manipulating classes through script cannot be made with
obfuscated selectors, that's why you can see `:global` in code. Maybe you
know better way to change classes without losing focus.

* fix: span attributes

* fix: remove icon flickering with icons cache

* fix: reset `results` when search pattern is empty

* chore: fix extra rectangular overlay on calculation results

* chore: fix closing window when pressing enter/return

* chore: fix keys not being registered

Co-authored-by: Parth Jadhav <[email protected]>
  • Loading branch information
Ty3uK and ParthJadhav authored Jan 9, 2023
1 parent 8eb8ded commit 19ff234
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 15 deletions.
5 changes: 4 additions & 1 deletion src/cache.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export const preferences = new Map();
export const paths = new Map();
export const paths = new Map();
export const icons = new Map();

export const FALLBACK_ICON_SYMBOL = Symbol();
2 changes: 1 addition & 1 deletion src/routes/App/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
});
const handleInput = async (event: any) => {
results = [];
if (event.target.value === "") {
results = [];
footerText = "verve.app";
return;
}
Expand Down
3 changes: 2 additions & 1 deletion src/routes/App/lib/CalculationResult.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
};
const searchResultClicked = async (event: any) => {
if (event.keyCode !== 13) return;
await copyAnswer();
const searchBarInput = document.getElementById(
"searchBarInput"
Expand All @@ -18,7 +19,7 @@
</script>

<div class="result">
<button class="calculation-button" id={results[0]} on:click={searchResultClicked}>
<button class="calculation-button" id={results[0]} on:keydown={searchResultClicked}>
<p>{results[0]}</p>
</button>
</div>
Expand Down
48 changes: 36 additions & 12 deletions src/routes/App/lib/SearchResult.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,35 @@
import { convertFileSrc } from "@tauri-apps/api/tauri";
import { appWindow, LogicalSize } from "@tauri-apps/api/window";
import { afterUpdate } from "svelte";
import { FALLBACK_ICON_SYMBOL, icons } from "../../../cache";
import CalculationResult from "./CalculationResult.svelte";
afterUpdate(async () => {
const height = document.getElementsByClassName("container")[0].clientHeight;
await appWindow.setSize(new LogicalSize(750, height));
if (results.length > 0 && results[0] !== "") {
const firstResult = document.getElementById(results[0]);
firstResult.classList.add('searchResultFocused');
await firstResult.focus();
}
});
async function getIcon(app_name: string) {
const fallbackIcon = convertFileSrc(
await resolveResource("assets/default.svg")
);
let icon = icons.get(app_name);
let fallbackIcon = icons.get(FALLBACK_ICON_SYMBOL);
if (icon && fallbackIcon) {
return { icon, fallbackIcon };
}
if (!fallbackIcon) {
fallbackIcon = convertFileSrc(
await resolveResource("assets/default.svg")
);
icons.set(FALLBACK_ICON_SYMBOL, fallbackIcon);
}
let iconPath: string;
if (
[
"Migration Assistant",
Expand All @@ -31,14 +45,17 @@
"AirPort Utility",
].includes(app_name)
) {
const icon_path = await resolveResource(
iconPath = await resolveResource(
`assets/appIcons/${app_name}.app.png`
);
return { icon: convertFileSrc(icon_path), fallbackIcon };
} else {
const appDataDirPath = await appDataDir();
iconPath = await join(appDataDirPath, `appIcons/${app_name}.app.png`);
}
const appDataDirPath = await appDataDir();
const filePath = await join(appDataDirPath, `appIcons/${app_name}.app.png`);
return { icon: convertFileSrc(filePath), fallbackIcon };
icon = convertFileSrc(iconPath);
icons.set(app_name, icon);
return { icon, fallbackIcon };
}
async function handleKeydown(event) {
Expand All @@ -58,6 +75,8 @@
else newIndex = (currentIndex + 1) % items.length;
}
if (current !== null && items[newIndex] !== null) {
items[newIndex].classList.add('searchResultFocused');
current.classList.remove('searchResultFocused');
current.blur();
items[newIndex].focus();
}
Expand Down Expand Up @@ -85,7 +104,9 @@
{#await getIcon(result
.split("/")
.pop()
.replace(/.app$/, "")) then { icon, fallbackIcon }}
.replace(/.app$/, ""))}
<span class="appIcon"></span>
{:then {icon, fallbackIcon}}
<img
class="appIcon"
src={icon}
Expand Down Expand Up @@ -123,12 +144,15 @@
order: 1;
flex-grow: 0;
}
.searchResult:focus {
background: var(--highlight-overlay);
outline: 0;
:global(.searchResultFocused) {
background: var(--highlight-overlay) !important;
outline: 0 !important;
border-radius: 8px;
}
.appIcon {
display: inline-flex;
width: 24px;
height: 24px;
margin-right: 8px;
Expand Down

0 comments on commit 19ff234

Please sign in to comment.