Skip to content

Commit

Permalink
Merge pull request #22 from web-dahuyou/dev
Browse files Browse the repository at this point in the history
新增小功能
  • Loading branch information
web-dahuyou authored Aug 19, 2024
2 parents b1c198d + 7644e8b commit b8ffde7
Show file tree
Hide file tree
Showing 24 changed files with 308 additions and 43 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
- 支持分类、标签组、标签页管理,包括一键收集保存、恢复、星标、锁定、增删改查、拖拽排序等功能。
- 分类支持展开/收起,支持创建分类和标签组,方便移动其他标签组/标签页到新分类/新标签组。
- 支持多种插件格式的 **导入/导出** 功能,支持导出到本地。目前支持 `NiceTab``OneTab` 格式的交叉导入导出(比如:可选择导入OneTab格式并导出为NiceTab格式;或者将NiceTab格式导出为OneTab格式),后续可根据需求增加其他插件格式的导入导出功能。
- 支持**远程同步**,您可根据需求将标签页同步到自己的 github 和 gitee 账号,只需要配置自己的 access token 即可(注意 token 权限只勾选 gists 操作)。
- 支持**远程同步**,您可根据需求将标签页同步到自己的 github 和 gitee 账号,只需要配置自己的 access token 即可(注意 token 权限只勾选 gists 操作)。
- 支持**皮肤主题切换**,目前暂时设置了有限的几种主题色提供选择,后续可根据需求扩大选择范围。
- 支持**多语言**,目前暂时支持中英文切换 (非地道英语,期待英语大佬帮忙校正)。
- 支持**回收站功能**,回收站中的标签页可还原到标签列表或者彻底删除。标签列表和回收站支持根据分类和标签组归类合并,方便管理。
Expand Down Expand Up @@ -110,6 +110,7 @@
- 打开**管理后台 > 标签列表**页,查看已发送的标签页列表,支持分类和标签组管理。
- 打开**管理后台 > 设置**页,可保存扩展的偏好设置。
- 打开**管理后台 > 导入导出**页,可进行NiceTab和OneTab格式的标签页导入导出操作。
- 打开**管理后台 > 同步**页,可根据需求将标签页同步到自己的 github 和 gitee 账号,只需要配置自己的 access token 即可(注意 token 权限只勾选 gists 操作)。
- 打开**管理后台 > 回收站**页,可查看和管理从标签列表页中删除的分类、标签组、标签页,并进行还原和删除操作。

## 更新计划
Expand Down
4 changes: 2 additions & 2 deletions entrypoints/common/components/StickyBox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactNode, useEffect, useState, useRef, useCallback } from 'react';
import { ReactNode, useEffect, useState, useRef } from 'react';
import styled from 'styled-components';
import { classNames } from '~/entrypoints/common/utils';

