[ENG-1592] Correctly assign tab titles on desktop (#2030)

* correctly set tab titles

* use selectedTabIndex

* empty tabId

* prettier
This commit is contained in:
Brendan Allan 2024-02-01 23:40:38 +08:00 committed by GitHub
parent 8cbd38d6f9
commit 74d97d4957
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 36 additions and 31 deletions

View file

@ -80,18 +80,22 @@ const routes = createRoutes(platform, cache);
function AppInner() {
const [tabs, setTabs] = useState(() => [createTab()]);
const [tabIndex, setTabIndex] = useState(0);
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
const selectedTab = tabs[selectedTabIndex]!;
function createTab() {
const history = createMemoryHistory();
const router = createMemoryRouterWithHistory({ routes, history });
const id = Math.random().toString();
const dispose = router.subscribe((event) => {
// we don't care about non-idle events as those are artifacts of form mutations + suspense
if (event.navigation.state !== 'idle') return;
setTabs((routers) => {
const index = routers.findIndex((r) => r.router === router);
const index = routers.findIndex((r) => r.id === id);
if (index === -1) return routers;
const routerAtIndex = routers[index]!;
@ -105,12 +109,12 @@ function AppInner() {
: Math.max(routerAtIndex.maxIndex, history.index)
};
return [...routers];
return [...routers]
});
});
return {
id: Math.random().toString(),
id,
router,
history,
dispose,
@ -121,8 +125,6 @@ function AppInner() {
};
}
const tab = tabs[tabIndex]!;
const createTabPromise = useRef(Promise.resolve());
const ref = useRef<HTMLDivElement>(null);
@ -131,38 +133,37 @@ function AppInner() {
const div = ref.current;
if (!div) return;
div.appendChild(tab.element);
div.appendChild(selectedTab.element);
return () => {
while (div.firstChild) {
div.removeChild(div.firstChild);
}
};
}, [tab.element]);
}, [selectedTab.element]);
return (
<RouteTitleContext.Provider
value={useMemo(
() => ({
setTitle(title) {
setTabs((oldTabs) => {
const tabs = [...oldTabs];
const tab = tabs[tabIndex];
if (!tab) return tabs;
setTitle(id, title) {
setTabs((tabs) => {
const tabIndex = tabs.findIndex(t => t.id === id);
if (tabIndex === -1) return tabs;
tabs[tabIndex] = { ...tab, title };
tabs[tabIndex] = { ...tabs[tabIndex]!, title };
return tabs;
return [...tabs];
});
}
}),
[tabIndex]
[]
)}
>
<TabsContext.Provider
value={{
tabIndex,
setTabIndex,
tabIndex: selectedTabIndex,
setTabIndex: setSelectedTabIndex,
tabs: tabs.map(({ router, title }) => ({ router, title })),
createTab() {
createTabPromise.current = createTabPromise.current.then(
@ -170,9 +171,10 @@ function AppInner() {
new Promise((res) => {
startTransition(() => {
setTabs((tabs) => {
const newTabs = [...tabs, createTab()];
const newTab = createTab();
const newTabs = [...tabs, newTab];
setTabIndex(newTabs.length - 1);
setSelectedTabIndex(newTabs.length - 1);
return newTabs;
});
@ -192,7 +194,7 @@ function AppInner() {
tabs.splice(index, 1);
setTabIndex(Math.min(tabIndex, tabs.length - 1));
setSelectedTabIndex(Math.min(selectedTabIndex, tabs.length - 1));
return [...tabs];
});
@ -201,15 +203,16 @@ function AppInner() {
}}
>
<SpacedriveInterfaceRoot>
{tabs.map((tab) =>
{tabs.map((tab, index) =>
createPortal(
<SpacedriveRouterProvider
key={tab.id}
routing={{
routes,
visible: tabIndex === tabs.indexOf(tab),
visible: selectedTabIndex === tabs.indexOf(tab),
router: tab.router,
currentIndex: tab.currentIndex,
tabId: tab.id,
maxIndex: tab.maxIndex
}}
/>,

View file

@ -112,6 +112,7 @@ function App() {
<SpacedriveRouterProvider
routing={{
...router,
tabId: '',
routes,
visible: true
}}

View file

@ -1,8 +1,4 @@
use crate::{
api::CoreEvent,
object::{media::thumbnail::get_indexed_thumbnail_path, orphan_remover::OrphanRemoverActor},
sync, Node,
};
use crate::{api::CoreEvent, object::media::thumbnail::get_indexed_thumbnail_path, sync, Node};
use sd_file_path_helper::{file_path_to_full_path, IsolatedFilePathData};
use sd_p2p::spacetunnel::Identity;

View file

@ -6,6 +6,7 @@ import { createRoutes } from './app';
export const RoutingContext = createContext<{
visible: boolean;
currentIndex: number;
tabId: string;
maxIndex: number;
routes: ReturnType<typeof createRoutes>;
} | null>(null);

View file

@ -1,17 +1,19 @@
import { createContext, useContext, useLayoutEffect } from 'react';
import { useRoutingContext } from '~/RoutingContext';
export function useRouteTitle(title: string) {
const routingCtx = useRoutingContext();
const ctx = useContext(RouteTitleContext);
// layout effect avoids 'New Tab' showing up briefly
useLayoutEffect(() => {
document.title = title;
if (ctx) ctx.setTitle(title);
}, [title, ctx]);
if (ctx) ctx.setTitle(routingCtx.tabId, title);
}, [routingCtx.tabId, title, ctx]);
return title;
}
export const RouteTitleContext = createContext<{
setTitle: (title: string) => void;
setTitle: (id: string, title: string) => void;
} | null>(null);

View file

@ -53,6 +53,7 @@ export function SpacedriveRouterProvider(props: {
visible: boolean;
router: Router;
currentIndex: number;
tabId: string;
maxIndex: number;
};
}) {
@ -63,6 +64,7 @@ export function SpacedriveRouterProvider(props: {
routes: props.routing.routes,
visible: props.routing.visible,
currentIndex: props.routing.currentIndex,
tabId: props.routing.tabId,
maxIndex: props.routing.maxIndex
}}
>