mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: back and forward buttons nav scroll fix
This commit is contained in:
parent
da8c39d0b6
commit
268b6ce926
@ -9,7 +9,7 @@
|
|||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx .",
|
"test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx .",
|
||||||
"test:errors": "eslint --quiet --ext .js,.ts,.tsx .",
|
"test:errors": "tsc --noEmit",
|
||||||
"test:prettier": "yarn prettier --list-different src",
|
"test:prettier": "yarn prettier --list-different src",
|
||||||
"tauri:clean": "cargo make --cwd .. tauri_clean",
|
"tauri:clean": "cargo make --cwd .. tauri_clean",
|
||||||
"tauri:dev": "tauri dev",
|
"tauri:dev": "tauri dev",
|
||||||
|
@ -2,44 +2,29 @@ import { ShowMenuSvg } from '../../_shared/svg/ShowMenuSvg';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useAppSelector } from '../../../stores/store';
|
import { useAppSelector } from '../../../stores/store';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
import { activePageIdActions } from '../../../stores/reducers/activePageId/slice';
|
|
||||||
|
|
||||||
export const Breadcrumbs = ({ menuHidden, onShowMenuClick }: { menuHidden: boolean; onShowMenuClick: () => void }) => {
|
export const Breadcrumbs = ({ menuHidden, onShowMenuClick }: { menuHidden: boolean; onShowMenuClick: () => void }) => {
|
||||||
const dispatch = useDispatch();
|
|
||||||
const [folderName, setFolderName] = useState('');
|
const [folderName, setFolderName] = useState('');
|
||||||
const [pageName, setPageName] = useState('');
|
const [pageName, setPageName] = useState('');
|
||||||
const activePageId = useAppSelector((state) => state.activePageId);
|
const [activePageId, setActivePageId] = useState<string>('');
|
||||||
|
const currentLocation = useLocation();
|
||||||
const pagesStore = useAppSelector((state) => state.pages);
|
const pagesStore = useAppSelector((state) => state.pages);
|
||||||
const foldersStore = useAppSelector((state) => state.folders);
|
const foldersStore = useAppSelector((state) => state.folders);
|
||||||
const [pageHistory, setPageHistory] = useState<string[]>([]);
|
|
||||||
const [historyIndex, setHistoryIndex] = useState(0);
|
useEffect(() => {
|
||||||
|
const { pathname } = currentLocation;
|
||||||
|
const parts = pathname.split('/');
|
||||||
|
const pageId = parts[parts.length - 1];
|
||||||
|
setActivePageId(pageId);
|
||||||
|
}, [currentLocation]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const page = pagesStore.find((p) => p.id === activePageId);
|
const page = pagesStore.find((p) => p.id === activePageId);
|
||||||
const folder = foldersStore.find((f) => f.id === page?.folderId);
|
const folder = foldersStore.find((f) => f.id === page?.folderId);
|
||||||
setFolderName(folder?.title || '');
|
setFolderName(folder?.title || '');
|
||||||
setPageName(page?.title || '');
|
setPageName(page?.title || '');
|
||||||
setPageHistory([...pageHistory, activePageId]);
|
|
||||||
}, [pagesStore, foldersStore, activePageId]);
|
}, [pagesStore, foldersStore, activePageId]);
|
||||||
|
|
||||||
const currentLocation = useLocation();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// if there is no active page, we should try to get the page id from the url
|
|
||||||
if (!activePageId?.length) {
|
|
||||||
const { pathname } = currentLocation;
|
|
||||||
const parts = pathname.split('/');
|
|
||||||
// `/"page"/{pageType}/{pageId}`
|
|
||||||
if (parts.length !== 4) return;
|
|
||||||
|
|
||||||
const pageId = parts[parts.length - 1];
|
|
||||||
// const pageType = parts[parts.length - 2];
|
|
||||||
|
|
||||||
dispatch(activePageIdActions.setActivePageId(pageId));
|
|
||||||
}
|
|
||||||
}, [activePageId, currentLocation]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'flex items-center'}>
|
<div className={'flex items-center'}>
|
||||||
<div className={'mr-4 flex items-center'}>
|
<div className={'mr-4 flex items-center'}>
|
||||||
@ -50,10 +35,10 @@ export const Breadcrumbs = ({ menuHidden, onShowMenuClick }: { menuHidden: boole
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<button className={'p-1'} onClick={() => history.back()}>
|
<button className={'p-1'} onClick={() => history.back()}>
|
||||||
<img src={'/images/home/arrow_left.svg'} />
|
<img src={'/images/home/arrow_left.svg'} alt={''} />
|
||||||
</button>
|
</button>
|
||||||
<button className={'p-1'} onClick={() => history.forward()}>
|
<button className={'p-1'} onClick={() => history.forward()}>
|
||||||
<img src={'/images/home/arrow_right.svg'} />
|
<img src={'/images/home/arrow_right.svg'} alt={''} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className={'mr-8 flex items-center gap-4'}>
|
<div className={'mr-8 flex items-center gap-4'}>
|
||||||
|
@ -7,14 +7,12 @@ import { AppBackendService } from '../../../stores/effects/folder/app/app_bd_svc
|
|||||||
import { WorkspaceBackendService } from '../../../stores/effects/folder/workspace/workspace_bd_svc';
|
import { WorkspaceBackendService } from '../../../stores/effects/folder/workspace/workspace_bd_svc';
|
||||||
import { useError } from '../../error/Error.hooks';
|
import { useError } from '../../error/Error.hooks';
|
||||||
import { AppObserver } from '../../../stores/effects/folder/app/app_observer';
|
import { AppObserver } from '../../../stores/effects/folder/app/app_observer';
|
||||||
import { activePageIdActions } from '../../../stores/reducers/activePageId/slice';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { INITIAL_FOLDER_HEIGHT, PAGE_ITEM_HEIGHT } from '../../_shared/constants';
|
import { INITIAL_FOLDER_HEIGHT, PAGE_ITEM_HEIGHT } from '../../_shared/constants';
|
||||||
|
|
||||||
export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
||||||
const appDispatch = useAppDispatch();
|
const appDispatch = useAppDispatch();
|
||||||
const workspace = useAppSelector((state) => state.workspace);
|
const workspace = useAppSelector((state) => state.workspace);
|
||||||
const foldersStore = useAppSelector((state) => state.folders);
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -145,8 +143,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
|||||||
|
|
||||||
setShowPages(true);
|
setShowPages(true);
|
||||||
|
|
||||||
appDispatch(activePageIdActions.setActivePageId(newView.id));
|
|
||||||
|
|
||||||
navigate(`/page/document/${newView.id}`);
|
navigate(`/page/document/${newView.id}`);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error.showError(e?.message);
|
error.showError(e?.message);
|
||||||
@ -172,8 +168,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
appDispatch(activePageIdActions.setActivePageId(newView.id));
|
|
||||||
|
|
||||||
navigate(`/page/board/${newView.id}`);
|
navigate(`/page/board/${newView.id}`);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error.showError(e?.message);
|
error.showError(e?.message);
|
||||||
@ -199,8 +193,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
appDispatch(activePageIdActions.setActivePageId(newView.id));
|
|
||||||
|
|
||||||
navigate(`/page/grid/${newView.id}`);
|
navigate(`/page/grid/${newView.id}`);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
error.showError(e?.message);
|
error.showError(e?.message);
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import { useAppDispatch, useAppSelector } from '../../../stores/store';
|
import { useAppSelector } from '../../../stores/store';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { IPage } from '../../../stores/reducers/pages/slice';
|
import { IPage } from '../../../stores/reducers/pages/slice';
|
||||||
import { ViewLayoutTypePB } from '../../../../services/backend';
|
import { ViewLayoutTypePB } from '../../../../services/backend';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { activePageIdActions } from '../../../stores/reducers/activePageId/slice';
|
|
||||||
|
|
||||||
export const useNavigationPanelHooks = function () {
|
export const useNavigationPanelHooks = function () {
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const folders = useAppSelector((state) => state.folders);
|
const folders = useAppSelector((state) => state.folders);
|
||||||
const pages = useAppSelector((state) => state.pages);
|
const pages = useAppSelector((state) => state.pages);
|
||||||
const width = useAppSelector((state) => state.navigationWidth);
|
const width = useAppSelector((state) => state.navigationWidth);
|
||||||
@ -37,8 +35,6 @@ export const useNavigationPanelHooks = function () {
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
dispatch(activePageIdActions.setActivePageId(page.id));
|
|
||||||
|
|
||||||
navigate(`/page/${pageTypeRoute}/${page.id}`);
|
navigate(`/page/${pageTypeRoute}/${page.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@ import { NewFolderButton } from './NewFolderButton';
|
|||||||
import { NavigationResizer } from './NavigationResizer';
|
import { NavigationResizer } from './NavigationResizer';
|
||||||
import { IFolder } from '../../../stores/reducers/folders/slice';
|
import { IFolder } from '../../../stores/reducers/folders/slice';
|
||||||
import { IPage } from '../../../stores/reducers/pages/slice';
|
import { IPage } from '../../../stores/reducers/pages/slice';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
import { useAppSelector } from '../../../stores/store';
|
import { useAppSelector } from '../../../stores/store';
|
||||||
import {
|
import {
|
||||||
ANIMATION_DURATION,
|
ANIMATION_DURATION,
|
||||||
@ -34,12 +33,19 @@ export const NavigationPanel = ({
|
|||||||
onPageClick: (page: IPage) => void;
|
onPageClick: (page: IPage) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const el = useRef<HTMLDivElement>(null);
|
const el = useRef<HTMLDivElement>(null);
|
||||||
const dispatch = useDispatch();
|
|
||||||
const foldersStore = useAppSelector((state) => state.folders);
|
const foldersStore = useAppSelector((state) => state.folders);
|
||||||
const pagesStore = useAppSelector((state) => state.pages);
|
const pagesStore = useAppSelector((state) => state.pages);
|
||||||
const activePageId = useAppSelector((state) => state.activePageId);
|
const [activePageId, setActivePageId] = useState<string>('');
|
||||||
|
const currentLocation = useLocation();
|
||||||
const [maxHeight, setMaxHeight] = useState(0);
|
const [maxHeight, setMaxHeight] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { pathname } = currentLocation;
|
||||||
|
const parts = pathname.split('/');
|
||||||
|
const pageId = parts[parts.length - 1];
|
||||||
|
setActivePageId(pageId);
|
||||||
|
}, [currentLocation]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!el.current) return;
|
if (!el.current) return;
|
||||||
@ -70,7 +76,7 @@ export const NavigationPanel = ({
|
|||||||
const elHeight = el.current.getBoundingClientRect().height;
|
const elHeight = el.current.getBoundingClientRect().height;
|
||||||
const scrollTop = el.current.scrollTop;
|
const scrollTop = el.current.scrollTop;
|
||||||
|
|
||||||
if (scrollTop + elHeight < height) {
|
if (scrollTop + elHeight < height || scrollTop > height) {
|
||||||
el.current.scrollTo({ top: height - elHeight, behavior: 'smooth' });
|
el.current.scrollTo({ top: height - elHeight, behavior: 'smooth' });
|
||||||
}
|
}
|
||||||
}, ANIMATION_DURATION);
|
}, ANIMATION_DURATION);
|
||||||
|
@ -1,18 +1,27 @@
|
|||||||
import { IPage, pagesActions } from '../../../stores/reducers/pages/slice';
|
import { IPage, pagesActions } from '../../../stores/reducers/pages/slice';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../stores/store';
|
import { useAppDispatch } from '../../../stores/store';
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { nanoid } from 'nanoid';
|
import { nanoid } from 'nanoid';
|
||||||
import { ViewBackendService } from '../../../stores/effects/folder/view/view_bd_svc';
|
import { ViewBackendService } from '../../../stores/effects/folder/view/view_bd_svc';
|
||||||
import { useError } from '../../error/Error.hooks';
|
import { useError } from '../../error/Error.hooks';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
export const usePageEvents = (page: IPage) => {
|
export const usePageEvents = (page: IPage) => {
|
||||||
const appDispatch = useAppDispatch();
|
const appDispatch = useAppDispatch();
|
||||||
const [showPageOptions, setShowPageOptions] = useState(false);
|
const [showPageOptions, setShowPageOptions] = useState(false);
|
||||||
const [showRenamePopup, setShowRenamePopup] = useState(false);
|
const [showRenamePopup, setShowRenamePopup] = useState(false);
|
||||||
const activePageId = useAppSelector((state) => state.activePageId);
|
const [activePageId, setActivePageId] = useState<string>('');
|
||||||
|
const currentLocation = useLocation();
|
||||||
const viewBackendService: ViewBackendService = new ViewBackendService(page.id);
|
const viewBackendService: ViewBackendService = new ViewBackendService(page.id);
|
||||||
const error = useError();
|
const error = useError();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const { pathname } = currentLocation;
|
||||||
|
const parts = pathname.split('/');
|
||||||
|
const pageId = parts[parts.length - 1];
|
||||||
|
setActivePageId(pageId);
|
||||||
|
}, [currentLocation]);
|
||||||
|
|
||||||
const onPageOptionsClick = () => {
|
const onPageOptionsClick = () => {
|
||||||
setShowPageOptions(!showPageOptions);
|
setShowPageOptions(!showPageOptions);
|
||||||
};
|
};
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
||||||
export const activePageIdSlice = createSlice({
|
|
||||||
name: 'activePageId',
|
|
||||||
initialState: '',
|
|
||||||
reducers: {
|
|
||||||
setActivePageId(state, action: PayloadAction<string>) {
|
|
||||||
return action.payload;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const activePageIdActions = activePageIdSlice.actions;
|
|
@ -16,7 +16,6 @@ import { workspaceSlice } from './reducers/workspace/slice';
|
|||||||
import { databaseSlice } from './reducers/database/slice';
|
import { databaseSlice } from './reducers/database/slice';
|
||||||
import { boardSlice } from './reducers/board/slice';
|
import { boardSlice } from './reducers/board/slice';
|
||||||
import { errorSlice } from './reducers/error/slice';
|
import { errorSlice } from './reducers/error/slice';
|
||||||
import { activePageIdSlice } from './reducers/activePageId/slice';
|
|
||||||
|
|
||||||
const listenerMiddlewareInstance = createListenerMiddleware({
|
const listenerMiddlewareInstance = createListenerMiddleware({
|
||||||
onError: () => console.error,
|
onError: () => console.error,
|
||||||
@ -26,7 +25,6 @@ const store = configureStore({
|
|||||||
reducer: {
|
reducer: {
|
||||||
[foldersSlice.name]: foldersSlice.reducer,
|
[foldersSlice.name]: foldersSlice.reducer,
|
||||||
[pagesSlice.name]: pagesSlice.reducer,
|
[pagesSlice.name]: pagesSlice.reducer,
|
||||||
[activePageIdSlice.name]: activePageIdSlice.reducer,
|
|
||||||
[navigationWidthSlice.name]: navigationWidthSlice.reducer,
|
[navigationWidthSlice.name]: navigationWidthSlice.reducer,
|
||||||
[currentUserSlice.name]: currentUserSlice.reducer,
|
[currentUserSlice.name]: currentUserSlice.reducer,
|
||||||
[gridSlice.name]: gridSlice.reducer,
|
[gridSlice.name]: gridSlice.reducer,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user