Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/common/utils/call-event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface EventName {
}
bookmarksChanged: Bookmark[]
updatedPetSettings: {
instanceId?: string
petName?: string
petType: PetTypes
background?: PetBackgroundId
Expand Down
14 changes: 2 additions & 12 deletions src/context/free-widget/use-widget-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ import { setToStorage, watchStorage } from '@/common/storage'
import { DEFAULT_COLS, DEFAULT_WIDGET_LAYOUT } from '@/layouts/widgets/layout-engine'
import type { StoredWidget } from '@/layouts/widgets/layout-engine/types'
import { applyInstanceIdMap, buildInstanceIdMap } from '@/layouts/widgets/instance-id'
import {
migrateWidgetLayoutIfNeeded,
replaceWidgetifyWithPetAndPhoto,
} from '@/layouts/widgets/migration'
import { migrateWidgetLayoutIfNeeded } from '@/layouts/widgets/migration'
import {
getUserWidgetsApi,
syncUserWidgetsApi,
Expand Down Expand Up @@ -164,22 +161,15 @@ export function useWidgetSync({
disabled: sw.disabled,
}))

const { layout: replacedWidgets, hasChanged: wasReplaced } =
replaceWidgetifyWithPetAndPhoto(rawWidgets)

const fromSrv: StoredWidget[] = sanitizeLayout(
replacedWidgets,
rawWidgets,
DEFAULT_COLS
)

savedLayoutRef.current = fromSrv
setSavedLayout(fromSrv)
applyRuntimeLayout(reflowForColumns(fromSrv, colsRef.current))
persistLayout(fromSrv)

if (wasReplaced) {
triggerServerSync(fromSrv)
}
} else {
const localLayout = await migrateWidgetLayoutIfNeeded()
if (localLayout && localLayout.length > 0) {
Expand Down
42 changes: 1 addition & 41 deletions src/layouts/widgets/migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,51 +44,11 @@ const topWidgets: StoredWidget[] = [
},
]

export function replaceWidgetifyWithPetAndPhoto(widgets: StoredWidget[]): {
layout: StoredWidget[]
hasChanged: boolean
} {
let hasChanged = false
const result: StoredWidget[] = []

for (const widget of widgets) {
if (widget.id === ('widgetify' as any)) {
hasChanged = true
const col = widget.position?.col ?? 6
const baseRow = widget.position?.row ?? 0

result.push({
id: WidgetKeys.photo,
instanceId: 'photo-default',
position: { col, row: baseRow },
size: { w: 2, h: 2 },
widgetId: 'photo-default',
})

result.push({
id: WidgetKeys.pet,
instanceId: 'pet-default',
position: { col, row: baseRow + 2 },
size: { w: 2, h: 1 },
widgetId: 'pet-default',
})
} else {
result.push(widget)
}
}

return { layout: result, hasChanged }
}

export async function migrateWidgetLayoutIfNeeded(): Promise<StoredWidget[]> {
const existingStored = await getFromStorage('storedWidgets')

if (Array.isArray(existingStored)) {
const { layout, hasChanged } = replaceWidgetifyWithPetAndPhoto(existingStored)
if (hasChanged) {
await setToStorage('storedWidgets', layout)
}
return layout
return existingStored
}

const { appearance, activeWidgets } = await getMultipleFromStorage([
Expand Down
8 changes: 7 additions & 1 deletion src/layouts/widgets/pet/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,15 @@ export const PET_SPECIES_LABEL: Record<PetTypes, string> = {
[PetTypes.CAT]: 'گربه',
}

export const DEFAULT_PET_BACKGROUND: PetBackgroundId = 'forest'
export const DEFAULT_PET_BACKGROUND: PetBackgroundId = 'none'

export const PET_BACKGROUNDS: Record<PetBackgroundId, PetBackground> = {
none: {
id: 'none',
label: 'بدون محیط',
image: null,
groundOffsetPx: 0,
},
forest: {
id: 'forest',
label: 'جنگل شب',
Expand Down
109 changes: 82 additions & 27 deletions src/layouts/widgets/pet/pet-setting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
import { getFromStorage } from '@/common/storage'
import { callEvent } from '@/common/utils/call-event'
import { TextInput } from '@/components/ui'
import { useFreeWidgets } from '@/context/free-widget/free-widget.context'
import { PetOptionTile } from './components/pet-option-tile'
import {
BASE_PET_OPTIONS,
Expand All @@ -11,7 +12,7 @@ import {
PET_PREVIEW,
PET_SPECIES_LABEL,
} from './constants'
import { type PetBackgroundId, PetTypes } from './types'
import { type PetBackgroundId, type PetMeta, PetTypes } from './types'
import { getPetBackground } from './utils/get-pet-background'

const PET_LIST = Object.keys(BASE_PET_OPTIONS.petOptions) as PetTypes[]
Expand All @@ -21,13 +22,34 @@ const TIPS = [
'برای غذا دادن، در محیط اطراف آن کلیک کنید',
]

export function PetSettings() {
const [petType, setPetType] = useState<PetTypes>(PetTypes.DOG)
const [petName, setPetName] = useState('')
const [background, setBackground] = useState<PetBackgroundId>(DEFAULT_PET_BACKGROUND)
interface PetSettingsProps {
instanceId?: string
size?: { w: number; h: number }
}

export function PetSettings({ instanceId }: PetSettingsProps = {}) {
const { runtimeLayout, updateWidgetSettings } = useFreeWidgets()
const targetWidget = instanceId
? runtimeLayout.find((w) => w.instanceId === instanceId)
: null
const targetMeta = targetWidget?.meta as PetMeta | undefined

const [petType, setPetType] = useState<PetTypes>(targetMeta?.petType || PetTypes.DOG)
const [petName, setPetName] = useState(targetMeta?.petName || '')
const [background, setBackground] = useState<PetBackgroundId>(
targetMeta?.background || DEFAULT_PET_BACKGROUND
)

useEffect(() => {
async function load() {
if (instanceId && targetMeta) {
const type = targetMeta.petType || PetTypes.DOG
setPetType(type)
setPetName(targetMeta.petName || BASE_PET_OPTIONS.petOptions[type].name)
setBackground(targetMeta.background || DEFAULT_PET_BACKGROUND)
return
}

const stored = await getFromStorage('pets')
if (!stored?.petOptions) return

Expand All @@ -38,26 +60,60 @@ export function PetSettings() {
}

load()
}, [])
}, [instanceId, targetMeta])

function onChangePetName(value: string) {
setPetName(value)
callEvent('updatedPetSettings', { petName: value, petType })
if (instanceId) {
updateWidgetSettings(instanceId, {
...targetMeta,
petType,
petName: value,
background,
})
}
callEvent('updatedPetSettings', { instanceId, petName: value, petType })
}

async function onChangePetType(value: PetTypes) {
const stored = await getFromStorage('pets')

setPetType(value)
setPetName(
const fallbackName =
stored?.petOptions[value]?.name ?? BASE_PET_OPTIONS.petOptions[value].name
)
callEvent('updatedPetSettings', { petType: value })

setPetType(value)
setPetName(fallbackName)

if (instanceId) {
updateWidgetSettings(instanceId, {
...targetMeta,
petType: value,
petName: fallbackName,
background,
})
}
callEvent('updatedPetSettings', {
instanceId,
petType: value,
petName: fallbackName,
})
}

function onChangeBackground(value: PetBackgroundId) {
setBackground(value)
callEvent('updatedPetSettings', { petType, background: value })
if (instanceId) {
updateWidgetSettings(instanceId, {
...targetMeta,
petType,
petName,
background: value,
})
}
callEvent('updatedPetSettings', {
instanceId,
petType,
background: value,
})
}

const displayName = petName.trim() || BASE_PET_OPTIONS.petOptions[petType].name
Expand All @@ -69,7 +125,7 @@ export function PetSettings() {
<div
className="flex items-end justify-center overflow-hidden border w-16 h-16 shrink-0 rounded-2xl border-content"
style={{
backgroundImage: `url(${scene.image})`,
backgroundImage: scene.image ? `url(${scene.image})` : undefined,
backgroundSize: 'cover',
backgroundPosition: 'bottom center',
}}
Expand All @@ -96,11 +152,7 @@ export function PetSettings() {
<h4 id="pet-type-label" className="text-sm font-medium text-content">
حیوان خانگی
</h4>
<div
role="group"
aria-labelledby="pet-type-label"
className="grid grid-cols-5 gap-2"
>
<div aria-labelledby="pet-type-label" className="grid grid-cols-5 gap-2">
{PET_LIST.map((type) => (
<PetOptionTile
key={type}
Expand All @@ -126,9 +178,8 @@ export function PetSettings() {
محیط
</h4>
<div
role="group"
aria-labelledby="pet-background-label"
className="grid grid-cols-3 gap-2"
className="grid grid-cols-4 gap-2"
>
{PET_BACKGROUND_LIST.map((item) => (
<PetOptionTile
Expand All @@ -138,13 +189,17 @@ export function PetSettings() {
onSelect={() => onChangeBackground(item.id)}
>
<div
className="w-full h-12"
style={{
backgroundImage: `url(${item.image})`,
backgroundSize: 'cover',
backgroundPosition: 'bottom center',
}}
/>
className="w-full h-12 flex items-center justify-center bg-base-300/40"
style={
item.image
? {
backgroundImage: `url(${item.image})`,
backgroundSize: 'cover',
backgroundPosition: 'bottom center',
}
: undefined
}
></div>
</PetOptionTile>
))}
</div>
Expand Down
Loading
Loading