Skip to content

Commit 211c3b2

Browse files
authored
Feature/automation fixes (#51)
* fixed long running issue with deepsave not working on the 1st save * fixed automation saving issue * have the user approve permission before running automations * ready for release
1 parent 748fc74 commit 211c3b2

File tree

13 files changed

+729
-1342
lines changed

13 files changed

+729
-1342
lines changed

package-lock.json

Lines changed: 516 additions & 1230 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "your-rapport",
3-
"version": "0.28.0",
3+
"version": "0.29.0",
44
"description": "A chrome extension for saving screenshots and making them searchable.",
55
"license": "Commercial",
66
"scripts": {

src/backgrounds/automation-runner.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import BulkAutomationUrl from '../models/schemas/BulkAutomationUrl';
1212
import { NoChangeDetectedError } from '../errors/NoChangeDetectedError';
1313
import { Tag } from '../models/schemas/Tag';
1414
import { getUtc, getUtcNow } from '../utilities/transformers';
15+
import { getActivePageInfo } from '../pages/Content/scripts/pageInfo';
1516

1617

1718
let processing: boolean = false;
@@ -142,13 +143,9 @@ async function processQueue() {
142143

143144
// Wait for load or DNS failure (ERR_NAME_NOT_RESOLVED)
144145
await waitForCompleteOrDnsError(tabId);
145-
const response = await chrome.tabs.sendMessage(tabId, { cmd: PAGE_INFO });
146-
const { pageInfo } = response
147146
await focusTab(tabId);
148-
149147
// wait for the page to finish loading
150148
// TODO: add configurable delay
151-
await sleep(2000)
152149

153150
// the automation requires scrolling through the page
154151
if (!job.isDeepSave) {
@@ -158,10 +155,10 @@ async function processQueue() {
158155
})
159156
do {
160157

161-
await sleep(1000)
158+
await sleep(3000)
162159
const refreshedJob = await db.bulkAutomation.get(job.uuid)
163-
164160
if (!refreshedJob) {
161+
await debug('Unknown automation job', job)
165162
throw Error('Unknown job')
166163
}
167164

@@ -177,12 +174,12 @@ async function processQueue() {
177174
}
178175
job.screenShotsCollected = refreshedJob.screenShotsCollected
179176
ExtensionPin.setAutomationRunning(await getQueue());
180-
await sleep(1000);
181177
}
182178
while (['running', 'queued'].includes(job.status));
183179
}
184180
// deep save
185181
else {
182+
const pageInfo = await getActivePageInfo(tab);
186183
await capture(tab, pageInfo, true, job as BulkAutomationUrl);
187184
}
188185
await complete(job);
@@ -200,8 +197,9 @@ async function processQueue() {
200197
if (!job.keepTabOpen && job.status !== 'failed' && tabId) {
201198
try {
202199
await chrome.tabs.remove(tabId);
203-
} catch {
204-
200+
}
201+
catch {
202+
// error closing the tab, ignore it
205203
}
206204
}
207205
}

src/components/TopAppBar.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,27 @@ import SyncDisabledIcon from '@mui/icons-material/SyncDisabled';
1717
import { Configuration } from '../models/schemas/Configuration';
1818
import SecurityIcon from '@mui/icons-material/Security';
1919
import { allSitesAccessApproved, removeAllSitesAccess, requestAllSitesAccess } from '../services/manifest_permissions';
20+
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
21+
import { db } from '../models/db/dexieDb';
2022

2123
export default function TopAppBar() {
2224
const [anchorEl, setAnchorEl] = React.useState(null);
2325
const open = Boolean(anchorEl);
2426
const [auth, setAuth] = React.useState(true);
2527
const [configuration, setConfiguration] = useState({})
2628
const [hasPermission, setHasPermission] = useState(true);
29+
const [hasGeminiEnabled, setHasGeminiEnabled] = useState(false);
30+
const [geminiTooltip, setGeminiTooltip] = useState('')
2731

2832
useEffect(() => {
2933
async function fetchData(){
3034
const user = await getUser();
3135
setAuth(user && user.verify() ? true : false);
3236
setConfiguration(await Configuration.getConfiguration());
3337
setHasPermission(await allSitesAccessApproved());
38+
const result = await LanguageModel.availability({ languages: ["en"] })
39+
setGeminiTooltip(result)
40+
setHasGeminiEnabled(result === 'available');
3441
}
3542
fetchData();
3643
}, []);
@@ -69,6 +76,19 @@ export default function TopAppBar() {
6976
if(found){
7077
createTab(found.url, '_blank');
7178
}
79+
80+
if(found.name === 'automations'){
81+
// stop all automations from running
82+
const automations = await db.bulkAutomation.toArray();
83+
automations.forEach(a => {
84+
// flagged to run
85+
if(a.active && !a.ranOn){
86+
a.active = false;
87+
}
88+
})
89+
await db.bulkAutomation.bulkPut(automations);
90+
}
91+
7292
}
7393

7494
return (
@@ -133,6 +153,23 @@ export default function TopAppBar() {
133153
</Tooltip>
134154

135155

156+
<Tooltip
157+
title={ 'Gemini Nano is ' + geminiTooltip}>
158+
<IconButton
159+
size="large"
160+
aria-label=""
161+
color="inherit"
162+
onClick={async() => {
163+
if(geminiTooltip === 'downloadable') {
164+
chrome.runtime.sendMessage({cmd: 'installGemini'})
165+
}
166+
}}
167+
>
168+
<AutoAwesomeIcon color={ ['available', 'downloading'].includes(geminiTooltip) ? 'info' : 'error'}/>
169+
</IconButton>
170+
</Tooltip>
171+
172+
136173
{auth && configuration.syncBackgroundEnabled ? (
137174
<Tooltip title={'Local data sync is active'}>
138175
<IconButton

src/components/tables/BulkAutomationDataTable.js

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,41 +17,43 @@ import {
1717
UUID
1818
} from '../../services/constants';
1919
import { debug } from '../../services/logger_services';
20-
import { sortByField } from '../../utilities/transformers';
20+
import { sha256, sortByField } from '../../utilities/transformers';
2121
import { db } from '../../models/db/dexieDb';
2222
import ExtensionPin from '../../utilities/ExtensionPin';
23+
import { requestAllSitesAccess } from '../../services/manifest_permissions';
2324

2425
export default function BulkAutomationTable(props) {
2526
const [rows, setRows] = useState([]);
26-
const [isLoading, setIsLoading] = useState(true);
27+
const [isLoading, setIsLoading] = useState(false);
28+
let cacheHash = '';
2729

2830
async function fetchData() {
2931
showLoader();
30-
setIsLoading(true);
3132
const start = performance.now();
3233
const data = await db.bulkAutomation.toArray();
34+
cacheHash = await sha256(JSON.stringify(data));
3335
sortByField(data, 'createdOn')
34-
35-
if (data.length !== rows.length) {
36-
setRows(data);
37-
}
36+
setRows(data);
3837
const elapsed = performance.now() - start;
3938
debug(`Finished after ${Math.max(elapsed).toFixed(0)}ms`);
40-
setIsLoading(false)
4139
hideLoader();
4240
}
4341

4442
useEffect(() => {
45-
fetchData();
46-
43+
fetchData()
4744
/**
4845
* Check if any updates occurred
4946
* @type {number}
5047
*/
5148
const intervalId = setInterval(async () => {
52-
// TODO: improve reload algorithm
53-
fetchData();
54-
}, 10000); // wait 10 seconds before re-renders
49+
const data = await db.bulkAutomation.toArray();
50+
const currentHash = await sha256(JSON.stringify(data));
51+
if(currentHash !== cacheHash){
52+
cacheHash = currentHash;
53+
sortByField(data, 'createdOn')
54+
setRows(data);
55+
}
56+
}, 5000); // wait 5 seconds before re-renders
5557
return () => clearInterval(intervalId);
5658
}, []);
5759

@@ -315,6 +317,12 @@ export default function BulkAutomationTable(props) {
315317
<Tooltip title={'Re run the automation on this url'}>
316318
<IconButton
317319
onClick={async () => {
320+
const hasPermission = await requestAllSitesAccess();
321+
322+
if(!hasPermission){
323+
alert('Automations do not work unless your approve the permission request.');
324+
return;
325+
}
318326
db.transaction('rw', db.bulkAutomation, async () => {
319327
const automation = await db.bulkAutomation.get(record.uuid);
320328
automation.active = true;
@@ -372,7 +380,16 @@ export default function BulkAutomationTable(props) {
372380
'Start Automation Process, do not interact with your browser while automation is running.'
373381
}
374382
>
375-
<IconButton onClick={() => startAutomationProcess()}>
383+
<IconButton onClick={async() => {
384+
const hasPermission = await requestAllSitesAccess();
385+
if(hasPermission){
386+
startAutomationProcess()
387+
}
388+
else{
389+
alert('Automations do not work unless your approve the permission request.')
390+
}
391+
}}>
392+
376393
<DirectionsRunIcon />
377394
</IconButton>
378395
</Tooltip>

src/components/tables/ScheduledAutomationDataTable.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import ScheduleAutomationDialog from '../dialogs/automations/ScheduledAutomation
2323
import DirectionsRunIcon from '@mui/icons-material/DirectionsRun';
2424
import EditIcon from '@mui/icons-material/Edit';
2525
import { CronExpressionParser } from 'cron-parser';
26+
import { requestAllSitesAccess } from '../../services/manifest_permissions';
2627

2728

2829
export default function ScheduledAutomationDataTable(): JSX.Element {
@@ -349,7 +350,15 @@ export default function ScheduledAutomationDataTable(): JSX.Element {
349350
customToolbar: () => (
350351
<>
351352
<Tooltip title={'Add a new scheduled automation'}>
352-
<IconButton onClick={() => { setIsOpen(true)}}>
353+
<IconButton onClick={async() => {
354+
const hasPermission = await requestAllSitesAccess();
355+
if(!hasPermission){
356+
alert('Automations do not work unless your approve the permission request.');
357+
return;
358+
}
359+
360+
setIsOpen(true)
361+
}}>
353362
<AlarmAddIcon />
354363
</IconButton>
355364
</Tooltip>

0 commit comments

Comments
 (0)