@@ -34,7 +38,7 @@ function Layout({ children }: { children: ReactNode }) {
style={{
height: 'calc(100vh - 64px - 48px)',
}}
- className={'appflowy-layout overflow-y-auto overflow-x-hidden'}
+ className={'appflowy-layout appflowy-scroll-container select-none overflow-y-auto overflow-x-hidden'}
>
{children}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/BreadCrumb.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/BreadCrumb.tsx
index 986ba9337d..8dc6ec6617 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/BreadCrumb.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/bread_crumb/BreadCrumb.tsx
@@ -25,7 +25,7 @@ function Breadcrumb() {
if (!currentPage) {
if (isTrash) {
- return
{t('trash.text')};
+ return
{t('trash.text')};
}
return null;
@@ -36,7 +36,7 @@ function Breadcrumb() {
{parentPages?.map((page: Page) => (
{
@@ -48,10 +48,11 @@ function Breadcrumb() {
{page.name || t('document.title.placeholder')}
))}
-
- {getPageIcon(currentPage)}
- {currentPage?.name || t('menuAppHeader.defaultNewPageName')}
-
+
+
+
{getPageIcon(currentPage)}
+ {currentPage.name || t('menuAppHeader.defaultNewPageName')}
+
);
}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/collapse_menu_button/CollapseMenuButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/collapse_menu_button/CollapseMenuButton.tsx
index e1b6f9e414..ca37d8aedd 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/collapse_menu_button/CollapseMenuButton.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/collapse_menu_button/CollapseMenuButton.tsx
@@ -42,8 +42,8 @@ function CollapseMenuButton() {
return (
-
- {isCollapsed ? : }
+
+
);
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/SideBar.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/SideBar.tsx
index cee598b66d..02e8bfb60b 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/SideBar.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/side_bar/SideBar.tsx
@@ -1,22 +1,50 @@
-import React from 'react';
-import { useAppSelector } from '$app/stores/store';
+import React, { useEffect, useRef } from 'react';
+import { useAppDispatch, useAppSelector } from '$app/stores/store';
import { AppflowyLogoDark } from '$app/components/_shared/svg/AppflowyLogoDark';
import { AppflowyLogoLight } from '$app/components/_shared/svg/AppflowyLogoLight';
import CollapseMenuButton from '$app/components/layout/collapse_menu_button/CollapseMenuButton';
import Resizer from '$app/components/layout/side_bar/Resizer';
import UserInfo from '$app/components/layout/side_bar/UserInfo';
import WorkspaceManager from '$app/components/layout/workspace_manager/WorkspaceManager';
+import { ThemeMode } from '$app_reducers/current-user/slice';
+import { sidebarActions } from '$app_reducers/sidebar/slice';
function SideBar() {
const { isCollapsed, width, isResizing } = useAppSelector((state) => state.sidebar);
- const isDark = useAppSelector((state) => state.currentUser?.userSetting?.isDark);
+ const dispatch = useAppDispatch();
+ const themeMode = useAppSelector((state) => state.currentUser?.userSetting?.themeMode);
+ const isDark =
+ themeMode === ThemeMode.Dark ||
+ (themeMode === ThemeMode.System && window.matchMedia('(prefers-color-scheme: dark)').matches);
+
+ const lastCollapsedRef = useRef(isCollapsed);
+
+ useEffect(() => {
+ const handleResize = () => {
+ const width = window.innerWidth;
+
+ if (width <= 800 && !isCollapsed) {
+ lastCollapsedRef.current = false;
+ dispatch(sidebarActions.setCollapse(true));
+ } else if (width > 800 && !lastCollapsedRef.current) {
+ lastCollapsedRef.current = true;
+ dispatch(sidebarActions.setCollapse(false));
+ }
+ };
+
+ window.addEventListener('resize', handleResize);
+
+ return () => {
+ window.removeEventListener('resize', handleResize);
+ };
+ }, [dispatch, isCollapsed]);
return (
<>
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/TopBar.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/TopBar.tsx
index d1b0fead63..fd7fe34ec7 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/TopBar.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/top_bar/TopBar.tsx
@@ -9,7 +9,7 @@ function TopBar() {
return (
{sidebarIsCollapsed && (
-
+
)}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.tsx
index 165a9ab1d1..0035ba702f 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.tsx
+++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/workspace_manager/Workspace.tsx
@@ -29,7 +29,9 @@ function Workspace({ workspace, opened }: { workspace: WorkspaceItem; opened: bo
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
- setShowPages(!showPages);
+ setShowPages((prev) => {
+ return !prev;
+ });
}}
onMouseEnter={() => {
setShowAdd(true);
@@ -59,7 +61,9 @@ function Workspace({ workspace, opened }: { workspace: WorkspaceItem; opened: bo
)}
- {showPages &&
}
+
+
+
>
);
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/sidebar/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/sidebar/slice.ts
index c8a9d864ac..fae1d59214 100644
--- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/sidebar/slice.ts
+++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/sidebar/slice.ts
@@ -19,6 +19,9 @@ export const sidebarSlice = createSlice({
toggleCollapse(state) {
state.isCollapsed = !state.isCollapsed;
},
+ setCollapse(state, action: PayloadAction
) {
+ state.isCollapsed = action.payload;
+ },
changeWidth(state, action: PayloadAction) {
state.width = action.payload;
},
diff --git a/frontend/appflowy_tauri/src/appflowy_app/utils/open_url.ts b/frontend/appflowy_tauri/src/appflowy_app/utils/open_url.ts
new file mode 100644
index 0000000000..f14b256517
--- /dev/null
+++ b/frontend/appflowy_tauri/src/appflowy_app/utils/open_url.ts
@@ -0,0 +1,18 @@
+import { open as openWindow } from '@tauri-apps/api/shell';
+
+export const pattern = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w.-]*)*\/?$/;
+
+export function openUrl(str: string) {
+ if (pattern.test(str)) {
+ const linkPrefix = ['http://', 'https://', 'file://', 'ftp://', 'ftps://', 'mailto:'];
+
+ if (linkPrefix.some((prefix) => str.startsWith(prefix))) {
+ void openWindow(str);
+ } else {
+ void openWindow('https://' + str);
+ }
+ } else {
+ // open google search
+ void openWindow('https://www.google.com/search?q=' + encodeURIComponent(str));
+ }
+}
diff --git a/frontend/appflowy_tauri/src/styles/template.css b/frontend/appflowy_tauri/src/styles/template.css
index f17595b74a..9d5d3efbc1 100644
--- a/frontend/appflowy_tauri/src/styles/template.css
+++ b/frontend/appflowy_tauri/src/styles/template.css
@@ -101,23 +101,20 @@ th {
}
.react-datepicker__day:hover {
border-radius: 100%;
- background: var(--fill-hover);
+ background: var(--fill-default);
+ color: var(--content-on-fill);
}
.react-datepicker__day--outside-month {
color: var(--text-caption);
}
.react-datepicker__day--in-range {
- background: var(--fill-active);
+ background: var(--fill-hover);
+ color: var(--content-on-fill);
}
-.react-datepicker__day--in-selecting-range {
- background: var(--fill-active) !important;
-}
-
-
.react-datepicker__day--today {
- border: 1px solid var(--fill-hover);
+ border: 1px solid var(--fill-default);
color: var(--text-title);
border-radius: 100%;
background: transparent;
@@ -126,7 +123,14 @@ th {
}
.react-datepicker__day--today:hover{
+ background: var(--fill-default);
+ color: var(--content-on-fill);
+}
+
+.react-datepicker__day--in-selecting-range, .react-datepicker__day--today.react-datepicker__day--in-range {
background: var(--fill-hover);
+ color: var(--content-on-fill);
+ border-color: transparent;
}
.react-datepicker__day--keyboard-selected {
@@ -135,14 +139,28 @@ th {
.react-datepicker__day--range-start, .react-datepicker__day--range-end, .react-datepicker__day--selected {
- background: var(--fill-default);
+ &.react-datepicker__day--today {
+ background: var(--fill-default);
+ color: var(--content-on-fill);
+ }
+ background: var(--fill-default) !important;
color: var(--content-on-fill);
}
.react-datepicker__day--range-start, .react-datepicker__day--range-end, .react-datepicker__day--selected:hover {
- background: var(--fill-hover);
+ background: var(--fill-default);
+ color: var(--content-on-fill);
}
.react-swipeable-view-container {
height: 100%;
}
+
+.grid-sticky-header::-webkit-scrollbar {
+ width: 0;
+ height: 0;
+}
+.grid-scroll-container::-webkit-scrollbar {
+ width: 0;
+ height: 0;
+}
diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json
index 74b8839b4a..f5258622be 100644
--- a/frontend/resources/translations/en.json
+++ b/frontend/resources/translations/en.json
@@ -240,7 +240,12 @@
"rename": "Rename",
"helpCenter": "Help Center",
"add": "Add",
- "yes": "Yes"
+ "yes": "Yes",
+ "Done": "Done",
+ "Cancel": "Cancel",
+ "clear": "Clear",
+ "remove": "Remove",
+ "dontRemove": "Don't remove"
},
"label": {
"welcome": "Welcome!",
@@ -605,7 +610,8 @@
"deleteFieldPromptMessage": "Are you sure? This property will be deleted",
"newColumn": "New Column",
"format": "Format",
- "reminderOnDateTooltip": "This cell has a scheduled reminder"
+ "reminderOnDateTooltip": "This cell has a scheduled reminder",
+ "optionAlreadyExist": "Option already exists"
},
"rowPage": {
"newField": "Add a new field",
@@ -683,7 +689,8 @@
"median": "Median",
"min": "Min",
"sum": "Sum"
- }
+ },
+ "removeSorting": "Would you like to remove sorting?"
},
"document": {
"menuName": "Document",