Format code

This commit is contained in:
Nicola Benaglia 2025-04-20 09:57:22 +02:00
parent fbf4207680
commit 88f4ce4e4d

View File

@ -1,205 +1,251 @@
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { useMemo } from 'react';
import { DndContext, closestCenter } from '@dnd-kit/core'; import { DndContext, closestCenter } from '@dnd-kit/core';
import { arrayMove, SortableContext, sortableKeyboardCoordinates, useSortable } from '@dnd-kit/sortable'; import {
import { KeyboardSensor, PointerSensor, TouchSensor, useSensor, useSensors } from '@dnd-kit/core'; arrayMove,
SortableContext,
sortableKeyboardCoordinates,
useSortable,
} from '@dnd-kit/sortable';
import {
KeyboardSensor,
PointerSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
import { CSS } from '@dnd-kit/utilities'; import { CSS } from '@dnd-kit/utilities';
import { Avatar, ButtonBase } from '@mui/material'; import { Avatar, ButtonBase } from '@mui/material';
import { AppCircle, AppCircleContainer, AppCircleLabel } from './Apps-styles'; import { AppCircle, AppCircleContainer, AppCircleLabel } from './Apps-styles';
import { getBaseApiReact, MyContext } from '../../App'; import { getBaseApiReact } from '../../App';
import { executeEvent } from '../../utils/events'; import { executeEvent } from '../../utils/events';
import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom } from '../../atoms/global'; import {
settingsLocalLastUpdatedAtom,
sortablePinnedAppsAtom,
} from '../../atoms/global';
import { useRecoilState, useSetRecoilState } from 'recoil'; import { useRecoilState, useSetRecoilState } from 'recoil';
import { saveToLocalStorage } from './AppsNavBar'; import { saveToLocalStorage } from './AppsNavBar';
import { ContextMenuPinnedApps } from '../ContextMenuPinnedApps'; import { ContextMenuPinnedApps } from '../ContextMenuPinnedApps';
import LockIcon from "@mui/icons-material/Lock"; import LockIcon from '@mui/icons-material/Lock';
import { useHandlePrivateApps } from './useHandlePrivateApps'; import { useHandlePrivateApps } from './useHandlePrivateApps';
const SortableItem = ({ id, name, app, isDesktop }) => { const SortableItem = ({ id, name, app, isDesktop }) => {
const {openApp} = useHandlePrivateApps() const { openApp } = useHandlePrivateApps();
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id }); const { attributes, listeners, setNodeRef, transform, transition } =
const style = { useSortable({ id });
transform: CSS.Transform.toString(transform),
transition,
padding: '10px',
border: '1px solid #ccc',
marginBottom: '5px',
borderRadius: '4px',
backgroundColor: '#f9f9f9',
cursor: 'grab',
color: 'black'
};
return ( const style = {
<ContextMenuPinnedApps app={app} isMine={!!app?.isMine}> backgroundColor: '#f9f9f9',
<ButtonBase border: '1px solid #ccc',
ref={setNodeRef} {...attributes} {...listeners} borderRadius: '4px',
sx={{ color: 'black',
width: "80px", cursor: 'grab',
transform: CSS.Transform.toString(transform), marginBottom: '5px',
transition, padding: '10px',
}} transform: CSS.Transform.toString(transform),
onClick={async ()=> { transition,
if(app?.isPrivate){ };
try {
await openApp(app?.privateAppProperties)
} catch (error) {
console.error(error)
}
} else { return (
executeEvent("addTab", { <ContextMenuPinnedApps app={app} isMine={!!app?.isMine}>
data: app <ButtonBase
}) ref={setNodeRef}
} {...attributes}
{...listeners}
}} sx={{
> width: '80px',
<AppCircleContainer sx={{ transform: CSS.Transform.toString(transform),
border: "none", transition,
gap: isDesktop ? '10px': '5px' }}
}}> onClick={async () => {
<AppCircle if (app?.isPrivate) {
sx={{ try {
border: "none", await openApp(app?.privateAppProperties);
}} } catch (error) {
> console.error(error);
{app?.isPrivate && !app?.privateAppProperties?.logo ? ( }
<LockIcon } else {
executeEvent('addTab', {
data: app,
});
}
}}
>
<AppCircleContainer
sx={{
border: 'none',
gap: isDesktop ? '10px' : '5px',
}}
>
<AppCircle
sx={{ sx={{
height: "42px", border: 'none',
width: "42px",
}} }}
/> >
) : ( {app?.isPrivate && !app?.privateAppProperties?.logo ? (
<Avatar <LockIcon
sx={{ sx={{
height: "42px", height: '42px',
width: "42px", width: '42px',
'& img': { }}
objectFit: 'fill', />
} ) : (
}} <Avatar
alt={app?.metadata?.title || app?.name} sx={{
src={ app?.privateAppProperties?.logo ? app?.privateAppProperties?.logo :`${getBaseApiReact()}/arbitrary/THUMBNAIL/${ height: '42px',
app?.name width: '42px',
}/qortal_avatar?async=true`} '& img': {
> objectFit: 'fill',
<img },
style={{ }}
width: "31px", alt={app?.metadata?.title || app?.name}
height: "auto", src={
}} app?.privateAppProperties?.logo
// src={LogoSelected} ? app?.privateAppProperties?.logo
alt="center-icon" : `${getBaseApiReact()}/arbitrary/THUMBNAIL/${
/> app?.name
</Avatar> }/qortal_avatar?async=true`
)} }
>
</AppCircle> <img
{app?.isPrivate ? ( style={{
<AppCircleLabel> width: '31px',
{`${app?.privateAppProperties?.appName || "Private"}`} height: 'auto',
</AppCircleLabel> }}
) : ( // src={LogoSelected}
<AppCircleLabel> alt="center-icon"
{app?.metadata?.title || app?.name} />
</AppCircleLabel> </Avatar>
)} )}
</AppCircle>
</AppCircleContainer> {app?.isPrivate ? (
</ButtonBase> <AppCircleLabel>
</ContextMenuPinnedApps> {`${app?.privateAppProperties?.appName || 'Private'}`}
); </AppCircleLabel>
) : (
<AppCircleLabel>{app?.metadata?.title || app?.name}</AppCircleLabel>
)}
</AppCircleContainer>
</ButtonBase>
</ContextMenuPinnedApps>
);
}; };
export const SortablePinnedApps = ({ isDesktop, myWebsite, myApp, availableQapps = [] }) => { export const SortablePinnedApps = ({
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom); isDesktop,
const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom); myWebsite,
myApp,
availableQapps = [],
}) => {
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
const setSettingsLocalLastUpdated = useSetRecoilState(
settingsLocalLastUpdatedAtom
);
const transformPinnedApps = useMemo(() => { const transformPinnedApps = useMemo(() => {
// Clone the existing pinned apps list
let pinned = [...pinnedApps];
// Clone the existing pinned apps list // Function to add or update `isMine` property
let pinned = [...pinnedApps]; const addOrUpdateIsMine = (pinnedList, appToCheck) => {
if (!appToCheck) return pinnedList;
// Function to add or update `isMine` property const existingIndex = pinnedList.findIndex(
const addOrUpdateIsMine = (pinnedList, appToCheck) => { (item) =>
if (!appToCheck) return pinnedList; item?.service === appToCheck?.service &&
item?.name === appToCheck?.name
);
const existingIndex = pinnedList.findIndex( if (existingIndex !== -1) {
(item) => item?.service === appToCheck?.service && item?.name === appToCheck?.name // If the app is already in the list, update it with `isMine: true`
); pinnedList[existingIndex] = {
...pinnedList[existingIndex],
isMine: true,
};
} else {
// If not in the list, add it with `isMine: true` at the beginning
pinnedList.unshift({ ...appToCheck, isMine: true });
}
if (existingIndex !== -1) { return pinnedList;
// If the app is already in the list, update it with `isMine: true` };
pinnedList[existingIndex] = { ...pinnedList[existingIndex], isMine: true };
} else {
// If not in the list, add it with `isMine: true` at the beginning
pinnedList.unshift({ ...appToCheck, isMine: true });
}
return pinnedList; // Update or add `myWebsite` and `myApp` while preserving their positions
}; pinned = addOrUpdateIsMine(pinned, myWebsite);
pinned = addOrUpdateIsMine(pinned, myApp);
// Update or add `myWebsite` and `myApp` while preserving their positions // Update pinned list based on availableQapps
pinned = addOrUpdateIsMine(pinned, myWebsite); pinned = pinned.map((pin) => {
pinned = addOrUpdateIsMine(pinned, myApp); const findIndex = availableQapps?.findIndex(
(item) => item?.service === pin?.service && item?.name === pin?.name
);
if (findIndex !== -1)
return {
...availableQapps[findIndex],
...pin,
};
// Update pinned list based on availableQapps return pin;
pinned = pinned.map((pin) => { });
const findIndex = availableQapps?.findIndex(
(item) => item?.service === pin?.service && item?.name === pin?.name
);
if (findIndex !== -1) return {
...availableQapps[findIndex],
...pin
}
return pin; return pinned;
});
return pinned;
}, [myApp, myWebsite, pinnedApps, availableQapps]); }, [myApp, myWebsite, pinnedApps, availableQapps]);
const sensors = useSensors(
useSensor(PointerSensor, {
activationConstraint: {
distance: 10, // Set a distance to avoid triggering drag on small movements
},
}),
useSensor(TouchSensor, {
activationConstraint: {
distance: 10, // Also apply to touch
},
}),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
);
const sensors = useSensors( const handleDragEnd = (event) => {
useSensor(PointerSensor, { const { active, over } = event;
activationConstraint: {
distance: 10, // Set a distance to avoid triggering drag on small movements
},
}),
useSensor(TouchSensor, {
activationConstraint: {
distance: 10, // Also apply to touch
},
}),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
);
const handleDragEnd = (event) => { if (!over) return; // Make sure the drop target exists
const { active, over } = event;
if (!over) return; // Make sure the drop target exists if (active.id !== over.id) {
const oldIndex = transformPinnedApps.findIndex(
(item) => `${item?.service}-${item?.name}` === active.id
);
const newIndex = transformPinnedApps.findIndex(
(item) => `${item?.service}-${item?.name}` === over.id
);
if (active.id !== over.id) { const newOrder = arrayMove(transformPinnedApps, oldIndex, newIndex);
const oldIndex = transformPinnedApps.findIndex((item) => `${item?.service}-${item?.name}` === active.id); setPinnedApps(newOrder);
const newIndex = transformPinnedApps.findIndex((item) => `${item?.service}-${item?.name}` === over.id); saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', newOrder);
setSettingsLocalLastUpdated(Date.now());
}
};
const newOrder = arrayMove(transformPinnedApps, oldIndex, newIndex); return (
setPinnedApps(newOrder); <DndContext
saveToLocalStorage('ext_saved_settings','sortablePinnedApps', newOrder) sensors={sensors}
setSettingsLocalLastUpdated(Date.now()) collisionDetection={closestCenter}
} onDragEnd={handleDragEnd}
}; >
return ( <SortableContext
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}> items={transformPinnedApps.map((app) => `${app?.service}-${app?.name}`)}
<SortableContext items={transformPinnedApps.map((app) => `${app?.service}-${app?.name}`)}> >
{transformPinnedApps.map((app) => ( {transformPinnedApps.map((app) => (
<SortableItem isDesktop={isDesktop} key={`${app?.service}-${app?.name}`} id={`${app?.service}-${app?.name}`} name={app?.name} app={app} /> <SortableItem
))} isDesktop={isDesktop}
</SortableContext> key={`${app?.service}-${app?.name}`}
</DndContext> id={`${app?.service}-${app?.name}`}
); name={app?.name}
app={app}
/>
))}
</SortableContext>
</DndContext>
);
}; };