Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add filter to NFT page #1639

Merged
merged 2 commits into from
Nov 10, 2024
Merged

Conversation

AMIRKHANEF
Copy link
Member

@AMIRKHANEF AMIRKHANEF commented Nov 10, 2024

close: #1638

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a filtering and sorting component for NFTs, enhancing user interaction and item management.
    • Added a responsive UI for displaying network information with improved media handling.
  • Bug Fixes

    • Improved fetching logic for GIFs and media types, ensuring proper display based on content.
  • Refactor

    • Removed the previous tabbed interface, streamlining the user experience with a filtering mechanism.
  • Style

    • Enhanced typography styling for improved visual consistency across components.

Copy link
Contributor

coderabbitai bot commented Nov 10, 2024

Walkthrough

This pull request introduces several modifications across multiple components in the Polkadot extension. Notably, a new Filters component is added to manage NFT filtering and sorting, replacing the previously existing Tabs component. The Details.tsx component sees enhancements in media handling and UI responsiveness. New interfaces for filter and sort states are defined in types.ts, improving type management. Overall, the changes refine user interactions and enhance the functionality of the NFT display and management system.

Changes

File Path Change Summary
packages/extension-polkagate/src/fullscreen/nft/components/Details.tsx - Added InfoRow component with conditional divider property.
- Updated fullscreen state management.
- Refined GIF source logic and useEffect for fetching.
- Adjusted fullscreen functions.
packages/extension-polkagate/src/fullscreen/nft/components/Filters.tsx - Introduced new Filters component for managing NFT filters and sorting.
- Implemented internal state management with useReducer and useState.
packages/extension-polkagate/src/fullscreen/nft/components/NftFilter.tsx - Added NftFilter component for filtering and sorting NFTs with Material-UI.
- Included checkboxes for filters and radio buttons for sorting.
packages/extension-polkagate/src/fullscreen/nft/components/Tabs.tsx - Removed Tabs component that provided a tabbed interface for NFTs and uniques.
packages/extension-polkagate/src/fullscreen/nft/index.tsx - Added import for Filters component and removed Tabs.
- Updated state management for itemsToShow and step.
packages/extension-polkagate/src/fullscreen/nft/utils/types.ts - Added new interfaces: FilterState, FilterAction, SortState, and SortAction for enhanced type management.

Possibly related PRs

Suggested reviewers

  • AMIRKHANEF

🐇 In the land of code, changes abound,
Filters and sorting, new features found.
Tabs have been replaced, a fresh view to see,
With NFTs dancing, as happy as can be!
So hop along, dear coder, take heed,
For this update blooms like a springtime seed! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (9)
packages/extension-polkagate/src/fullscreen/nft/utils/types.ts (1)

118-128: Consider enhancing filter type definitions for better maintainability.

The filter interfaces could benefit from the following improvements:

  1. Add JSDoc comments explaining the purpose of each filter
  2. Consider using an enum or union type for filter values instead of booleans to support future multi-select options
  3. Consider renaming ambiguous filters for clarity (e.g., 'unique', 'nft')

Here's a suggested improvement:

+/** Represents the state of NFT filters */
 export interface FilterState {
+  /** Filter by NFT collections */
   collections: boolean;
+  /** Filter by individual NFTs */
   nft: boolean;
-  unique: boolean;
+  /** Filter by RMRK standard NFTs */
+  rmrk: boolean;
   /** Filter by Kusama network */
   kusama: boolean;
   /** Filter by Polkadot network */
   polkadot: boolean;
 }

+/** Action to update a specific filter */
 export interface FilterAction {
   filter: keyof FilterState;
 }

+/** Initial state for filters */
+export const initialFilterState: FilterState = {
+  collections: false,
+  nft: false,
+  rmrk: false,
+  kusama: false,
+  polkadot: false
+};
packages/extension-polkagate/src/fullscreen/nft/index.tsx (2)

61-61: Consider memoization optimization.

While adding nftManager to the dependency array is correct, consider wrapping the handleNftUpdate callback with useCallback to prevent unnecessary re-renders if the nftManager reference changes.

