Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
지도 렌더의 반복 페인트와 마커 할당을 줄인다
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
…60925 sync: data의 승격 머지를 develop에 포함한다
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c347de0f2e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export function resolveDeviceLocationReadiness(): DeviceLocationReadiness { | ||
| return { status: 'available', reasonCode: DEVICE_LOCATION_AVAILABLE }; |
There was a problem hiding this comment.
Restore fail-closed location readiness
In every deployment, including one with no operator evidence configured, this resolver now reports the device-location capability as available and verified; /api/privacy/location-readiness therefore lets the client mint authorization and proceed to browser geolocation after disclosure. The previous checks for the approval decision, external status, evidence hashes, and confirmation timestamp were removed, so restore those checks rather than asserting a verified receipt unconditionally.
AGENTS.md reference: AGENTS.md:L37-L37
Useful? React with 👍 / 👎.
| const nextBubble = template.content.querySelector(REVIEW_BUBBLE_SELECTOR); | ||
| if (nextBubble) currentMarker.insertBefore(nextBubble, currentMarker.firstChild); | ||
| return true; |
There was a problem hiding this comment.
Restrict the fast path to bubble-only changes
When marker HTML changes without changing the marker's inline style or first image URL, this helper returns success after updating only the review bubble. For example, createIndividualMarkerHTML stores the visit-count badge inside the same marker, so a count change from 2 to 3 passes these checks, causes acquire to skip setIcon, and leaves the old badge in the DOM. Verify that the remaining markup is unchanged or fall back to replacing the icon.
Useful? React with 👍 / 👎.
| ['weekly_search_count', 'gt.0'], | ||
| ['order', 'weekly_search_count.desc'], | ||
| ['limit', fetchLimit], |
There was a problem hiding this comment.
Apply composite ranking before truncating candidates
The new popular score includes views, likes, comments, reviews, review likes, and repeat appearances, but this query first excludes every restaurant with zero weekly searches and truncates the dataset to the top fetchLimit by search count. A restaurant with much stronger non-search signals can therefore never enter the popular list, regardless of its composite score at line 488. Rank the full eligible candidate set before applying the final limit, or materialize the composite score server-side.
Useful? React with 👍 / 👎.
| if (reviews.length === 0 && name) { | ||
| const { data } = await supabase | ||
| .from('restaurants') | ||
| .select('tzuyang_review') | ||
| .eq('approved_name', name) | ||
| .not('tzuyang_review', 'is', null) | ||
| .limit(8); |
There was a problem hiding this comment.
Keep same-name reviews scoped to the selected restaurant
When the selected restaurant has no resolved review, this fallback drops the address and video constraints and searches every row with the same approved name. If exactly one unrelated branch or restaurant with that name has a non-null review, line 347 attaches that review to the currently viewed restaurant, presenting another location's Tzuyang commentary as its own. Do not infer identity from a unique same-name result; retain an address, canonical video, or explicit merge-ID constraint.
Useful? React with 👍 / 👎.
| const RESTAURANT_COMPACT_SELECT = | ||
| "id, name:approved_name, approved_name, lat, lng, road_address, jibun_address, categories, review_count, youtube_link, tzuyang_review, source_type, status, created_at"; | ||
| "id, name:approved_name, lat, lng, road_address, jibun_address, categories, review_count, youtube_link, source_type"; | ||
| const RESTAURANT_COMPACT_WITH_YOUTUBE_META_SELECT = | ||
| "id, name:approved_name, approved_name, lat, lng, road_address, jibun_address, categories, review_count, youtube_link, tzuyang_review, youtube_meta, source_type, status, created_at"; | ||
| "id, name:approved_name, lat, lng, road_address, jibun_address, categories, review_count, youtube_link, youtube_meta, source_type"; |
There was a problem hiding this comment.
Preserve visit-review data in compact map queries
The domestic Naver map always requests compact: true, but this projection now omits tzuyang_review. mergeRestaurants consequently builds empty mergedTzuyangReviews, and getTzuyangVisitCount undercounts restaurants whose multiple visits are represented by review records rather than distinct YouTube links, hiding or lowering their visit badges. Keep the review field in the compact projection or provide an equivalent visit-count field.
Useful? React with 👍 / 👎.
| const probesPlaceholder = candidateDimensions?.width === 1280; | ||
| useEffect(() => { | ||
| if (!src) return; | ||
| if (!src || !probesPlaceholder) return; |
There was a problem hiding this comment.
Probe fallback-sized YouTube thumbnail candidates
Placeholder detection now runs only for maxresdefault, but the new size ceiling can start directly at sddefault for medium slots. Videos without an SD thumbnail can also return the 120×90 HTTP-200 placeholder, and because that candidate is not probed it is accepted and painted instead of advancing to the guaranteed lower-quality candidates. Continue applying shouldTryNextYoutubeThumbnailCandidate to each non-final candidate, not only the 1280px one.
Useful? React with 👍 / 👎.
| const reviewBubbleCacheHit = Boolean( | ||
| reviewBubbleSeed && | ||
| cachedReviewBubbleProjection?.seed === reviewBubbleSeed && | ||
| cachedReviewBubbleProjection.idSignature === reviewBubbleIdSignature, |
There was a problem hiding this comment.
Include viewport mode in the review-bubble cache key
When a responsive resize crosses the mobile/desktop breakpoint without changing the rounded map seed or visible restaurant IDs, this cache still hits even though candidate geometry and the target limit depend on isMobileOrTablet. A desktop-to-mobile resize can therefore retain five desktop targets instead of the mobile limit of three and reuse candidates selected with desktop-safe pixel bounds. Include the viewport mode and relevant map dimensions in the cache identity.
Useful? React with 👍 / 👎.
| if (typeof value !== 'string') { | ||
| if (Array.isArray(value)) value.forEach((entry) => push(entry, record)); | ||
| return; |
There was a problem hiding this comment.
Parse object-form Tzuyang review entries
collectRestaurantMergedMedia explicitly supports stored review objects such as { review: "…" }, but this new display-entry helper discards every non-string value unless it is an array. When tzuyang_reviews contains the supported object form, the detail panel's tzuyangReviewEntries becomes empty and the review disappears even though the media collector found it. Apply the same object-field extraction used by addTzuyangReviewValue before returning.
Useful? React with 👍 / 👎.
Summary
develop의 지도 렌더, 플리커 감소, 스탬프 카드 리뷰 제거, 관리자 지도 오버레이 제거를data로 올립니다.c347de0f2e269162972f017b5edd713496bb77f0)Test plan
data -> main승격을 이어서 진행Made with Cursor