Skip to content

Commit fee9760

Browse files
authored
history: initial build (#1401)
1 parent f8cde4a commit fee9760

34 files changed

+1042
-1
lines changed

special-pages/index.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ export const support = {
5757
windows: ['copy', 'build-js'],
5858
apple: ['copy', 'build-js'],
5959
},
60+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
61+
history: {
62+
integration: ['copy', 'build-js'],
63+
windows: ['copy', 'build-js'],
64+
apple: ['copy', 'build-js'],
65+
},
6066
};
6167

6268
/** @type {{src: string, dest: string, dist: string, injectName: string}[]} */
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Fragment, h } from 'preact';
2+
import styles from './App.module.css';
3+
import { useTypedTranslation } from '../types.js';
4+
import { useEnv } from '../../../../shared/components/EnvironmentProvider.js';
5+
import { Header } from './Header.js';
6+
import { useSignal } from '@preact/signals';
7+
import { Results } from './Results.js';
8+
9+
export function App() {
10+
const { t } = useTypedTranslation();
11+
const { isDarkMode } = useEnv();
12+
const results = useSignal({
13+
info: {
14+
finished: true,
15+
term: '',
16+
},
17+
value: [],
18+
});
19+
return (
20+
<div class={styles.layout} data-theme={isDarkMode ? 'dark' : 'light'}>
21+
<header class={styles.header}>
22+
<Header setResults={(next) => (results.value = next)} />
23+
</header>
24+
<aside class={styles.aside}>
25+
<h1 class={styles.pageTitle}>History</h1>
26+
</aside>
27+
<main class={styles.main}>
28+
<Results results={results} />
29+
</main>
30+
</div>
31+
);
32+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
@import url("../../../../shared/styles/variables.css");
2+
@import url("../../styles/base.css");
3+
@import url("../../styles/theme.css");
4+
5+
body {
6+
font-size: var(--body-font-size);
7+
font-weight: var(--body-font-weight);
8+
line-height: var(--body-line-height);
9+
}
10+
11+
.layout {
12+
display: grid;
13+
grid-template-columns: 250px 1fr;
14+
grid-template-rows: 64px auto;
15+
grid-template-areas:
16+
'aside header'
17+
'aside main';
18+
overflow: hidden;
19+
height: 100vh;
20+
}
21+
.header {
22+
grid-area: header;
23+
padding-left: 48px;
24+
padding-right: 76px;
25+
padding-top: 16px;
26+
padding-bottom: 16px;
27+
}
28+
.search {
29+
justify-self: flex-end;
30+
}
31+
.aside {
32+
grid-area: aside;
33+
padding: 10px 16px;
34+
border-right: 1px solid var(--history-surface-border-color);
35+
}
36+
.pageTitle {
37+
font-size: var(--title-font-size);
38+
font-weight: var(--title-font-weight);
39+
line-height: var(--title-line-height);
40+
padding: 10px 6px 10px 10px;
41+
}
42+
.main {
43+
grid-area: main;
44+
overflow: auto;
45+
padding-left: 48px;
46+
padding-right: 76px;
47+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { h } from 'preact';
2+
import styles from './Components.module.css';
3+
4+
export function Components() {
5+
return <main class={styles.main}>Component list here!</main>;
6+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.main {
2+
3+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import styles from './Header.module.css';
2+
import { Fire } from '../icons/Fire.js';
3+
import { h } from 'preact';
4+
import { useMessaging, useTypedTranslation } from '../types.js';
5+
import { Cross } from '../icons/Cross.js';
6+
import { useEffect } from 'preact/hooks';
7+
8+
export function Header({ setResults }) {
9+
const { t } = useTypedTranslation();
10+
const historyPage = useMessaging();
11+
useEffect(() => {
12+
historyPage
13+
.query({ term: '', limit: 150, offset: 0 })
14+
// eslint-disable-next-line promise/prefer-await-to-then
15+
.then(setResults)
16+
// eslint-disable-next-line promise/prefer-await-to-then
17+
.catch((e) => {
18+
console.log('did catch...', e);
19+
});
20+
}, []);
21+
return (
22+
<div class={styles.root}>
23+
<div class={styles.controls}>
24+
<button class={styles.largeButton}>
25+
<Fire />
26+
<span>Clear History and Data...</span>
27+
</button>
28+
<button class={styles.largeButton}>
29+
<Cross />
30+
<span>Remove History...</span>
31+
</button>
32+
</div>
33+
<div class={styles.search}>
34+
<form
35+
action=""
36+
onSubmit={(e) => {
37+
e.preventDefault();
38+
const data = new FormData(/** @type {HTMLFormElement} */ (e.target));
39+
historyPage
40+
.query({ term: data.get('term')?.toString() || '', limit: 150, offset: 0 })
41+
// eslint-disable-next-line promise/prefer-await-to-then
42+
.then(setResults)
43+
// eslint-disable-next-line promise/prefer-await-to-then
44+
.catch((e) => {
45+
console.log('did catch...', e);
46+
});
47+
}}
48+
>
49+
<input type="search" placeholder={t('search')} class={styles.searchInput} name="term" />
50+
</form>
51+
</div>
52+
</div>
53+
);
54+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.root {
2+
display: flex;
3+
align-items: center;
4+
gap: 8px;
5+
}
6+
.controls {
7+
display: flex;
8+
gap: 8px;
9+
}
10+
.largeButton {
11+
background: transparent;
12+
display: flex;
13+
align-items: center;
14+
gap: 4px;
15+
height: 32px;
16+
border: none;
17+
18+
svg {
19+
flex-shrink: 0
20+
}
21+
22+
&:hover {
23+
background-color: var(--history-surface-color)
24+
}
25+
}
26+
.search {
27+
margin-left: auto;
28+
}
29+
.searchInput {
30+
width: 238px;
31+
height: 28px;
32+
border-radius: 6px;
33+
border: 1px solid var(--history-surface-border-color);
34+
padding-left: 9px;
35+
padding-right: 9px;
36+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { h } from 'preact';
2+
3+
/**
4+
* @param {object} props
5+
* @param {import("@preact/signals").Signal<import('../../types/history').HistoryQueryResponse>} props.results
6+
*/
7+
export function Results({ results }) {
8+
return (
9+
<div>
10+
<p>Params:</p>
11+
<pre>
12+
<code>{JSON.stringify(results.value.info)}</code>
13+
</pre>
14+
<br />
15+
<hr />
16+
<br />
17+
<p>Results:</p>
18+
<ul>
19+
{results.value.value.map((item) => {
20+
return (
21+
<li>
22+
<pre>
23+
<code>{JSON.stringify(item, null, 2)}</code>
24+
</pre>
25+
</li>
26+
);
27+
})}
28+
</ul>
29+
</div>
30+
);
31+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
title: History Page
3+
---
4+
5+
## Requests
6+
7+
- {@link "History Messages".InitialSetupRequest `initialSetup`}
8+
- Returns {@link "History Messages".InitialSetupResponse}
9+
10+
## Requests
11+
12+
### {@link "History Messages".QueryRequest `query`}
13+
- Sends {@link "History Messages".HistoryQuery}
14+
- Receives {@link "History Messages".HistoryQueryResponse}
15+
- Note: if an empty term is sent, you should reply with as many items as the limit allows.
16+
17+
The FE will send:
18+
```json
19+
{ "term": "", "limit": 150, "offset": 0 }
20+
```
21+
22+
The response will be:
23+
24+
```json
25+
{
26+
"info": {
27+
"finished": false,
28+
"term": ""
29+
},
30+
"value": [
31+
{
32+
"dateRelativeDay": "Today - Wednesday 15 January 2025",
33+
"dateShort": "15 Jan 2025",
34+
"dateTimeOfDay": "11:10",
35+
"domain": "youtube.com",
36+
"fallbackFaviconText": "L",
37+
"time": 1736939416961.617,
38+
"title": "Electric Callboy - Hypa Hypa (OFFICIAL VIDEO) - YouTube",
39+
"url": "https://www.youtube.com/watch?v=75Mw8r5gW8E"
40+
},
41+
{"...": "..."}
42+
]
43+
}
44+
```
45+
46+
## Notifications
47+
48+
### {@link "History Messages".ReportInitExceptionNotification `reportInitException`}
49+
- Sent when the application fails to initialize (for example, a JavaScript exception prevented it)
50+
- Sends: `{ message: string }` - see {@link "History Messages".ReportInitExceptionNotify}
51+
52+
### {@link "History Messages".ReportPageExceptionNotification `reportPageException`}
53+
- Sent when the application failed after initialization (for example, a JavaScript exception prevented it)
54+
- Sends: `{ message: string }` - see {@link "History Messages".ReportPageExceptionNotify}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { h } from 'preact';
2+
3+
export function Cross() {
4+
return (
5+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
6+
<path
7+
d="M13.2803 3.78033C13.5732 3.48744 13.5732 3.01256 13.2803 2.71967C12.9874 2.42678 12.5126 2.42678 12.2197 2.71967L8 6.93934L3.78033 2.71967C3.48744 2.42678 3.01256 2.42678 2.71967 2.71967C2.42678 3.01256 2.42678 3.48744 2.71967 3.78033L6.93934 8L2.71967 12.2197C2.42678 12.5126 2.42678 12.9874 2.71967 13.2803C3.01256 13.5732 3.48744 13.5732 3.78033 13.2803L8 9.06066L12.2197 13.2803C12.5126 13.5732 12.9874 13.5732 13.2803 13.2803C13.5732 12.9874 13.5732 12.5126 13.2803 12.2197L9.06066 8L13.2803 3.78033Z"
8+
fill="currentColor"
9+
fill-opacity="1"
10+
/>
11+
</svg>
12+
);
13+
}

0 commit comments

Comments
 (0)