feat(mobile): add multi-image indicator to feed posts
Multi-photo posts gave no visual hint they were swipeable — a viewer would only ever see the first image unless they already knew to swipe. Adds a "1 / N" counter badge (top-right overlay) and a dot-page indicator below the carousel, porting web's PostCard indicators.
This commit is contained in:
1 parent
086b0e8900
commit
82c9bb87b9
2 files changed
+58
-10
No files matched your search
+4
-5
@@ -34,10 +34,9 @@ TODO Neu2:
|
||||
→ Sichtbare Trennlinie zwischen den Einträgen ergänzt, live bestätigt.
|
||||
- [x] Benachrichtigungen sind nicht anklickbar, sollten aber zu dem jeweiligen Post / Pet gehen.
|
||||
→ Tap markiert als gelesen und navigiert zum Ziel (Post-Kommentare bzw. Tierprofil je nach Typ), live bestätigt.
|
||||
→ Nachbesserung: Alle Post-Benachrichtigungen zeigten nur die leere Kommentarliste statt des Beitrags selbst — die Kommentar-Seite lädt jetzt zusätzlich den Post (posts.getById) und zeigt ihn oben per PostCard an. Außerdem ist der Pet-Name in der Benachrichtigung jetzt separat anklickbar zum Profil, unabhängig vom restlichen Zeilen-Tap. Beides live bestätigt.
|
||||
- [x] Drei Punkte, menü im Feed, falls es der eigene Beitrag ist, lösch funktion hinzufügen, statt Report.
|
||||
→ Bei eigenem Beitrag öffnet "⋮" jetzt einen Lösch-Bestätigungsdialog statt der Report-Ansicht, bei fremden Beiträgen bleibt Report wie gewohnt; beides live bestätigt.
|
||||
- im Feed fehlt ein Indikator wenn in einem Post mehrere Bilder hinterlegt sind. das wischen funktioniert, aber nur wenn man weiß das dort mehrere bilder hinterlegt sind. unwissende würde nur ein bild sehen können.
|
||||
- [x] Kommentar Fenster ist nicht im Darkmode
|
||||
→ Screen nutzte noch die statischen (hellen) Farb-Tokens statt useTheme(); jetzt vollständig dark-mode-fähig, live bestätigt.
|
||||
-
|
||||
- [x] im Feed fehlt ein Indikator wenn in einem Post mehrere Bilder hinterlegt sind. das wischen funktioniert, aber nur wenn man weiß das dort mehrere bilder hinterlegt sind. unwissende würde nur ein bild sehen können.
|
||||
→ Zähler-Badge oben rechts ("1 / 3") plus Punkte-Indikator unter dem Bild ergänzt (analog zur Web-Version), live bestätigt.
|
||||
- [x] Kommentar Fenster ist nicht im Darkmode
|
||||
-
|
||||
@@ -184,7 +184,16 @@ type PostImagesProps = {
|
||||
onPressImage: (index: number) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* found.md: a multi-image post gave no visual hint it was swipeable — a
|
||||
* viewer would only ever see the first photo unless they already knew to
|
||||
* swipe. Ports web's PostCard indicators (index badge top-right + dots
|
||||
* below) so the carousel is discoverable at a glance.
|
||||
*/
|
||||
function PostImages({ images, width, onPressImage }: PostImagesProps) {
|
||||
const { colors } = useTheme();
|
||||
const [index, setIndex] = useState(0);
|
||||
|
||||
if (images.length === 0) return null;
|
||||
|
||||
if (images.length === 1) {
|
||||
@@ -192,14 +201,54 @@ function PostImages({ images, width, onPressImage }: PostImagesProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollView horizontal pagingEnabled showsHorizontalScrollIndicator={false} style={{ width }}>
|
||||
{images.map((image, index) => (
|
||||
<PostImage key={image.id} image={image} width={width} onPress={() => onPressImage(index)} />
|
||||
))}
|
||||
</ScrollView>
|
||||
<View>
|
||||
<View style={{ width }}>
|
||||
<ScrollView
|
||||
horizontal
|
||||
pagingEnabled
|
||||
showsHorizontalScrollIndicator={false}
|
||||
onMomentumScrollEnd={(e) => setIndex(Math.round(e.nativeEvent.contentOffset.x / width))}
|
||||
>
|
||||
{images.map((image, i) => (
|
||||
<PostImage key={image.id} image={image} width={width} onPress={() => onPressImage(i)} />
|
||||
))}
|
||||
</ScrollView>
|
||||
<View style={multiImageStyles.counterBadge}>
|
||||
<Text style={multiImageStyles.counterText}>
|
||||
{index + 1} / {images.length}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View style={multiImageStyles.dotsRow}>
|
||||
{images.map((_, i) => (
|
||||
<View
|
||||
key={i}
|
||||
style={[
|
||||
multiImageStyles.dot,
|
||||
{ backgroundColor: i === index ? colors.ink : colors.hairlineGray },
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const multiImageStyles = StyleSheet.create({
|
||||
counterBadge: {
|
||||
position: "absolute",
|
||||
top: 8,
|
||||
right: 8,
|
||||
backgroundColor: "rgba(0,0,0,0.5)",
|
||||
borderRadius: radii.sm,
|
||||
paddingHorizontal: 6,
|
||||
paddingVertical: 2,
|
||||
},
|
||||
counterText: { color: "#fff", fontSize: 11 },
|
||||
dotsRow: { flexDirection: "row", justifyContent: "center", alignItems: "center", gap: 6, paddingVertical: 8 },
|
||||
dot: { width: 6, height: 6, borderRadius: 3 },
|
||||
});
|
||||
|
||||
function PostImage({ image, width, onPress }: { image: PostCardImage; width: number; onPress: () => void }) {
|
||||
const rawRatio = image.width && image.height ? image.width / image.height : 1;
|
||||
const aspectRatio = Math.min(1.91, Math.max(0.75, rawRatio));
|
||||
|
||||
Reference in new issue
Block a user