Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
88 changes: 88 additions & 0 deletions src/data/repositories/chrome_local_storage_repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,92 @@ export class ChromeLocalStorageRepo implements StorageRepo {
});
});
}

async storeHiddenSenders(
emails: string[],
accountEmail: string,
): Promise<void> {
return new Promise((resolve, reject) => {
chrome.storage.local.get([accountEmail], (result) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
return;
}

const accountData = result[accountEmail] || { senders: [] };
const currentHidden = accountData.hiddenSenderEmails || [];
const updatedHidden = Array.from(
new Set([...currentHidden, ...emails]),
);

chrome.storage.local.set(
{
[accountEmail]: {
...accountData,
hiddenSenderEmails: updatedHidden,
},
},
() => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
return;
}
console.log("Updated hidden senders in local storage.");
resolve();
},
);
});
});
}

async readHiddenSenders(accountEmail: string): Promise<string[]> {
return new Promise((resolve, reject) => {
chrome.storage.local.get([accountEmail], (result) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
return;
}

const hiddenSenders = result[accountEmail]?.hiddenSenderEmails || [];
resolve(hiddenSenders);
});
});
}

async removeHiddenSenders(
emails: string[],
accountEmail: string,
): Promise<void> {
return new Promise((resolve, reject) => {
chrome.storage.local.get([accountEmail], (result) => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
return;
}

const accountData = result[accountEmail] || { senders: [] };
const currentHidden = accountData.hiddenSenderEmails || [];
const updatedHidden = currentHidden.filter(
(email: string) => !emails.includes(email),
);

chrome.storage.local.set(
{
[accountEmail]: {
...accountData,
hiddenSenderEmails: updatedHidden,
},
},
() => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
return;
}
console.log("Removed hidden senders from local storage.");
resolve();
},
);
});
});
}
}
28 changes: 28 additions & 0 deletions src/data/repositories/mocks/mock_storage_repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Sender } from "../../../domain/entities/sender";

export class MockStorageRepo implements StorageRepo {
private mockSenders: Sender[] = [];
private mockHiddenSenders: string[] = [];

constructor(initialSenders: Sender[] = this.mockSenders) {
this.mockSenders = initialSenders;
Expand Down Expand Up @@ -34,4 +35,31 @@ export class MockStorageRepo implements StorageRepo {
});
return Promise.resolve();
}

storeHiddenSenders(emails: string[], accountEmail: string): Promise<void> {
console.log(`[MOCK] Storing hidden senders for account: ${accountEmail}`);
emails.forEach((email) => {
console.log(`[MOCK] Hiding sender: ${email}`);
});
this.mockHiddenSenders = Array.from(
new Set([...this.mockHiddenSenders, ...emails]),
);
return Promise.resolve();
}

readHiddenSenders(accountEmail: string): Promise<string[]> {
console.log(`[MOCK] Reading hidden senders for account: ${accountEmail}`);
return Promise.resolve(this.mockHiddenSenders);
}

removeHiddenSenders(emails: string[], accountEmail: string): Promise<void> {
console.log(`[MOCK] Removing hidden senders for account: ${accountEmail}`);
emails.forEach((email) => {
console.log(`[MOCK] Unhiding sender: ${email}`);
});
this.mockHiddenSenders = this.mockHiddenSenders.filter(
(email) => !emails.includes(email),
);
return Promise.resolve();
}
}
23 changes: 23 additions & 0 deletions src/domain/repositories/storage_repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,27 @@ export interface StorageRepo {
* @param accountEmail - The email address of the account to associate the deletion with.
*/
deleteSenders(senderEmails: string[], accountEmail: string): Promise<void>;

/**
* Stores a list of hidden sender emails for a specific account.
*
* @param emails - An array of email addresses to hide.
* @param accountEmail - The email address of the account to associate the hidden senders with.
*/
storeHiddenSenders(emails: string[], accountEmail: string): Promise<void>;

/**
* Retrieves the list of hidden sender emails for a specific account.
*
* @param accountEmail - The email address of the account to retrieve hidden senders for.
*/
readHiddenSenders(accountEmail: string): Promise<string[]>;

/**
* Removes sender emails from the hidden list for a specific account.
*
* @param emails - An array of email addresses to unhide.
* @param accountEmail - The email address of the account to associate the unhiding with.
*/
removeHiddenSenders(emails: string[], accountEmail: string): Promise<void>;
}
4 changes: 4 additions & 0 deletions src/presentation/apps/popup/Popup.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,15 @@
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
margin: 16px auto;
gap: 8px;
}

.open-gmail-button img {
background-color: #233b86;
width: 20px;
height: 20px;
}

