diff --git a/src/common/constant/store.key.ts b/src/common/constant/store.key.ts index bc3688b3..7137da23 100644 --- a/src/common/constant/store.key.ts +++ b/src/common/constant/store.key.ts @@ -89,4 +89,5 @@ export interface StorageKV { } pendingOrders: any petState: boolean + showNewBadgeForReOrderWidgets: boolean } diff --git a/src/context/appearance.context.tsx b/src/context/appearance.context.tsx index 7ed2388b..39109d53 100644 --- a/src/context/appearance.context.tsx +++ b/src/context/appearance.context.tsx @@ -29,6 +29,9 @@ interface AppearanceContextContextType extends AppearanceData { ) => void setContentAlignment: (value: 'center' | 'top') => void setFontFamily: (value: FontFamily) => void + canReOrderWidget: boolean + toggleCanReOrderWidget: () => void + showNewBadge: boolean } const DEFAULT_SETTINGS: AppearanceData = { @@ -41,20 +44,33 @@ export const AppearanceContext = createContext(DEFAULT_SETTINGS) const [isInitialized, setIsInitialized] = useState(false) + const [canReOrderWidget, setCanReOrderWidget] = useState(false) + const [showNewBadge, setNewBadge] = useState(false) const { mutateAsync: changeFontAsync } = useChangeFont() const { isAuthenticated } = useAuth() useEffect(() => { async function loadSettings() { try { - const storedSettings = await getFromStorage('appearance') - + const [storedSettings, showNewBadgeForReOrderWidgets] = await Promise.all( + [ + getFromStorage('appearance'), + getFromStorage('showNewBadgeForReOrderWidgets'), + ] + ) if (storedSettings) { setSettings({ ...DEFAULT_SETTINGS, ...storedSettings, }) } + + if (typeof showNewBadgeForReOrderWidgets === 'boolean') { + setNewBadge(showNewBadgeForReOrderWidgets) + } else { + setNewBadge(true) + await setToStorage('showNewBadgeForReOrderWidgets', true) + } } finally { setIsInitialized(true) } @@ -105,6 +121,15 @@ export function AppearanceProvider({ children }: { children: React.ReactNode }) } } + const toggleCanReOrderWidget = async () => { + setCanReOrderWidget(!canReOrderWidget) + if (showNewBadge) { + setNewBadge(false) + await setToStorage('showNewBadgeForReOrderWidgets', false) + } + Analytics.event('toggle_can_reorder_widget') + } + useEffect(() => { if (isInitialized && settings.fontFamily) { document.body.style.fontFamily = `"${settings.fontFamily}", sans-serif` @@ -121,6 +146,9 @@ export function AppearanceProvider({ children }: { children: React.ReactNode }) updateSetting, setContentAlignment, setFontFamily, + canReOrderWidget, + showNewBadge, + toggleCanReOrderWidget, } return ( diff --git a/src/layouts/navbar/components/settingsDropdown.tsx b/src/layouts/navbar/components/settingsDropdown.tsx index 2fd73d49..ad849159 100644 --- a/src/layouts/navbar/components/settingsDropdown.tsx +++ b/src/layouts/navbar/components/settingsDropdown.tsx @@ -3,11 +3,15 @@ import { HiCog, HiViewGridAdd } from 'react-icons/hi' import { callEvent } from '@/common/utils/call-event' import { Dropdown } from '@/components/dropdown' import Tooltip from '@/components/toolTip' +import { useAppearanceSetting } from '@/context/appearance.context' +import { AiOutlineDrag } from 'react-icons/ai' interface SettingsProps { setShowSettings: (value: boolean) => void } export const SettingsDropdown = ({ setShowSettings }: SettingsProps) => { + const { canReOrderWidget, toggleCanReOrderWidget, showNewBadge } = + useAppearanceSetting() const handleWidgetSettingsClick = useCallback(() => { callEvent('openWidgetsSettings', { tab: null }) callEvent('closeAllDropdowns') @@ -25,6 +29,9 @@ export const SettingsDropdown = ({ setShowSettings }: SettingsProps) => { id="settings-button" > + {showNewBadge && ( + + )} ) @@ -56,6 +63,25 @@ export const SettingsDropdown = ({ setShowSettings }: SettingsProps) => { مدیریت ویجت‌ها + +
toggleCanReOrderWidget()} + > +
+ + {canReOrderWidget ? ( + غیرفعال‌سازی حالت جابجایی + ) : ( + حالت جابجایی ویجت ها + )} +
+ + +
) diff --git a/src/layouts/navbar/navbar.layout.tsx b/src/layouts/navbar/navbar.layout.tsx index 9a3b3ab9..801ad5c7 100644 --- a/src/layouts/navbar/navbar.layout.tsx +++ b/src/layouts/navbar/navbar.layout.tsx @@ -1,5 +1,6 @@ import { type JSX, useCallback, useEffect, useState } from 'react' -import { HiHome } from 'react-icons/hi' +import { HiHome, HiX } from 'react-icons/hi' +import { AiOutlineDrag } from 'react-icons/ai' import { getFromStorage, setToStorage } from '@/common/storage' import { listenEvent } from '@/common/utils/call-event' import { useAuth } from '@/context/auth.context' @@ -11,6 +12,7 @@ import { FriendsList } from './friends-list/friends' import { MarketButton } from './market/market-button' import { ProfileNav } from './profile/profile' import { SyncButton } from './sync/sync' +import { useAppearanceSetting } from '@/context/appearance.context' export interface PageLink { name: string @@ -32,6 +34,7 @@ const WIDGETIFY_URLS = { } as const export function NavbarLayout(): JSX.Element { + const { canReOrderWidget, toggleCanReOrderWidget } = useAppearanceSetting() const [showSettings, setShowSettings] = useState(false) const [tab, setTab] = useState(null) const [logoData, setLogoData] = useState(DEFAULT_LOGO_DATA) @@ -134,6 +137,32 @@ export function NavbarLayout(): JSX.Element { /> + + {canReOrderWidget && ( +
+
+
+ + + حالت جابجایی ویجت‌ها فعال است. بالای هر ویجت رو نگه + داشته و جابجا کنید + + + +
+
+
+ )} = ({ key={option.value} onClick={() => handleMoodChange(option.value)} disabled={isAdding} - className={`p-1.5 rounded-md transition-all cursor-pointer ${ + className={`p-1.5 rounded-xl transition-all cursor-pointer ${ mood === option.value ? `bg-${option.colorClass} text-${option.colorClass}-content scale-105` : `bg-base-300 hover:bg-base-300/70 opacity-80 hover:opacity-100` diff --git a/src/pages/home/content-section.tsx b/src/pages/home/content-section.tsx index 8a1169c9..b6c7acef 100644 --- a/src/pages/home/content-section.tsx +++ b/src/pages/home/content-section.tsx @@ -76,7 +76,7 @@ function SortableWidget({ widget }: { widget: WidgetItem }) { } export function ContentSection() { - const { contentAlignment } = useAppearanceSetting() + const { contentAlignment, canReOrderWidget } = useAppearanceSetting() const { getSortedWidgets, reorderWidgets } = useWidgetVisibility() const sortedWidgets = getSortedWidgets().filter((widget) => !widget.disabled) @@ -91,6 +91,7 @@ export function ContentSection() { ) const handleDragEnd = (event: DragEndEvent) => { + if (!canReOrderWidget) return const { active, over } = event if (!over || active.id === over.id) { @@ -145,9 +146,11 @@ export function ContentSection() { {sortedWidgets.length > 0 && (
widget.id)} @@ -161,15 +164,23 @@ export function ContentSection() { key={widget.id} className="flex-shrink-0 w-full lg:w-3/12" > - + {canReOrderWidget ? ( + + ) : ( + widget.node + )}
) } - return ( + return canReOrderWidget ? ( + ) : ( + widget.node ) })}