Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.11.1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/create-release-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: ruby/setup-ruby@d5126b9b3579e429dd52e51e68624dda2e05be25 # v1.267.0
with:
ruby-version: 3.4.7
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Install jq
run: sudo apt-get install -y jq
- name: Get version from manifest.json
Expand All @@ -31,7 +31,7 @@ jobs:
needs: create_tag_and_release_note
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 24.11.1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/validate-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
check_manifest_version_update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Install jq
run: sudo apt-get install jq
- name: Get latest tag from main branch
Expand Down
26 changes: 25 additions & 1 deletion src/platform/repository/TabGroupRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ import type {
TabGroup,
TabGroupColor,
} from "../../model/TabContainer";
import type { WindowId } from "../../model/Window";
import {
findGroupsByName,
flatTabsInWindows,
type Window,
type WindowId,
} from "../../model/Window";
import { ChromeLocalStorage } from "../storage/ChromeLocalStorage";
import { addTabsToGroup } from "./TabsRepository";

export const collapseTabGroup = async (groupId: number): Promise<void> => {
await chrome.tabGroups.update(groupId, { collapsed: true });
Expand All @@ -31,6 +37,24 @@ export const createGroupWithTabs = async (name: string, tabIds: number[]) => {
await chrome.tabGroups.update(groupId, { title: name });
};

export const groupTabsBySearchKeyword = async (
keyword: string,
windows: Window[],
tabIds: number[],
) => {
const pinnedTabs = flatTabsInWindows(windows).filter((tab) => tab.pinned);
const tabIdsExcludingPinned = tabIds.filter(
(tabId) => !pinnedTabs.some((tab) => tab.id === tabId),
);

const sameNameGroups = findGroupsByName(keyword, windows);
if (sameNameGroups.length > 0) {
await addTabsToGroup(tabIdsExcludingPinned, sameNameGroups[0].id);
}

await createGroupWithTabs(keyword, tabIdsExcludingPinned);
};

export const moveTabGroup = async (
groupId: number,
currentWindowId: number,
Expand Down
50 changes: 48 additions & 2 deletions src/platform/repository/TabsRepository.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import type { Tab, TabId, TabStatus } from "../../model/Tab";
import type { WindowId } from "../../model/Window";
import {
isSamePageTabs,
type Tab,
type TabId,
type TabStatus,
} from "../../model/Tab";
import {
flatTabsInWindows,
type Window,
type WindowId,
} from "../../model/Window";
import { ChromeLocalStorage } from "../storage/ChromeLocalStorage";
import { ChromeSessionStorage } from "../storage/ChromeSessionStorage";

Expand All @@ -24,6 +33,31 @@ export const closeTabs = async (tabIds: number[]) => {
await chrome.tabs.remove(tabIds);
};

export const moveTabFromRootToPinned = async (
tabId: number,
windowId: number,
index: number,
) => {
await moveTab(tabId, windowId, -1);
await pinTab(tabId);
await moveTab(tabId, windowId, index);
};

export const moveTabFromPinnedToPinned = async (
tabId: number,
sourceWindowId: number,
destWindowId: number,
index: number,
) => {
if (sourceWindowId === destWindowId) {
await moveTab(tabId, sourceWindowId, index);
} else {
await moveTab(tabId, destWindowId, -1);
await pinTab(tabId);
await moveTab(tabId, destWindowId, index);
}
};

export const updateTabLastActivatedAt = async (
tabId: number,
options?: {
Expand Down Expand Up @@ -164,6 +198,18 @@ export const unpinAllTabs = async (tabs: Tab[]) => {
}
};

export const resolveDuplicatedTabs = async (
windows: Window[],
targetTab: Tab,
) => {
const allTabs = flatTabsInWindows(windows);
const duplicateTabs = allTabs.filter(
(tab) => tab.id !== targetTab.id && isSamePageTabs(tab, targetTab),
);
const duplicateTabIds = duplicateTabs.map((t) => t.id);
await closeTabs(duplicateTabIds);
};

export const getRecentActiveTabs = async (): Promise<Tab[]> => {
const recentActiveTabs = await ChromeSessionStorage.getRecentActiveTabs();
if (!recentActiveTabs) return [];
Expand Down
23 changes: 23 additions & 0 deletions src/platform/repository/WindowsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,29 @@ export const closeWindow = async (window: Window): Promise<Window[]> => {
return getWindows();
};

export const mergeWindow = async (
destWindowId: number,
sourceWindow: Window,
) => {
for (const child of sourceWindow.children) {
if (isPinned(child)) {
for (const tab of child.children) {
await chrome.tabs.move(tab.id, { windowId: destWindowId, index: -1 });
await chrome.tabs.update(tab.id, { pinned: true });
}
}
if (isTabGroup(child)) {
await chrome.tabGroups.move(child.id, {
windowId: destWindowId,
index: -1,
});
}
if (isTab(child)) {
await chrome.tabs.move(child.id, { windowId: destWindowId, index: -1 });
}
}
};

const applyLastActivatedAtToTabs = async (
windows: Window[],
): Promise<Window[]> => {
Expand Down
2 changes: 1 addition & 1 deletion src/ui/components/ActionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ import {
} from "../../platform/repository/TabsRepository";
import {
closeWindow,
mergeWindow,
removeStoredWindow,
restoreWindow,
saveWindow,
saveWindows,
} from "../../platform/repository/WindowsRepository";
import mergeWindow from "../functions/mergeWindow";

type ActionMenuItemAttrs =
| {
Expand Down
4 changes: 2 additions & 2 deletions src/ui/components/DragAndDropContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ import {
} from "../../platform/repository/TabGroupRepository";
import {
moveTab,
moveTabFromPinnedToPinned,
moveTabFromRootToPinned,
moveTabOutOfGroup,
moveTabToOtherWindow,
unpinTab,
Expand All @@ -53,8 +55,6 @@ import {
addWindowWithTabGroup,
} from "../../platform/repository/WindowsRepository";
import { WindowsContext } from "../contexts/WindowsContext";
import moveTabFromPinnedToPinned from "../functions/moveTabFromPinnedToPinned";
import moveTabFromRootToPinned from "../functions/moveTabFromRootToPinned";
import TabGroupContainer from "./TabGroupContainer";
import TabItem from "./TabItem";

Expand Down
7 changes: 5 additions & 2 deletions src/ui/components/TabItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ import {
hasDuplicatedTabs,
type Window,
} from "../../model/Window";
import { closeTab, focusTab } from "../../platform/repository/TabsRepository";
import {
closeTab,
focusTab,
resolveDuplicatedTabs,
} from "../../platform/repository/TabsRepository";
import { WindowsContext } from "../contexts/WindowsContext";
import resolveDuplicatedTabs from "../functions/resolveDuplicatedTabs";
import { TabItemActionMenu } from "./ActionMenu";
import TabFavicon from "./TabFavicon";

Expand Down
27 changes: 0 additions & 27 deletions src/ui/functions/groupTabsBySearchKeyword.ts

This file was deleted.

23 changes: 0 additions & 23 deletions src/ui/functions/mergeWindow.ts

This file was deleted.

18 changes: 0 additions & 18 deletions src/ui/functions/moveTabFromPinnedToPinned.ts

This file was deleted.

13 changes: 0 additions & 13 deletions src/ui/functions/moveTabFromRootToPinned.ts

This file was deleted.

14 changes: 0 additions & 14 deletions src/ui/functions/resolveDuplicatedTabs.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/ui/options/TabSearchForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import { useCallback, useContext, useEffect, useRef, useState } from "react";
import t from "../../i18n/Translations";
import type { Tab } from "../../model/Tab";
import { findTabsByTitleOrUrl } from "../../model/Window";
import { groupTabsBySearchKeyword } from "../../platform/repository/TabGroupRepository";
import {
focusTab,
getRecentActiveTabs,
} from "../../platform/repository/TabsRepository";
import TabItem from "../components/TabItem";
import { WindowsContext, WindowsProvider } from "../contexts/WindowsContext";
import groupTabsBySearchKeyword from "../functions/groupTabsBySearchKeyword";

const smoothScrollTo = (container: HTMLElement, targetScrollTop: number) => {
const startScrollTop = container.scrollTop;
Expand Down
2 changes: 1 addition & 1 deletion src/ui/popup/SearchResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import { useContext, useEffect, useRef, useState } from "react";
import t from "../../i18n/Translations";
import type { Tab } from "../../model/Tab";
import { findTabsByTitleOrUrl } from "../../model/Window";
import { groupTabsBySearchKeyword } from "../../platform/repository/TabGroupRepository";
import {
focusTab,
getRecentActiveTabs,
} from "../../platform/repository/TabsRepository";
import TabItem from "../components/TabItem";
import { WindowsContext } from "../contexts/WindowsContext";
import groupTabsBySearchKeyword from "../functions/groupTabsBySearchKeyword";

type SearchResultProps = {
searchText: string;
Expand Down
Loading