From 51f9bec30aeb9ad11c14433c36c2efa56bcd7051 Mon Sep 17 00:00:00 2001 From: Ophir Bucai Date: Sat, 26 Apr 2025 00:23:08 +0300 Subject: [PATCH 1/7] Feature: Improve IconList layout supporting multiple columns based on the window's width --- website/components/ListItem.js | 5 +++-- website/screens/List.js | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/website/components/ListItem.js b/website/components/ListItem.js index 6ad6c326..5669076d 100644 --- a/website/components/ListItem.js +++ b/website/components/ListItem.js @@ -5,7 +5,7 @@ import PressableOpacity from "./PressableOpacity"; const ListItem = ({ name, family, onPress }) => { return ( - + @@ -26,7 +26,8 @@ const styles = StyleSheet.create({ paddingVertical: 15, alignItems: "center", borderBottomWidth: 1, - borderBottomColor: "#e3e3e3", + borderRightWidth: 1, + borderColor: "#e3e3e3", }, textView: { flexDirection: "column", diff --git a/website/screens/List.js b/website/screens/List.js index 5eb9edb4..8f74d25a 100644 --- a/website/screens/List.js +++ b/website/screens/List.js @@ -5,7 +5,13 @@ import React, { useImperativeHandle, forwardRef, } from "react"; -import { StyleSheet, View, FlatList, TextInput } from "react-native"; +import { + StyleSheet, + View, + FlatList, + TextInput, + useWindowDimensions +} from "react-native"; import { useDebouncedCallback } from "use-debounce"; import { IconsArray } from "../IconConstants"; import ListItem from "../components/ListItem"; @@ -193,12 +199,20 @@ const IconList = React.memo(({ query, filters, navigation }) => { [navigation] ); + const { width } = useWindowDimensions(); + + const numColumns = React.useMemo(() => { + return getNumColumns(width); + }, [width]); + return ( ); }); @@ -207,6 +221,11 @@ function keyExtractor(item) { return `${item.family}-${item.name}`; } +function getNumColumns(width, columnWidth = 300) { + const numColumns = Math.floor(width / columnWidth); + return Math.max(numColumns, 1); +} + const IconRow = React.memo(({ item, navigation }) => { return ( Date: Sat, 26 Apr 2025 01:16:10 +0300 Subject: [PATCH 2/7] fix: Handle text overlapping with ellipsis, ensure spacing towards the edge of the container --- website/components/ListItem.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/website/components/ListItem.js b/website/components/ListItem.js index 5669076d..12f39b16 100644 --- a/website/components/ListItem.js +++ b/website/components/ListItem.js @@ -11,8 +11,8 @@ const ListItem = ({ name, family, onPress }) => { - {name} - {family} + {name} + {family} @@ -32,6 +32,8 @@ const styles = StyleSheet.create({ textView: { flexDirection: "column", marginLeft: 20, + marginRight: 10, + flex: 1, }, name: { fontSize: 18, From 50eb72bf1b83d02dca527d7e7ddfc94bbff2d2a8 Mon Sep 17 00:00:00 2001 From: Ophir Bucai Date: Sat, 26 Apr 2025 02:02:12 +0300 Subject: [PATCH 3/7] fix: pad list for consistent item size --- website/screens/List.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/website/screens/List.js b/website/screens/List.js index 8f74d25a..9c2c86d8 100644 --- a/website/screens/List.js +++ b/website/screens/List.js @@ -194,6 +194,7 @@ const IconList = React.memo(({ query, filters, navigation }) => { const renderItem = React.useCallback( ({ item }) => { + if (!item) return ; return ; }, [navigation] @@ -205,10 +206,14 @@ const IconList = React.memo(({ query, filters, navigation }) => { return getNumColumns(width); }, [width]); + const paddedIconList = React.useMemo(() => { + return padList(icons, numColumns); + }, [icons, numColumns]); + return ( { ); }); -function keyExtractor(item) { - return `${item.family}-${item.name}`; +function keyExtractor(item, index) { + return item ? `${item.family}-${item.name}` : `empty-${index}`; } function getNumColumns(width, columnWidth = 300) { @@ -226,6 +231,11 @@ function getNumColumns(width, columnWidth = 300) { return Math.max(numColumns, 1); } +function padList(data = [], numColumns) { + const missing = data.length % numColumns; + return missing > 0 ? [...data, ...Array(missing).fill(null)] : data; +} + const IconRow = React.memo(({ item, navigation }) => { return ( Date: Sat, 26 Apr 2025 03:37:19 +0300 Subject: [PATCH 4/7] chore: extract empty style to improve clarity, improve variable names --- website/screens/List.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/website/screens/List.js b/website/screens/List.js index 9c2c86d8..b2769085 100644 --- a/website/screens/List.js +++ b/website/screens/List.js @@ -194,8 +194,10 @@ const IconList = React.memo(({ query, filters, navigation }) => { const renderItem = React.useCallback( ({ item }) => { - if (!item) return ; - return ; + if (!item) { + return ; + } + return ; }, [navigation] ); @@ -206,14 +208,14 @@ const IconList = React.memo(({ query, filters, navigation }) => { return getNumColumns(width); }, [width]); - const paddedIconList = React.useMemo(() => { + const data = React.useMemo(() => { return padList(icons, numColumns); }, [icons, numColumns]); return ( 0 ? [...data, ...Array(missing).fill(null)] : data; + const emptyItemsInLastRow = data.length % numColumns; + return emptyItemsInLastRow > 0 ? [...data, ...Array(emptyItemsInLastRow).fill(null)] : data; } -const IconRow = React.memo(({ item, navigation }) => { +const IconItem = React.memo(({ item, navigation }) => { return ( Date: Sat, 26 Apr 2025 14:49:04 +0300 Subject: [PATCH 5/7] fix: Correct calculation for filling missing items in the list --- website/screens/List.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/website/screens/List.js b/website/screens/List.js index b2769085..2574b0b6 100644 --- a/website/screens/List.js +++ b/website/screens/List.js @@ -234,8 +234,9 @@ function getNumColumns(width, columnWidth = 300) { } function padList(data = [], numColumns) { - const emptyItemsInLastRow = data.length % numColumns; - return emptyItemsInLastRow > 0 ? [...data, ...Array(emptyItemsInLastRow).fill(null)] : data; + const remainderInLastRow = data.length % numColumns; + const emptyItemsToAdd = remainderInLastRow > 0 ? numColumns - remainderInLastRow : 0; + return [...data, ...Array(emptyItemsToAdd).fill(null)]; } const IconItem = React.memo(({ item, navigation }) => { From 071b7108abef895f04aa4f9a1954656a17956c3e Mon Sep 17 00:00:00 2001 From: Ophir Bucai Date: Sat, 26 Apr 2025 15:36:51 +0300 Subject: [PATCH 6/7] chore: Optimize padList function for clarity and simplicity --- website/screens/List.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/screens/List.js b/website/screens/List.js index 2574b0b6..964a6342 100644 --- a/website/screens/List.js +++ b/website/screens/List.js @@ -235,7 +235,7 @@ function getNumColumns(width, columnWidth = 300) { function padList(data = [], numColumns) { const remainderInLastRow = data.length % numColumns; - const emptyItemsToAdd = remainderInLastRow > 0 ? numColumns - remainderInLastRow : 0; + const emptyItemsToAdd = Math.max(numColumns - remainderInLastRow, 0); return [...data, ...Array(emptyItemsToAdd).fill(null)]; } From 31b68384bccdd7635a71d1010c916414088f53da Mon Sep 17 00:00:00 2001 From: Ophir Bucai Date: Sat, 26 Apr 2025 15:57:48 +0300 Subject: [PATCH 7/7] fix: Validate itemsPerRow is an integer in padList --- website/screens/List.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/website/screens/List.js b/website/screens/List.js index 964a6342..083d57d4 100644 --- a/website/screens/List.js +++ b/website/screens/List.js @@ -233,10 +233,13 @@ function getNumColumns(width, columnWidth = 300) { return Math.max(numColumns, 1); } -function padList(data = [], numColumns) { - const remainderInLastRow = data.length % numColumns; - const emptyItemsToAdd = Math.max(numColumns - remainderInLastRow, 0); - return [...data, ...Array(emptyItemsToAdd).fill(null)]; +function padList(items = [], itemsPerRow) { + if (!Number.isInteger(itemsPerRow) || itemsPerRow <= 0) return items; + + const remainerInLastRow = items.length % itemsPerRow; + if (remainerInLastRow === 0) return items; + + return [...items, ...Array(itemsPerRow - remainerInLastRow).fill(null)]; } const IconItem = React.memo(({ item, navigation }) => {