/** * SettingsPage - Settings page component * Platform default: lists registered fragment routes under the settings base path * and mounts each with {@code settingsFragmentPath} so fragments can resolve their own meta. */ import React, { useMemo } from 'react'; import { Page } from '../components/Page.jsx'; import { YStack, Input, Text } from 'tamagui'; import { useRouter, useRoute } from '../components/Router.jsx'; import { getRootItem } from '../../platform/menu.js'; import { securityService, useSecurityState } from '../../security/runtime/security-service.js'; export function SettingsPage() { const router = useRouter(); const route = useRoute(); const securityState = useSecurityState(); const [searchQuery, setSearchQuery] = React.useState(''); const basePath = useMemo(() => { if (route.path) { const currentPath = route.fragment_path || route.path; const segments = currentPath.split('/').filter((s) => s.length > 0); return segments.length > 0 ? `/${segments[0]}` : '/settings'; } return '/settings'; }, [route.path, route.fragment_path]); const childRoutes = useMemo(() => { const allRoutes = router.getRoutes(); const settingsRoot = getRootItem('settings'); const settingsItems = settingsRoot ? Array.from(settingsRoot.items.values()) : []; const security = { ...securityState, isPermitted: (rights, resourcePath, options = {}) => securityService.isPermitted(rights, resourcePath, options) }; const routes = []; for (const [path, routeData] of allRoutes.entries()) { if (path.startsWith(`${basePath}/`) && path !== basePath) { if (routeData.is_fragment) { const matchingMenuItem = settingsItems.find((item) => item.invoke_target === path); if (matchingMenuItem && !matchingMenuItem.isRenderable(security)) { continue; } routes.push({ path, component: routeData.component, options: routeData.options || {} }); } } } routes.sort((a, b) => a.path.localeCompare(b.path)); return routes; }, [router, basePath, router.currentRoute, securityState]); const filteredRoutes = useMemo(() => { if (!searchQuery.trim()) { return childRoutes; } const query = searchQuery.toLowerCase(); return childRoutes.filter((r) => { const segments = r.path.split('/').filter((s) => s.length > 0); const routeName = segments[segments.length - 1] || ''; return routeName.toLowerCase().includes(query); }); }, [childRoutes, searchQuery]); return ( {filteredRoutes.length > 0 ? ( filteredRoutes.map((routeItem) => { const RouteComponent = routeItem.component; return ( ); }) ) : ( {searchQuery.trim() ? 'No settings found matching your search.' : 'No settings available.'} )} ); } export default SettingsPage;