Skip to content

Commit

Permalink
pinnedTabs
Browse files Browse the repository at this point in the history
  • Loading branch information
tarborlevan committed May 6, 2024
1 parent fa5faa8 commit 4560515
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 8 deletions.
5 changes: 5 additions & 0 deletions src/assets/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,9 @@ li.tab {

.collapsible-header {
line-height: 2.2;
}

.material-icons.pinned-tab {
color: gray;
transform: rotate3d(0, 1, 1, 45deg);
}
2 changes: 2 additions & 0 deletions src/popup/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Dispatch } from 'redux';
import { RUNTIME_MESSAGES } from '@/general/constants';
import { messageListener } from './listener';
import { ToastContainer } from "react-toastify";
import { loadInitialPinnedTabsState } from './redux/variables/varActions';

const App: React.FC = () => {
const config = useSelector((state: { config: IConfigProps }) => state.config);
Expand All @@ -25,6 +26,7 @@ const App: React.FC = () => {

useEffect(() => {
store.dispatch(loadInitialConfigState());
store.dispatch(loadInitialPinnedTabsState());
requestVariableUpdate({ action: RUNTIME_MESSAGES.config_get });
}, []);

Expand Down
27 changes: 24 additions & 3 deletions src/popup/components/BrowserTabsCollection.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import React from 'react';
import { browser } from '../utils';
import { browser, cx } from '../utils';
import { RUNTIME_MESSAGES } from '@/general/constants';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { Dispatch } from 'redux';
import { setBrowserTabs } from '../redux/tabs/tabActions';
import { setPinnedTabs } from '../redux/variables/varActions';

interface BrowserTabsCollectionTypes {
browserTabs: ICanvasTab[]
}

const BrowserTabsCollection: React.FC<BrowserTabsCollectionTypes> = ({ browserTabs }) => {
const dispatch = useDispatch<Dispatch<any>>();
const variables = useSelector((state: { variables: IVarState }) => state.variables);

const removeBrowserToCanvasTabClicked = (tab: ICanvasTab) => {
console.log('UI | Close icon clicked: ', tab.url);
Expand All @@ -28,12 +30,25 @@ const BrowserTabsCollection: React.FC<BrowserTabsCollectionTypes> = ({ browserTa
});
}

const togglePinned = (url: string) => {
const pinnedTabs = variables.pinnedTabs.filter(pt => pt !== url);
if(pinnedTabs.length !== variables.pinnedTabs.length) return dispatch(setPinnedTabs(pinnedTabs));
return dispatch(setPinnedTabs([...pinnedTabs, url]));
}

const sortByPinnedTabs: (browserTabs: ICanvasTab[], pinnedTabs: string[]) => ICanvasTab[] = (browserTabs, pinnedTabs) => {
return [
...(pinnedTabs.map(pt => browserTabs.find(tab => tab.url === pt)).filter(t => t) as ICanvasTab[]),
...browserTabs.filter(tab => !pinnedTabs.some(pt => pt === tab.url))
];
}

return (
<ul className="collection">
{
!browserTabs?.length ?
(<li className="collection-item">No browser tabs found</li>) :
browserTabs.map((tab: ICanvasTab, idx: number) => {
sortByPinnedTabs(browserTabs, variables.pinnedTabs).map((tab: ICanvasTab, idx: number) => {
if (!tab.url) return null;
return <li key={idx + tab.url} className="collection-item" style={{ display: 'flex', justifyContent: 'space-between' }}>
<a
Expand All @@ -53,6 +68,12 @@ const BrowserTabsCollection: React.FC<BrowserTabsCollectionTypes> = ({ browserTa
{tab.title || ""}
</a>
<span className="icons">
<i
className={cx("material-icons", variables.pinnedTabs.some(pt => pt === tab.url) ? "pinned-tab" : "")}
style={{ cursor: "pointer" }}
title={variables.pinnedTabs.some(pt => pt === tab.url) ? "Remove pin" : "Pin tab"}
onClick={(e) => { e.preventDefault(); togglePinned(tab.url as string); }}
>push_pin</i>
<i
className="material-icons"
style={{ cursor: "pointer" }}
Expand Down
8 changes: 7 additions & 1 deletion src/popup/redux/variables/varActionTypes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const SET_CONNECTED = 'SET_CONNECTED';
export const SET_CONTEXT = 'SET_CONTEXT';
export const SET_RETRYING = 'SET_RETRYING';
export const SET_PINNED_TABS = 'SET_PINNED_TABS';

interface SetConnected {
type: typeof SET_CONNECTED;
Expand All @@ -17,5 +18,10 @@ interface SetRetrying {
payload: boolean;
}

interface SetPinnedTabs {
type: typeof SET_PINNED_TABS;
payload: string[];
}


export type VariableActionTypes = SetConnected | SetContext | SetRetrying;
export type VariableActionTypes = SetConnected | SetContext | SetRetrying | SetPinnedTabs;
27 changes: 26 additions & 1 deletion src/popup/redux/variables/varActions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { SET_CONNECTED, SET_CONTEXT, SET_RETRYING, VariableActionTypes } from "./varActionTypes";
import { Dispatch } from "redux";
import { SET_CONNECTED, SET_CONTEXT, SET_PINNED_TABS, SET_RETRYING, VariableActionTypes } from "./varActionTypes";
import { browser } from "@/popup/utils";

export const setRetrying = (retrying: boolean): VariableActionTypes => ({
type: SET_RETRYING,
Expand All @@ -14,3 +16,26 @@ export const setContext = (context: IContext): VariableActionTypes => ({
type: SET_CONTEXT,
payload: context,
});

export const setPinnedTabs = (pinnedTabs: string[]): VariableActionTypes => ({
type: SET_PINNED_TABS,
payload: pinnedTabs,
});


export const loadInitialPinnedTabsState = () => async (dispatch: Dispatch<VariableActionTypes>) => {
try {
// Retrieve sync state from Chrome storage
const pinnedTabs = await new Promise<string[]>((resolve, reject) => {
browser.storage.local.get(["pinnedTabs"]).then(storage => {
console.log("get pinnedTabs result: ", storage);
resolve(storage.pinnedTabs || []);
});
});

// Dispatch action to set sync state
dispatch(setPinnedTabs(pinnedTabs));
} catch (error) {
console.error('Error loading initial state from Chrome storage:', error);
}
};
20 changes: 17 additions & 3 deletions src/popup/redux/variables/varReducer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { SET_CONNECTED, SET_CONTEXT, SET_RETRYING, VariableActionTypes } from "./varActionTypes";
import { browser } from "@/popup/utils";
import { SET_CONNECTED, SET_CONTEXT, SET_PINNED_TABS, SET_RETRYING, VariableActionTypes } from "./varActionTypes";

const DEFAULT_STATE = {
connected: false,
context: {
url: "universe:///",
color: "#fff"
},
retrying: false
retrying: false,
pinnedTabs: []
}

const savePinnedTabsToStorage = (pinnedTabs: string[]) => {
console.log("saving pinnedTabs to storage...", pinnedTabs);
browser.storage.local.set({ "pinnedTabs": pinnedTabs });
};

const varReducer = (state = DEFAULT_STATE, action: VariableActionTypes): IVarState => {
switch (action.type) {
case SET_CONNECTED:
Expand All @@ -25,7 +32,14 @@ const varReducer = (state = DEFAULT_STATE, action: VariableActionTypes): IVarSta
return {
...state,
retrying: action.payload
}
};
case SET_PINNED_TABS:
const result = {
...state,
pinnedTabs: action.payload,
};
savePinnedTabsToStorage(result.pinnedTabs);
return result;
default:
return state;
}
Expand Down
1 change: 1 addition & 0 deletions src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ interface IVarState {
connected: boolean;
context: IContext;
retrying: boolean;
pinnedTabs: string[];
}

interface ITabsInfo {
Expand Down

0 comments on commit 4560515

Please sign in to comment.