+ const handleNftUpdate = useCallback((updatedAddress: string, updatedNfts: ItemInformation[]) => {
+   if (updatedAddress === address) {
+     setNfts(updatedNfts);
+   }
+ }, [address]);

  useEffect(() => {
    const myNfts = nftManager.get(address);
    setNfts(myNfts);

-   const handleNftUpdate = (updatedAddress: string, updatedNfts: ItemInformation[]) => {
-     if (updatedAddress === address) {
-       setNfts(updatedNfts);
-     }
-   };

    nftManager.subscribe(handleNftUpdate);
    return () => {
      nftManager.unsubscribe(handleNftUpdate);
    };
  }, [address, nftManager, handleNftUpdate]);

Line range hint 127-131: Add loading and error states for filtered items.

While the Filters integration looks good, consider handling loading and empty states for itemsToShow to improve user experience.

  <Filters
    items={nfts}
    setItemsToShow={setItemsToShow}
  />
+ {itemsToShow === undefined && (
+   <Typography>Loading NFTs...</Typography>
+ )}
+ {itemsToShow === null && (
+   <Typography>No NFTs found</Typography>
+ )}
  <NftList
    apis={apis}
    nfts={itemsToShow}
  />
packages/extension-polkagate/src/fullscreen/nft/components/NftFilter.tsx (3)

4-14: Consider organizing imports for better maintainability.

Group the imports into these categories for better organization:

  1. External libraries (React, MUI)
  2. Internal components/hooks
  3. Types/interfaces
/* eslint-disable react/jsx-max-props-per-line */

import type { FilterAction, FilterState, SortAction, SortState } from '../utils/types';

+ // External imports
import React, { useCallback } from 'react';
import { FilterAltOutlined as FilterIcon, FilterList as FilterListIcon, ImportExport as ImportExportIcon } from '@mui/icons-material';
import { Divider, FormControl, FormControlLabel, Grid, Popover, Radio, RadioGroup, Typography, useTheme } from '@mui/material';

+ // Internal imports
import Checkbox2 from '../../../components/Checkbox2';
import { useTranslation } from '../../../hooks';

15-20: Add JSDoc documentation for the Props interface.

Adding documentation will improve code maintainability and help other developers understand the purpose of each prop.

+/**
+ * Props for the Filters and NftFilters components
+ * @property {React.Dispatch<FilterAction>} dispatchFilter - Dispatch function for filter actions
+ * @property {FilterState} filters - Current filter state
+ * @property {React.Dispatch<SortAction>} dispatchSort - Dispatch function for sort actions
+ * @property {SortState} sort - Current sort state
+ */
interface Props {
  dispatchFilter: React.Dispatch<FilterAction>;
  filters: FilterState;
  dispatchSort: React.Dispatch<SortAction>;
  sort: SortState;
}

30-32: Fix parameter naming in onSort callback.

The parameter name 'unable' appears to be a typo and should be 'disable' to better reflect its purpose.

