diff --git a/artifacts/postiz-mobile/app/(tabs)/compose.tsx b/artifacts/postiz-mobile/app/(tabs)/compose.tsx index 77138f2..0cbc47e 100644 --- a/artifacts/postiz-mobile/app/(tabs)/compose.tsx +++ b/artifacts/postiz-mobile/app/(tabs)/compose.tsx @@ -56,22 +56,6 @@ type MediaItem = | { type: "local"; uri: string } | { type: "uploaded"; id: string; path: string; workspaceId: string }; -// Maps a type string to a display label, used for grouping within a workspace -function networkLabel(intg: PostizIntegration): string { - const t = (intg.type ?? intg.internalType ?? "").toLowerCase(); - if (t.includes("twitter") || t.includes("x-") || t === "x") return "X / Twitter"; - if (t.includes("instagram")) return "Instagram"; - if (t.includes("linkedin")) return "LinkedIn"; - if (t.includes("facebook")) return "Facebook"; - if (t.includes("tiktok")) return "TikTok"; - if (t.includes("youtube")) return "YouTube"; - if (t.includes("pinterest")) return "Pinterest"; - if (t.includes("mastodon")) return "Mastodon"; - if (t.includes("bluesky") || t.includes("bsky")) return "Bluesky"; - if (t.includes("threads")) return "Threads"; - if (t.includes("reddit")) return "Reddit"; - return "Other"; -} function resolveMediaUrl(path: string, baseUrl: string): string { if (path.startsWith("http://") || path.startsWith("https://")) return path; @@ -156,7 +140,7 @@ export default function ComposeScreen() { staleTime: 60000, }); - // Group: workspace → network label → integrations + // Group: workspace → flat list of integrations const grouped = useMemo(() => { if (!allIntegrations) return []; const byWorkspace = new Map(); @@ -166,21 +150,20 @@ export default function ComposeScreen() { } return workspaces .filter((ws) => byWorkspace.has(ws.id)) - .map((ws) => { - const intgs = byWorkspace.get(ws.id)!; - const byNetwork = new Map(); - for (const intg of intgs) { - const key = networkLabel(intg); - if (!byNetwork.has(key)) byNetwork.set(key, []); - byNetwork.get(key)!.push(intg); - } - return { - workspace: ws, - networks: Array.from(byNetwork.entries()).map(([label, channels]) => ({ label, channels })), - }; - }); + .map((ws) => ({ workspace: ws, channels: byWorkspace.get(ws.id)! })); }, [allIntegrations, workspaces]); + const toggleWorkspace = (wsId: string) => { + const wsChannels = grouped.find((g) => g.workspace.id === wsId)?.channels ?? []; + const allIds = wsChannels.map((c) => c.id); + const allSelected = allIds.every((id) => selectedChannels.includes(id)); + if (allSelected) { + setSelectedChannels((prev) => prev.filter((id) => !allIds.includes(id))); + } else { + setSelectedChannels((prev) => [...new Set([...prev, ...allIds])]); + } + }; + const effectiveCharLimit = useMemo(() => { if (selectedChannels.length === 0 || !allIntegrations) return 3000; const selected = allIntegrations.filter((i) => selectedChannels.includes(i.id)); @@ -552,50 +535,51 @@ export default function ComposeScreen() { ) : ( - {grouped.map(({ workspace, networks }, wsIdx) => ( - 0 && { marginTop: 8 }, - ]} - > - {/* Workspace header */} - - - - {workspace.name} - - + {grouped.map(({ workspace, channels }, wsIdx) => { + const allIds = channels.map((c) => c.id); + const selectedCount = allIds.filter((id) => selectedChannels.includes(id)).length; + const allSelected = selectedCount === allIds.length; + const someSelected = selectedCount > 0 && !allSelected; + return ( + 0 && { marginTop: 8 }, + ]} + > + {/* Workspace header — tap to select/deselect all */} + toggleWorkspace(workspace.id)} + style={[styles.workspaceHeader, { borderBottomColor: colors.border }]} + > + + + {workspace.name} + + + - {/* Network groups */} - - {networks.map(({ label, channels }) => ( - - {networks.length > 1 && ( - - {label} - - )} - - {channels.map((intg) => ( - toggleChannel(intg.id)} - /> - ))} - - - ))} + {/* Flat channel chips */} + + {channels.map((intg) => ( + toggleChannel(intg.id)} + /> + ))} + - - ))} + ); + })} )} @@ -777,10 +761,7 @@ const styles = StyleSheet.create({ borderBottomWidth: StyleSheet.hairlineWidth, }, workspaceName: { fontSize: 11, fontFamily: "Inter_600SemiBold", letterSpacing: 0.5 }, - networkGroups: { padding: 10, gap: 10 }, - networkGroup: { gap: 4 }, - networkLabel: { fontSize: 10, fontFamily: "Inter_500Medium", letterSpacing: 0.4, marginLeft: 2 }, - chipRow: { flexDirection: "row", flexWrap: "wrap", gap: 6 }, + chipRow: { flexDirection: "row", flexWrap: "wrap", gap: 6, padding: 10 }, scheduleRow: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: 16, paddingVertical: 12, borderRadius: 12, borderWidth: 1,