Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions package-lock.json

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

14 changes: 14 additions & 0 deletions src/background.index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { DebugTab } from './shared/db/types';
import { WAKE_UP_BACKGROUND } from './shared/messages';

import Port = chrome.runtime.Port;
import { manageLocalStoreSpace } from './background/services/data';

interface Service {
name: string;
Expand All @@ -30,6 +31,10 @@ const ASYNC_POLL_INTERVAL_MINUTES = 1;
const ASYNC_STATS_INTERVAL_ALARM_NAME = 'send-stats';
const ASYNC_STATS_INTERVAL_MINUTES = 1;

const ASYNC_CLEAN_TIMELINE_ALARM_NAME = 'clean-timeline';
const ASYNC_CLEAN_TIMELINE_MINUTES = 1440; // 24 hours * 60 minutes - one day
const DEFAULT_CUTOFF_DAYS = 60;

function findDebuggingTabIndexFromId(tabIdOrUrl: number | string | undefined) {
if (tabIdOrUrl !== undefined) {
for (let i = 0; i < debuggingTabs.length; i++) {
Expand Down Expand Up @@ -78,6 +83,10 @@ const asyncPollAlarmHandler = async (): Promise<void> => {
const sendStatsAlarmHandler = async (): Promise<void> =>
await sendWebActivityAutomatically();

const cleanTimeLineAlarmHandler = async (): Promise<void> => {
await manageLocalStoreSpace(DEFAULT_CUTOFF_DAYS)
}

const ChromeServiceDefinition: Array<Service> = [
{
handler: asyncPollAlarmHandler,
Expand All @@ -89,6 +98,11 @@ const ChromeServiceDefinition: Array<Service> = [
intervalInMinutes: ASYNC_STATS_INTERVAL_MINUTES,
name: ASYNC_STATS_INTERVAL_ALARM_NAME,
},
{
handler: cleanTimeLineAlarmHandler,
intervalInMinutes: ASYNC_CLEAN_TIMELINE_MINUTES,
name: ASYNC_CLEAN_TIMELINE_ALARM_NAME
}
];

ChromeServiceDefinition.forEach((service) => {
Expand Down
69 changes: 69 additions & 0 deletions src/background/services/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { connect, TimeTrackerStoreTables } from '../../shared/db/idb';
import { logMessage } from '../tables/logs';

const getIdsToDelete = async (cutOffDate: Date) => {
await logMessage(`Cut Off Date: ${cutOffDate.getTime()}`);
const db = await connect();
const timeline = await db.getAll(
TimeTrackerStoreTables.Timeline,
);
const idsToDelete: number[] = [];

for (const data of timeline) {
const recordDate = new Date(data.date).getTime();
if (recordDate < cutOffDate.getTime()) {
const id: number = data.id as number;
// Should be deleted
idsToDelete.push(id);
}
}

return idsToDelete;
};

const deleteRecordsById = async (idsToDelete: number[]): Promise<string> => {
try {

const db = await connect();
const transaction = db.transaction(
TimeTrackerStoreTables.Timeline,
'readwrite',
);
const store = transaction.objectStore(TimeTrackerStoreTables.Timeline);

for (const id of idsToDelete) {
// Using any as delete function expects string but we store id as number
// this throws lint error
const delId: any = id;
await store.delete(delId);
}

await transaction.done;
await logMessage('Records deleted successfully.');
return 'Records deleted successfully.';
} catch (error) {
console.error('Error deleting IDB records:', error);
return 'Failed to delete records.';
}
};

const manageLocalStoreSpace = async (
defaultCutOff: number,
): Promise<string> => {
await logMessage(`Handling Old Data Cleanup`);
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - defaultCutOff);
const idsToDelete = await getIdsToDelete(cutoffDate);

await logMessage(
`Records to Delete: ${JSON.stringify(idsToDelete, null, 2)}`,
);

if (idsToDelete.length > 0) {
return await deleteRecordsById(idsToDelete);
}

return 'No data available for deletion beyond the 60 days timeframe.'
};

export { manageLocalStoreSpace };
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from "react";
import { Panel, PanelBody, PanelHeader } from "../../../blocks/Panel";
import { Button, ButtonType } from "../../../blocks/Button";
import { handleClearTimeLineData } from "../../../shared/db/helper";

export const CleanUpTimeLineStorage: React.FC = () => {
const [state, setState] = React.useState<{
status: boolean,
statusText: string,
}>({
status: false,
statusText: '',
});

const handleClearData = (() => {
handleClearTimeLineData()
.then((res) => {
setState({
status: true,
statusText: res
})
})
});

const { status, statusText } = state;
return (
<Panel>
<PanelHeader>Clean Up Old Timeline Data</PanelHeader>
<PanelBody className="flex flex-col gap-2">
<p>Timeline records older than 60 days will be removed from the database.</p>
<div className="flex justify-between items-center gap-2">
<div className="flex-1">
{status
&& (<p className="text-yellow-600">{statusText}</p>)
}
</div>
<Button
className="py-2 px-4 border-2 border-solid border-transparent"
buttonType={ButtonType.Primary}
onClick={handleClearData}
>
Clear
</Button>
</div>
</PanelBody>
</Panel>
)
}
2 changes: 2 additions & 0 deletions src/popup/pages/PreferencesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Input } from './../../blocks/Input';
import {IgnoredDomainSetting} from '../components/IgnoredDomainsSetting/IgnoredDomainSetting';
import { WhitelistDomainSetting } from '../components/WhitelistDomainsSetting/WhitelistDomainSetting';
import {UserTokenSetting} from "../components/UserTokenSetting/UserTokenSetting";
import { CleanUpTimeLineStorage } from '../components/CleanUpTimeLineStorage/CleanUpTimeLineStorage';

export const PreferencesPage: FC = () => {
const [isWhitelistShown, hideWhitelist] = React.useState<boolean>(true);
Expand Down Expand Up @@ -45,6 +46,7 @@ export const PreferencesPage: FC = () => {
{(isWhitelistShown ? <WhitelistDomainSetting />: <IgnoredDomainSetting />)}
</PanelBody>
</Panel>
<CleanUpTimeLineStorage />
</div>
);
};
7 changes: 7 additions & 0 deletions src/shared/db/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { manageLocalStoreSpace } from "../../background/services/data";

const DEFAULT_CUTOFF_DAYS = 60;

export const handleClearTimeLineData = async () => {
return await manageLocalStoreSpace(DEFAULT_CUTOFF_DAYS)
};
1 change: 1 addition & 0 deletions src/shared/db/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface TimelineRecord {
secure: boolean;
activityPeriodStart: number;
activityPeriodEnd: number;
id?: number;
}

export type ActiveTabState = {
Expand Down