Expand Down Expand Up @@ -74,7 +74,7 @@ export function StickyBox({ children, topGap = 0, fullWidth = false, bgColor = '
<StyledStickyInner
ref={innerRef}
className={classNames('sticky-box-inner', fixed && 'fixed')}
$width={fullWidth ? '100%' : wrapperBounds.width}
$width={fullWidth ? '' : wrapperBounds.width}
$left={fullWidth ? 0 : wrapperBounds.left}
$top={topGap}
$bgColor={bgColor}
Expand Down
74 changes: 74 additions & 0 deletions entrypoints/common/components/StickyFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { ReactNode, useEffect, useState, useRef } from 'react';
import styled from 'styled-components';

const StyledStickyInner = styled.div<{
$width?: number | string;
$left?: number | string;
$bottom: number | string;
$bgColor?: string;
$paddingX?: number | string;
}>`
position: relative;
width: 100%;
padding: 0 ${(props) => props.$paddingX || 0}px;
background: ${(props) => props.$bgColor || '#fff'};
&.fixed {
position: fixed;
width: ${(props) => props.$width ? `${props.$width}px` : '100%'};
left: ${(props) => `${props.$left || 0}px`};
bottom: ${(props) => `${props.$bottom || 0}px`};
box-shadow: 0 -2px 12px 1px rgba(0, 0, 0, 0.1);
z-index: 10;
}
`;

interface StickyFooterProps {
children: ReactNode;
bottomGap?: number;
fullWidth?: boolean;
bgColor?: string;
paddingX?: number | string;
}

export default function StickyFooter({
children,
bottomGap = 0,
fullWidth = false,
bgColor = '#fff',
paddingX = 0,
}: StickyFooterProps) {
const wrapperRef = useRef<HTMLDivElement>(null);
const innerRef = useRef<HTMLDivElement>(null);
const [wrapperBounds, setWrapperBounds] = useState({
bottom: 0,
left: 0,
width: 0,
height: 0,
});

useEffect(() => {
const wrapper = wrapperRef.current;
const inner = innerRef.current;
if (!wrapper || !inner) return;
const { left, width } = wrapper.getBoundingClientRect();
const { height } = inner.getBoundingClientRect();
wrapper.style.height = `${height}px`;
setWrapperBounds({ bottom: 0, left, width, height });
}, []);

return (
<div ref={wrapperRef} className="sticky-footer-wrapper">
<StyledStickyInner
ref={innerRef}
className="sticky-footer-inner fixed"
$width={fullWidth ? '' : wrapperBounds.width}
$left={fullWidth ? 0 : wrapperBounds.left}
$bottom={bottomGap}
$bgColor={bgColor}
$paddingX={fullWidth ? wrapperBounds.left : paddingX}
>
{children}
</StyledStickyInner>
</div>
);
}
11 changes: 10 additions & 1 deletion entrypoints/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
magenta,
gold,
} from '@ant-design/colors';
import type { LanguageTypes, SettingsProps, TabEvents } from '~/entrypoints/types';
import type { LanguageTypes, SettingsProps, TabEvents, SyncType } from '~/entrypoints/types';

export const GITHUB_URL = 'https://github.com/web-dahuyou/NiceTab';

Expand Down Expand Up @@ -91,6 +91,15 @@ export const IS_GROUP_SUPPORT = 'group' in browser.tabs && 'tabGroups' in brows
export const SUCCESS_KEY = 'success';
export const FAILED_KEY = 'failed';

// 同步方式枚举
export const syncTypeMap: Record<string, SyncType> = {
AUTO: 'auto',
MANUAL_PULL_MERGE: 'manual-pull-merge',
MANUAL_PULL_FORCE: 'manual-pull-force',
MANUAL_PUSH_MERGE: 'manual-push-merge',
MANUAL_PUSH_FORCE: 'manual-push-force',
};

export default {
ENUM_COLORS,
THEME_COLORS,
Expand Down
1 change: 1 addition & 0 deletions entrypoints/common/locale/modules/home/enUS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
'home.recoverAll': 'Recover All',
'home.emptyTip': 'No Data',
'home.searchTagAndGroup': 'Search Tag/Group',
'home.moveAllGroupTo': 'Move All Group To ...',
'home.createTabGroup': 'Create Tab Group',
'home.helpInfo': 'Help Info',
'home.removeTitle': 'Remove Reminder',
Expand Down
1 change: 1 addition & 0 deletions entrypoints/common/locale/modules/home/zhCN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
'home.recoverAll': '全部还原',
'home.emptyTip': '暂无数据',
'home.searchTagAndGroup': '搜索分类/标签组',
'home.moveAllGroupTo': '移动所有标签组到...',
'home.createTabGroup': '创建标签组',
'home.helpInfo': '帮助信息',
'home.removeTitle': '删除提醒',
Expand Down
2 changes: 1 addition & 1 deletion entrypoints/common/locale/modules/settings/enUS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default {
'settings.closeTabsAfterSendTabs': 'When sending tabs - whether to automatically close the tabs ?',
'settings.closeTabsAfterSendTabs.yes': 'Automatically close',
'settings.closeTabsAfterSendTabs.no': 'Do not',
'settings.deleteAfterRestore': 'When restoring tabs - whether to remove the tabs ?',
'settings.deleteAfterRestore': 'When opening tabs or tab groups - whether to remove the tabs ?',
'settings.deleteAfterRestore.yes': 'Remove (pinned tabs remain)',
'settings.deleteAfterRestore.no': 'All remain (recommended)',
'settings.deleteUnlockedEmptyGroup': 'When clearing tabs - whether to remove the empty group ?',
Expand Down
2 changes: 1 addition & 1 deletion entrypoints/common/locale/modules/settings/zhCN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default {
'settings.closeTabsAfterSendTabs': '发送标签页时-是否自动关闭标签页{mark}',
'settings.closeTabsAfterSendTabs.yes': '自动关闭标签页',
'settings.closeTabsAfterSendTabs.no': '不要自动关闭标签页',
'settings.deleteAfterRestore': '恢复标签页/标签组时-是否自动删除标签页{mark}',
'settings.deleteAfterRestore': '打开标签页/标签组时-是否自动删除标签页{mark}',
'settings.deleteAfterRestore.yes': '从NiceTab列表中删除(仍保留固定标签页)',
'settings.deleteAfterRestore.no': '保留在NiceTab列表中(推荐)',
'settings.deleteUnlockedEmptyGroup': '清空标签页时-是否自动删除该标签组{mark}',
Expand Down
4 changes: 4 additions & 0 deletions entrypoints/common/locale/modules/sync/enUS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export default {
'sync.noGithubToken': 'No github access token',
'sync.noGiteeToken': 'No gitee access token',
'sync.syncType.auto': 'auto',
'sync.syncType.manualPullMerge': 'menual pull (merge)',
'sync.syncType.manualPullForce': 'menual pull (overwrite)',
'sync.syncType.manualPushMerge': 'menual push (merge)',
'sync.syncType.manualPushForce': 'menual push (force)',
'sync.lastSyncTime': 'Last Sync Time',
Expand All @@ -15,6 +17,8 @@ export default {
'sync.syncType': 'Sync Type',
'sync.syncResult': 'Sync Result',
'sync.tip.auto': 'Auto Sync by mergeing push type',
'sync.tip.manualPullMerge': 'ull remote data, merge to local data.',
'sync.tip.manualPullForce': 'Pull remote data, force overwrite local data.',
'sync.tip.manualPushMerge': 'Pull remote data, merge to local data, and then push to remote.',
'sync.tip.manualPushForce': 'Push local data to remote (force overwrite).',
'sync.tip.tokenChange': 'Change the access token will clear the local {type} sync history',
Expand Down
4 changes: 4 additions & 0 deletions entrypoints/common/locale/modules/sync/zhCN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export default {
'sync.noGithubToken': '未设置 github access token',
'sync.noGiteeToken': '未设置 gitee access token',
'sync.syncType.auto': '自动同步',
'sync.syncType.manualPullMerge': '手动拉取-合并到本地',
'sync.syncType.manualPullForce': '手动拉取-覆盖本地数据',
'sync.syncType.manualPushMerge': '手动同步-合并推送',
'sync.syncType.manualPushForce': '手动同步-覆盖推送',
'sync.lastSyncTime': '上次同步时间',
Expand All @@ -15,6 +17,8 @@ export default {
'sync.syncType': '同步方式',
'sync.syncResult': '同步结果',
'sync.tip.auto': '以合并推送的方式按时自动同步',
'sync.tip.manualPullMerge': '拉取远程数据,合并到本地',
'sync.tip.manualPullForce': '拉取远程数据,覆盖本地数据',
'sync.tip.manualPushMerge': '拉取远程数据,与本地合并,然后推送',
'sync.tip.manualPushForce': '推送本地数据到远程(强制覆盖)',
'sync.tip.tokenChange': '修改access token会清空本地{type}的同步历史记录',
Expand Down
16 changes: 12 additions & 4 deletions entrypoints/common/storage/syncUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
fetchApi,
getLocaleMessages,
} from '~/entrypoints/common/utils';
import { SUCCESS_KEY, FAILED_KEY } from '~/entrypoints/common/constants';
import { SUCCESS_KEY, FAILED_KEY, syncTypeMap } from '~/entrypoints/common/constants';
import Store from './instanceStore';

type GistFilesProps = {
Expand Down Expand Up @@ -231,10 +231,10 @@ export default class SyncUtils {
async handleBySyncType(
remoteType: SyncRemoteType,
syncType: SyncType,
gistData?: GistResponseItemProps
gistData: GistResponseItemProps
) {
let result: GistResponseItemProps = {} as GistResponseItemProps;
if (syncType === 'manual-push-force') {
if (syncType === syncTypeMap.MANUAL_PUSH_FORCE) {
result = await this.updateGist(remoteType);
} else {
try {
Expand All @@ -255,9 +255,17 @@ export default class SyncUtils {
} else {
fileContent = fileInfo?.content || '';
}

if (syncType === syncTypeMap.MANUAL_PULL_FORCE) {
await Store.tabListUtils.clearAll();
}
const tagList = extContentImporter.niceTab(fileContent || '');
await Store.tabListUtils.importTags(tagList, 'merge');
result = await this.updateGist(remoteType);
if (syncType === syncTypeMap.MANUAL_PUSH_MERGE) {
result = await this.updateGist(remoteType);
} else {
result = { id: gistData?.id } as GistResponseItemProps;
}
} catch (e) {
console.log(e);
}
Expand Down
56 changes: 56 additions & 0 deletions entrypoints/common/storage/tabListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,62 @@ export default class TabListUtils {
await this.setTagList(tagList);
return { targetGroupId: undefined };
}
// 当前分类中所有标签组移动到(穿越)
async allTabGroupsMoveThrough({
sourceTagId,
targetTagId,
autoMerge = false,
}: {
sourceTagId: Key;
targetTagId: Key;
autoMerge?: boolean;
}) {
const tagList = await this.getTagList();
let isSourceFound = false,
isTargetFound = false,
sourceTagIndex = 0,
targetTagIndex = 0;
for (let tIndex = 0; tIndex < tagList.length; tIndex++) {
const tag = tagList[tIndex];
if (tag.tagId === targetTagId) {
isTargetFound = true;
targetTagIndex = tIndex;
}
if (tag.tagId === sourceTagId) {
isSourceFound = true;
sourceTagIndex = tIndex;
}

if (isSourceFound && isTargetFound) break;
}

if (isSourceFound && isTargetFound) {
const sourceTag = tagList?.[sourceTagIndex];
const allSourceGroups = sourceTag?.groupList?.splice(0);

const targetTag = tagList?.[targetTagIndex];

// 如果开启自动合并,则同名标签组会自动合并
if (autoMerge) {
targetTag.groupList = mergeGroupsAndTabs({
targetList: targetTag.groupList || [],
insertList: allSourceGroups,
exceptValue: UNNAMED_GROUP,
})

await this.setTagList(tagList);
} else {
// 穿越操作改为往队尾插入
targetTag.groupList = [...targetTag?.groupList, ...allSourceGroups];
await this.setTagList(tagList);
}

return { targetTagId: targetTag.tagId };
}

await this.setTagList(tagList);
return { targetTagId: undefined };
}
// 标签组排序
async groupListSort(sortType: string, tagId: Key) {
const tagList = await this.getTagList();
Expand Down
2 changes: 1 addition & 1 deletion entrypoints/options/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ function AppLayout() {
</div>

{/* 回到顶部 */}
<FloatButton.Group shape="circle" style={{ right: 30 }}>
<FloatButton.Group shape="circle" style={{ right: 30, bottom: 70 }}>
{/* BackTop组件自带的 tooltip 在点击按钮时会闪 */}
<span title={$fmt('common.backToTop')}>
<FloatButton.BackTop duration={100} visibilityHeight={400} />
Expand Down
11 changes: 10 additions & 1 deletion entrypoints/options/home/Home.styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const StyledSidebarWrapper = styled.div<{
position: fixed;
top: 100px;
transition: transform 0.2s ease-in-out;
border-right: 1px solid rgba(5, 5, 5, 0.06);
&.collapsed {
.sidebar-inner-content {
Expand Down Expand Up @@ -103,7 +104,7 @@ export const StyledListWrapper = styled.div<{
.content {
padding-left: 40px;
border-left: 1px solid rgba(5, 5, 5, 0.06);
// border-left: 1px solid rgba(5, 5, 5, 0.06);
}
`;

Expand Down Expand Up @@ -134,6 +135,14 @@ export const StyledTreeNodeItem = styled.div`
}
`;

export const StyledFooterWrapper = styled.div<{ $paddingLeft?: number }>`
display: flex;
align-items: center;
height: 60px;
padding-left: ${(props) => props.$paddingLeft || 0}px;
transition: padding 0.2s ease-in-out;
`;

export default {
name: 'option-home-styled',
};
Loading

0 comments on commit b8ffde7

Please sign in to comment.