mirror of
https://github.com/linkwarden/linkwarden.git
synced 2026-04-18 12:09:44 +00:00
feat: enhance layout components with iOS version checks and improve header styles
This commit is contained in:
@@ -7,6 +7,8 @@ export default function Layout() {
|
||||
const router = useRouter();
|
||||
const { colorScheme } = useColorScheme();
|
||||
|
||||
const isIOS26Plus = Platform.OS === "ios" && Number(Platform.Version) >= 26;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
screenOptions={{
|
||||
@@ -26,7 +28,7 @@ export default function Layout() {
|
||||
headerIconColor: colorScheme === "dark" ? "white" : "black",
|
||||
},
|
||||
headerLargeTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"], // or whatever token you want
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
@@ -38,12 +40,9 @@ export default function Layout() {
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
headerStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: colorScheme === "dark"
|
||||
? rawTheme["dark"]["base-100"]
|
||||
: "white",
|
||||
backgroundColor: isIOS26Plus
|
||||
? "transparent"
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -10,6 +10,8 @@ export default function Layout() {
|
||||
const router = useRouter();
|
||||
const { colorScheme } = useColorScheme();
|
||||
|
||||
const isIOS26Plus = Platform.OS === "ios" && Number(Platform.Version) >= 26;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
screenOptions={{
|
||||
@@ -18,7 +20,7 @@ export default function Layout() {
|
||||
headerTintColor: colorScheme === "dark" ? "white" : "black",
|
||||
headerShadowVisible: false,
|
||||
headerLargeTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"], // or whatever token you want
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
@@ -30,12 +32,9 @@ export default function Layout() {
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
headerStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: colorScheme === "dark"
|
||||
? rawTheme["dark"]["base-100"]
|
||||
: "white",
|
||||
backgroundColor: isIOS26Plus
|
||||
? "transparent"
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -7,6 +7,8 @@ export default function Layout() {
|
||||
const router = useRouter();
|
||||
const { colorScheme } = useColorScheme();
|
||||
|
||||
const isIOS26Plus = Platform.OS === "ios" && Number(Platform.Version) >= 26;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
screenOptions={{
|
||||
@@ -26,7 +28,7 @@ export default function Layout() {
|
||||
headerIconColor: colorScheme === "dark" ? "white" : "black",
|
||||
},
|
||||
headerLargeTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"], // or whatever token you want
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
@@ -38,12 +40,9 @@ export default function Layout() {
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
headerStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: colorScheme === "dark"
|
||||
? rawTheme["dark"]["base-100"]
|
||||
: "white",
|
||||
backgroundColor: isIOS26Plus
|
||||
? "transparent"
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { Stack } from "expo-router";
|
||||
import { Stack, useRouter } from "expo-router";
|
||||
import { useColorScheme } from "nativewind";
|
||||
import { rawTheme, ThemeName } from "@/lib/colors";
|
||||
import { Platform } from "react-native";
|
||||
import { Platform, View } from "react-native";
|
||||
|
||||
export default function Layout() {
|
||||
const { colorScheme } = useColorScheme();
|
||||
const router = useRouter();
|
||||
|
||||
const isIOS26Plus =
|
||||
Platform.OS === "ios" && parseInt(Platform.Version as string, 10) >= 26;
|
||||
const themeBackgroundColor = rawTheme[colorScheme as ThemeName]["base-100"];
|
||||
|
||||
return (
|
||||
<Stack
|
||||
@@ -12,37 +17,53 @@ export default function Layout() {
|
||||
headerTitle: "Settings",
|
||||
headerLargeTitle: true,
|
||||
headerTintColor: colorScheme === "dark" ? "white" : "black",
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerShadowVisible: false,
|
||||
headerLargeTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"], // or whatever token you want
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
},
|
||||
headerLargeStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
Platform.OS === "ios" ? "transparent" : themeBackgroundColor,
|
||||
},
|
||||
headerBackTitle: "Back",
|
||||
headerStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: colorScheme === "dark"
|
||||
? rawTheme["dark"]["base-100"]
|
||||
: "white",
|
||||
backgroundColor: isIOS26Plus ? "transparent" : themeBackgroundColor,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Stack.Screen name="index" />
|
||||
<Stack.Screen
|
||||
name="index"
|
||||
options={{
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="preferredCollection"
|
||||
options={{
|
||||
headerTitle: "Preferred Collection",
|
||||
headerLargeTitle: false,
|
||||
headerTransparent: Platform.OS === "ios",
|
||||
headerBackground: () => (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: themeBackgroundColor,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
headerSearchBarOptions: {
|
||||
placeholder: "Search Collections",
|
||||
autoCapitalize: "none",
|
||||
onChangeText: (e) => {
|
||||
router.setParams({
|
||||
search: encodeURIComponent(e.nativeEvent.text),
|
||||
});
|
||||
},
|
||||
headerIconColor: colorScheme === "dark" ? "white" : "black",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
@@ -1,27 +1,38 @@
|
||||
import { View, Text, FlatList, TouchableOpacity } from "react-native";
|
||||
import React, { useCallback, useMemo, useState } from "react";
|
||||
import { View, Text, FlatList, TouchableOpacity, Platform } from "react-native";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import useAuthStore from "@/store/auth";
|
||||
import useDataStore from "@/store/data";
|
||||
import { useCollections } from "@linkwarden/router/collections";
|
||||
import { CollectionIncludingMembersAndLinkCount } from "@linkwarden/types/global";
|
||||
import Input from "@/components/ui/Input";
|
||||
import { Folder, Check } from "lucide-react-native";
|
||||
import { useColorScheme } from "nativewind";
|
||||
import { rawTheme, ThemeName } from "@/lib/colors";
|
||||
import { useLocalSearchParams } from "expo-router";
|
||||
import { useHeaderHeight } from "@react-navigation/elements";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
|
||||
const PreferredCollectionScreen = () => {
|
||||
const { auth } = useAuthStore();
|
||||
const { data, updateData } = useDataStore();
|
||||
const collections = useCollections(auth);
|
||||
const { colorScheme } = useColorScheme();
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const { search } = useLocalSearchParams<{ search?: string }>();
|
||||
const [filteredCollections, setFilteredCollections] = useState<
|
||||
CollectionIncludingMembersAndLinkCount[]
|
||||
>([]);
|
||||
const headerHeight = useHeaderHeight();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const filteredCollections = useMemo(() => {
|
||||
if (!collections.data) return [];
|
||||
const q = searchQuery.trim().toLowerCase();
|
||||
if (q === "") return collections.data;
|
||||
return collections.data.filter((col) => col.name.toLowerCase().includes(q));
|
||||
}, [collections.data, searchQuery]);
|
||||
useEffect(() => {
|
||||
const filter =
|
||||
collections.data?.filter((e) =>
|
||||
e.name
|
||||
.toLowerCase()
|
||||
.includes(decodeURIComponent(search?.toLowerCase() || ""))
|
||||
) || [];
|
||||
|
||||
setFilteredCollections(filter);
|
||||
}, [search, collections.data]);
|
||||
|
||||
const renderCollection = useCallback(
|
||||
({
|
||||
@@ -70,26 +81,19 @@ const PreferredCollectionScreen = () => {
|
||||
keyExtractor={(item) => item.id?.toString() || ""}
|
||||
renderItem={renderCollection}
|
||||
contentContainerStyle={{
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 20,
|
||||
paddingBottom: 20,
|
||||
paddingHorizontal: 16,
|
||||
flexGrow: 1,
|
||||
paddingTop: Platform.OS === "ios" ? headerHeight + 10 : 10,
|
||||
paddingBottom: insets.bottom + 60,
|
||||
}}
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
ListHeaderComponent={
|
||||
<Input
|
||||
placeholder="Search collections"
|
||||
className="mb-4 bg-base-200 h-10"
|
||||
value={searchQuery}
|
||||
onChangeText={setSearchQuery}
|
||||
/>
|
||||
}
|
||||
ListEmptyComponent={
|
||||
<Text
|
||||
style={{ textAlign: "center", marginTop: 20 }}
|
||||
className="text-neutral"
|
||||
<View
|
||||
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
|
||||
>
|
||||
No collections match “{searchQuery}”
|
||||
</Text>
|
||||
<Text className="text-neutral text-center">
|
||||
No collections match “{search}”
|
||||
</Text>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -7,6 +7,8 @@ export default function Layout() {
|
||||
const router = useRouter();
|
||||
const { colorScheme } = useColorScheme();
|
||||
|
||||
const isIOS26Plus = Platform.OS === "ios" && Number(Platform.Version) >= 26;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
screenOptions={{
|
||||
@@ -26,24 +28,20 @@ export default function Layout() {
|
||||
headerIconColor: colorScheme === "dark" ? "white" : "black",
|
||||
},
|
||||
headerLargeTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"], // or whatever token you want
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: rawTheme[colorScheme as ThemeName]["base-content"],
|
||||
},
|
||||
headerLargeStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
backgroundColor: isIOS26Plus
|
||||
? "transparent"
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
headerStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: colorScheme === "dark"
|
||||
? rawTheme["dark"]["base-100"]
|
||||
: "white",
|
||||
backgroundColor: isIOS26Plus
|
||||
? "transparent"
|
||||
: rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -299,14 +299,10 @@ const RootComponent = ({
|
||||
},
|
||||
headerStyle: {
|
||||
backgroundColor:
|
||||
Platform.OS === "ios"
|
||||
? "transparent"
|
||||
: colorScheme === "dark"
|
||||
? rawTheme["dark"]["base-100"]
|
||||
: "white",
|
||||
rawTheme[colorScheme as ThemeName]["base-100"],
|
||||
},
|
||||
headerRight: () => (
|
||||
<View className="flex-row gap-5 px-2">
|
||||
<View className="flex-row gap-5">
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
if (tmp.link) {
|
||||
|
||||
Reference in New Issue
Block a user