-const onSort = useCallback((enable: keyof SortState, unable: keyof SortState) => () => {
-  dispatchSort({ enable, unable });
+const onSort = useCallback((enable: keyof SortState, disable: keyof SortState) => () => {
+  dispatchSort({ enable, disable });
}, [dispatchSort]);
packages/extension-polkagate/src/fullscreen/nft/components/Details.tsx (3)

287-288: Consider simplifying the divider logic.

The divider condition !!itemInformation.description || (!itemInformation.isCollection && !!itemInformation.collectionName) is complex and may be difficult to maintain. Consider extracting this logic into a separate function or adopting a more consistent approach to dividers.

+ const shouldShowDivider = useCallback(() => {
+   return !!itemInformation.description || 
+          (!itemInformation.isCollection && !!itemInformation.collectionName);
+ }, [itemInformation.description, itemInformation.isCollection, itemInformation.collectionName]);

  <InfoRow
-   divider={!!itemInformation.description || (!itemInformation.isCollection && !!itemInformation.collectionName)}
+   divider={shouldShowDivider()}
    text={itemInformation.chainName}
    title={t('Network')}
  />

Alternatively, consider using a more consistent pattern for dividers, such as showing them between all rows except the last one, which would be more maintainable and predictable.


Line range hint 199-203: Improve fullscreen error handling.

The current error handling for fullscreen requests only logs errors to the console. Consider handling these errors more gracefully by showing a user-friendly message when fullscreen requests fail.

  const openFullscreen = useCallback(() => {
    if (showFullscreenDisabled) {
      return;
    }

-   document.documentElement.requestFullscreen().catch(console.error);
+   document.documentElement.requestFullscreen().catch((error) => {
+     console.error('Fullscreen request failed:', error);
+     // Show user-friendly error message
+     // Consider adding a toast notification or inline message
+   });
    setShowFullscreen(true);
  }, [showFullscreenDisabled]);

Line range hint 1-289: Consider breaking down the component for better maintainability.

The Details component is quite large and handles multiple responsibilities (media display, fullscreen management, information display). Consider splitting it into smaller, focused components:

  1. MediaDisplay - Handle different media types (images, GIFs, audio, HTML)
  2. InfoSection - Handle the information display and divider logic
  3. FullscreenControls - Manage fullscreen functionality

This would improve:

  • Code organization and maintainability
  • Testing capabilities
  • Reusability of individual components
  • State management clarity

Would you like me to provide a detailed example of this restructuring?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 860e98f and 21e251a.

📒 Files selected for processing (6)
  • packages/extension-polkagate/src/fullscreen/nft/components/Details.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/nft/components/Filters.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/nft/components/NftFilter.tsx (1 hunks)
  • packages/extension-polkagate/src/fullscreen/nft/components/Tabs.tsx (0 hunks)
  • packages/extension-polkagate/src/fullscreen/nft/index.tsx (4 hunks)
  • packages/extension-polkagate/src/fullscreen/nft/utils/types.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • packages/extension-polkagate/src/fullscreen/nft/components/Tabs.tsx
🔇 Additional comments (5)
packages/extension-polkagate/src/fullscreen/nft/index.tsx (2)

21-21: LGTM: Clean state management implementation.

The new imports and state variables are well-typed and properly integrated. The use of an enum for step management provides good type safety.

Also applies to: 41-42


21-21: Verify removal of Tabs component.

Let's ensure no other components depend on the removed Tabs component.

packages/extension-polkagate/src/fullscreen/nft/components/NftFilter.tsx (2)

153-153: LGTM!

The component is properly memoized before export to prevent unnecessary re-renders.


6-6: Verify type definitions and component integration.

Let's verify the type definitions and component usage in the codebase.

✅ Verification successful

Types are properly integrated and used correctly

The imported types FilterAction, FilterState, SortAction, and SortState are correctly defined in utils/types.ts and properly used in both NftFilter and Filters components. The integration shows:

  1. Types are properly defined in the types file
  2. Correct usage in reducer functions and component props
  3. Proper integration with parent component (Filters)
  4. Consistent type usage across the filter functionality
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify type definitions and component integration

# Check type definitions
echo "Checking type definitions..."
ast-grep --pattern 'type FilterAction = { $$$; };' 
ast-grep --pattern 'type SortAction = { $$$; };'

# Check component usage
echo "Checking component usage..."
rg -l "import.*NftFilters?" --type tsx

Length of output: 304


Script:

#!/bin/bash
# Let's try a different approach to verify the types and component usage

# Check for type definitions in utils/types
echo "Checking type definitions in utils/types..."
fd "types.ts" --exec cat {}

# Check component usage with different extension
echo "Checking component usage..."
rg -l "import.*NftFilter" --type ts --type tsx

# Look for FilterAction and SortAction usage
echo "Checking type usage..."
rg "FilterAction|SortAction" --type ts --type tsx

Length of output: 48344


Script:

#!/bin/bash
# Let's try without specifying file types for rg

# Check for type definitions
echo "Checking type definitions..."
rg -p "type (FilterAction|FilterState|SortAction|SortState)"

# Check component usage
echo "Checking component usage..."
rg -p "import.*NftFilter"

# Look for usage of these types
echo "Checking type usage..."
rg -p "(FilterAction|SortAction) *[=:]"

Length of output: 430


Script:

#!/bin/bash
# Let's check the content of related files

# Check the content of NftFilter component
echo "Checking NftFilter component..."
cat packages/extension-polkagate/src/fullscreen/nft/components/NftFilter.tsx

# Check the content of Filters component
echo "Checking Filters component..."
cat packages/extension-polkagate/src/fullscreen/nft/components/Filters.tsx

# Check the types file
echo "Checking types file..."
cat packages/extension-polkagate/src/fullscreen/nft/utils/types.ts

Length of output: 15111

packages/extension-polkagate/src/fullscreen/nft/components/Filters.tsx (1)

63-65: ⚠️ Potential issue

Ensure chainName is defined before using toLowerCase()

In the getDecimal function, chainName might be undefined, which would cause an error when calling toLowerCase().

Consider adding a check for chainName:

 const getDecimal = useCallback((chainName: string) => {
+  if (!chainName) return undefined;
   return selectableNetworks.find(({ network }) => network.toLowerCase() === chainName.toLowerCase())?.decimals[0];
 }, []);

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
packages/extension-polkagate/src/fullscreen/nft/components/InfoRow.tsx (1)

47-47: Consider centralizing typography styles for better maintainability.

The font weight changes from 400 to 500 across multiple typography elements suggest an effort to establish a consistent visual hierarchy. While the changes themselves are valid, having these styles scattered across individual components could lead to maintenance challenges.

Consider:

  1. Creating a theme-based typography system
  2. Using styled components or a CSS-in-JS solution
  3. Defining typography variants in a central location

Example approach using MUI theme customization:

// theme.ts
const theme = createTheme({
  typography: {
    nftLabel: {
      fontSize: '14px',
      fontWeight: 500,
    },
    // other variants...
  },
});

// Usage in component
<Typography variant="nftLabel">
  {t('Not listed')}
</Typography>

Also applies to: 69-69, 74-74

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 21e251a and bf8d102.

📒 Files selected for processing (2)
  • packages/extension-polkagate/src/fullscreen/nft/components/InfoRow.tsx (2 hunks)
  • packages/extension-polkagate/src/fullscreen/nft/components/Thumbnail.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/extension-polkagate/src/fullscreen/nft/components/Thumbnail.tsx
🔇 Additional comments (1)
packages/extension-polkagate/src/fullscreen/nft/components/InfoRow.tsx (1)

47-47: Verify accessibility compliance with font weight changes.

The increased font weight (500) improves visual prominence but should be tested for accessibility, particularly for color contrast ratios and readability.

Also applies to: 69-69, 74-74

✅ Verification successful

Based on the comprehensive search results showing Typography component usage across the codebase, I can now generate the final response:

Font weight 500 is consistently used for emphasis and visual hierarchy throughout the codebase

The font weight of 500 in the InfoRow component aligns with the established pattern across the codebase where this weight is commonly used for:

  • Section headers and labels
  • Important information that needs visual emphasis
  • Interactive elements like menu items and buttons
  • Selected/active states

The usage maintains accessibility standards as:

  • It provides sufficient contrast with regular text (400) and light text (300)
  • It's used sparingly and purposefully for visual hierarchy
  • It follows Material UI's recommended font weight scale
  • It's consistently applied across similar UI elements
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other typography elements in the codebase to ensure consistent font weight usage
rg -l "Typography.*fontWeight" | while read -r file; do
  echo "=== $file ==="
  rg "Typography.*fontWeight" "$file"
done

Length of output: 163280

@Nick-1979 Nick-1979 merged commit c8c835e into PolkaGate:main Nov 10, 2024
8 checks passed
github-actions bot pushed a commit that referenced this pull request Nov 10, 2024
# [0.25.0](v0.24.0...v0.25.0) (2024-11-10)

### Features

* add filter to NFT page ([#1639](#1639)) ([c8c835e](c8c835e))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: add filter to NFT album page
2 participants