.open-gmail-button:hover {
Expand Down
12 changes: 1 addition & 11 deletions src/presentation/apps/popup/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,11 @@ const PopupApp = () => {
<h2>InboxWhiz</h2>
<p>Manage your inbox effortlessly with InboxWhiz!</p>

<button
className="open-gmail-button"
onClick={openGmail}
style={{
display: "flex",
alignItems: "center",
justifyContent: "center",
margin: "16px auto",
}}
>
<button className="open-gmail-button" onClick={openGmail}>
<img
src="https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico"
alt="Gmail Logo"
className="gmailLogo"
style={{ width: "20px", height: "20px" }}
/>
Open Gmail
</button>
Expand Down
36 changes: 17 additions & 19 deletions src/presentation/apps/sidebar/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@
:root,
.light {
--bg-primary: #fff;
--bg-secondary: #f8f9fa;
--bg-hover: #e8eaed;
--text-primary: #333;
--text-secondary: #5f6368;
--selected-bg: #c2dbff;
--button-bg: #e9e9e9;
--button-hover: #d8d8d8;
--border-color: #c4c4c4;
--line-color: #f2f6fc;
--plain-button: #000;
Expand All @@ -54,10 +57,13 @@

.dark {
--bg-primary: #1e1e1e;
--bg-secondary: #2a2a2a;
--bg-hover: #353535;
--text-primary: #f0f0f0;
--text-secondary: #b0b3b8;
--selected-bg: #34527a;
--button-bg: #3a3a3a;
--button-hover: #4a4a4a;
--border-color: #444;
--line-color: #555;
--plain-button: #555;
Expand All @@ -73,6 +79,12 @@
color: var(--text-primary);
}

.no-results-message {
text-align: center;
padding: 40px 20px;
color: var(--text-secondary);
}

#declutter-body {
font-family: "Google Sans", Roboto, RobotoDraft, Helvetica, Arial, sans-serif;
height: 97vh;
Expand All @@ -81,25 +93,6 @@
margin: 5px;
}

.declutter-header {
background-color: var(--header-bg);
}

#declutter-body.login {
height: 100vh;
color: white;
background-color: #233b86;
align-items: center;
justify-content: center;
font-size: 1rem;
margin: 0;
}

#declutter-body.login #email-account {
margin-top: 7px;
font-size: 0.75rem;
}

.button-bar {
padding: 10px 5px 0 15px;
min-width: 300px;
Expand All @@ -108,6 +101,11 @@
align-items: center;
}

.sender-actions {
display: flex;
gap: 8px;
}

#senders {
padding: 10px;
overflow: hidden auto;
Expand Down
22 changes: 14 additions & 8 deletions src/presentation/apps/sidebar/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import "./App.css";
import { useTheme } from "../../providers/theme_provider.tsx";
import { ActionButton } from "./components/actionButton.tsx";
import { ReloadButton } from "./components/reloadButton.tsx";
import { ModalPopup } from "./components/modalPopup.tsx";
import { SendersContainer } from "./components/sendersContainer.tsx";
import { DeclutterHeader } from "./components/header.tsx";
import { ModalProvider } from "./providers/modalContext.tsx";
import ThemeToggle from "./components/themeToggle.tsx";
import { AppProvider } from "../../providers/app_provider.tsx";
import { ThemeProvider } from "../../providers/theme_provider.tsx";
import { SearchInput } from "./components/searchInput.tsx";
import { useApp } from "../../providers/app_provider.tsx";
import { SettingsModal } from "./components/settingsModal.tsx";
import { useState, useRef } from "react";

function App() {
return (
Expand All @@ -25,21 +25,22 @@ function App() {
function AppWithTheme() {
const { theme } = useTheme();
const { searchTerm, setSearchTerm } = useApp();
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
const settingsButtonRef = useRef<HTMLButtonElement>(null);

return (
<ModalProvider>
<div id="declutter-body" className={theme}>
<DeclutterHeader />
<DeclutterHeader
onOpenSettings={() => setIsSettingsOpen(true)}
settingsButtonRef={settingsButtonRef}
/>

<div className="button-bar">
<div className="sender-actions">
<ActionButton id="unsubscribe-button" />
<ActionButton id="delete-button" />
</div>

<div style={{ display: "flex" }}>
<ReloadButton />
<ThemeToggle />
<ActionButton id="hide-button" />
</div>
</div>

Expand All @@ -48,6 +49,11 @@ function AppWithTheme() {
<SendersContainer />

<ModalPopup />
<SettingsModal
isOpen={isSettingsOpen}
onClose={() => setIsSettingsOpen(false)}
triggerRef={settingsButtonRef}
/>
</div>
</ModalProvider>
);
Expand Down
10 changes: 9 additions & 1 deletion src/presentation/apps/sidebar/components/actionButton.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
cursor: pointer;
font-size: 14px;
height: 32px;
margin: 4px;
padding: 0 16px;
box-shadow: 0 3px 5px rgb(0 0 0 / 20%);
}
Expand All @@ -27,6 +26,15 @@
background-color: #ca2633;
}

#hide-button {
background-color: #5a6c7d;
color: white;
}

#hide-button:hover {
background-color: #6b7c8d;
}

.action-button .i {
margin-right: 5px;
}
Loading