Skip to content

Commit 485b557

Browse files
committed
[chrome] show trending google searches in urlbar suggestions
1 parent 9dae873 commit 485b557

File tree

1 file changed

+106
-6
lines changed

1 file changed

+106
-6
lines changed

packages/chrome/src/components/UrlInput.tsx

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import iconStar from "@ktibow/iconset-ion/star-outline";
1010
import iconStarFilled from "@ktibow/iconset-ion/star";
1111
import iconSearch from "@ktibow/iconset-ion/search";
1212
import iconForwards from "@ktibow/iconset-ion/arrow-forward";
13+
import iconTrendingUp from "@ktibow/iconset-ion/trending-up";
1314
import { Icon } from "./Icon";
1415
import { OmnibarButton } from "./OmnibarButton";
1516
import { createMenuCustom, setContextMenu } from "./Menu";
@@ -19,6 +20,7 @@ import { SiteInformationPopup } from "./SiteInformationPopup";
1920
import { emToPx, splitUrl } from "../utils";
2021
import { fetchSuggestions, type OmniboxResult } from "./suggestions";
2122
import { BookmarkPopup } from "./BookmarkPopup";
23+
import { bare } from "../IsolatedFrame";
2224

2325
export const focusOmnibox = createDelegate<void>();
2426

@@ -30,7 +32,49 @@ export function trimUrl(v: URL) {
3032
v.search
3133
);
3234
}
35+
export type TrendingQuery = {
36+
title: string;
37+
traffic?: string;
38+
url?: string;
39+
};
40+
41+
let trendingCached: TrendingQuery[] | null = null;
42+
export async function fetchGoogleTrending(geo = "US"): Promise<void> {
43+
try {
44+
if (trendingCached) return;
45+
46+
const res = await bare.fetch(
47+
"https://trends.google.com/_/TrendsUi/data/batchexecute",
48+
{
49+
method: "POST",
50+
body: `f.req=[[["i0OFE","[null, null, \\"${geo}\\", 0, null, 48]"]]]`,
51+
headers: {
52+
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
53+
Referer: "https://trends.google.com/trends/explore",
54+
},
55+
}
56+
);
57+
if (!res.ok) return;
58+
59+
const text = await res.text();
60+
const json = JSON.parse(text.slice(5));
61+
const data = JSON.parse(json[0][2]);
62+
const results: TrendingQuery[] = [];
63+
for (const item of data[1]) {
64+
results.push({
65+
title: item[0],
66+
traffic: item[1],
67+
url: item[2]
68+
? `https://www.google.com/search?q=${encodeURIComponent(item[0])}`
69+
: undefined,
70+
});
71+
}
3372

73+
trendingCached = results;
74+
} catch (err) {
75+
console.error("fetchGoogleTrending failed", err);
76+
}
77+
}
3478
export const UrlInput: Component<
3579
{
3680
tabUrl: URL;
@@ -44,11 +88,13 @@ export const UrlInput: Component<
4488
input: HTMLInputElement;
4589
focusindex: number;
4690
overflowItems: OmniboxResult[];
91+
trending: TrendingQuery[];
4792
}
4893
> = function (cx) {
4994
this.focusindex = 0;
5095
this.overflowItems = [];
5196
this.value = "";
97+
this.trending = [];
5298

5399
cx.mount = () => {
54100
setContextMenu(cx.root, [
@@ -59,6 +105,11 @@ export const UrlInput: Component<
59105
},
60106
},
61107
]);
108+
109+
fetchGoogleTrending();
110+
setTimeout(() => {
111+
fetchGoogleTrending();
112+
}, 1000);
62113
};
63114

64115
focusOmnibox.listen(() => {
@@ -112,6 +163,13 @@ export const UrlInput: Component<
112163
this.input.select();
113164
this.justselected = true;
114165
this.input.scrollLeft = 0;
166+
167+
fetchGoogleTrending().then(() => {
168+
// pick a random 3 from the cache
169+
this.trending = trendingCached!
170+
.sort(() => 0.5 - Math.random())
171+
.slice(0, 3);
172+
});
115173
};
116174

117175
const doSearch = () => {
@@ -199,6 +257,36 @@ export const UrlInput: Component<
199257
</div>
200258
</div>
201259
))}
260+
<div class="spacertext">Trending Searches</div>
261+
{use(this.trending).mapEach((item) => (
262+
<div
263+
class="overflowitem"
264+
on:click={() => {
265+
if (item.url) {
266+
this.active = false;
267+
this.input.blur();
268+
browser.activetab.pushNavigate(new URL(item.url));
269+
} else {
270+
this.value = item.title;
271+
this.focusindex = 0;
272+
}
273+
}}
274+
class:focused={false}
275+
title={item.url || item.title}
276+
>
277+
<div class="result-icon">
278+
<Icon icon={iconTrendingUp}></Icon>
279+
</div>
280+
<div class="result-content">
281+
<span class="description">
282+
{renderResultHighlight(item.title, this.input.value)}
283+
</span>
284+
{item.traffic && (
285+
<span class="url">{item.traffic} searches today</span>
286+
)}
287+
</div>
288+
</div>
289+
))}
202290
</div>
203291
<div class="realbar">
204292
<div class="lefticon">
@@ -245,17 +333,19 @@ export const UrlInput: Component<
245333
on:keydown={(e: KeyboardEvent) => {
246334
if (e.key === "ArrowDown") {
247335
e.preventDefault();
248-
this.focusindex++;
249-
if (this.focusindex > this.overflowItems.length) {
250-
this.focusindex = 0;
336+
let idx = this.focusindex + 1;
337+
if (idx > this.overflowItems.length) {
338+
idx = 0;
251339
}
340+
this.focusindex = idx;
252341
}
253342
if (e.key === "ArrowUp") {
254343
e.preventDefault();
255-
this.focusindex--;
256-
if (this.focusindex < 0) {
257-
this.focusindex = this.overflowItems.length;
344+
let idx = this.focusindex - 1;
345+
if (idx < 0) {
346+
idx = this.overflowItems.length;
258347
}
348+
this.focusindex = idx;
259349
}
260350
if (e.key === "Enter") {
261351
e.preventDefault();
@@ -437,6 +527,16 @@ UrlInput.style = css`
437527
438528
border-bottom: 1px solid var(--fg5);
439529
}
530+
531+
.spacertext {
532+
display: block;
533+
height: 2em;
534+
line-height: 2.5em;
535+
padding-left: 1.5em;
536+
color: var(--fg3);
537+
font-size: 0.9em;
538+
}
539+
440540
.overflowitem {
441541
display: flex;
442542
align-items: center;

0 commit comments

Comments
 (0)