diff --git a/package.json b/package.json
index 312657f..7e364f4 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "sociowire-frontend",
"private": true,
- "version": "0.0.114",
+ "version": "0.0.115",
"type": "module",
"scripts": {
"dev": "vite --host 0.0.0.0",
diff --git a/src/App.jsx b/src/App.jsx
index ae0b653..9de4b84 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -7,7 +7,7 @@ import ContentFilters from "./components/Filters/ContentFilters";
import IslandViewer from "./components/Island/IslandViewer";
import ChatContainer from "./components/Chat/ChatContainer";
import PostDetailModal from "./components/Posts/PostDetailModal";
-import { CreatePostFAB } from "./components/Posts/PostComposer";
+import PostComposer, { CreatePostFAB } from "./components/Posts/PostComposer";
import { AnimatePresence, motion } from "framer-motion";
import { fetchIslandByUsername } from "./api/client";
@@ -66,6 +66,10 @@ export default function App() {
// Island Viewer state (for viewing individual islands)
const [selectedIsland, setSelectedIsland] = useState(null);
+ // Post Composer state (for creating posts with island context)
+ const [showPostComposer, setShowPostComposer] = useState(false);
+ const [postComposerIsland, setPostComposerIsland] = useState(null);
+
// Post detail modal state (triggered from map markers)
const [detailPost, setDetailPost] = useState(null);
@@ -152,16 +156,30 @@ export default function App() {
return () => window.removeEventListener("sw:openPostDetail", handleOpenPostDetail);
}, []);
- // Listen for island post creation event
+ // Listen for post creator events
useEffect(() => {
+ // Handle opening post composer with island context
+ const handleOpenPostCreator = (e) => {
+ const { island_username } = e.detail || {};
+ setPostComposerIsland(island_username || null);
+ setShowPostComposer(true);
+ };
+
+ // Legacy island post event
const handleIslandPost = (e) => {
const { island } = e.detail || {};
if (island) {
- window.location.href = `/island/${island}?create=true`;
+ setPostComposerIsland(island);
+ setShowPostComposer(true);
}
};
+
+ window.addEventListener('sw:openPostCreator', handleOpenPostCreator);
window.addEventListener('sociowire:create-post', handleIslandPost);
- return () => window.removeEventListener('sociowire:create-post', handleIslandPost);
+ return () => {
+ window.removeEventListener('sw:openPostCreator', handleOpenPostCreator);
+ window.removeEventListener('sociowire:create-post', handleIslandPost);
+ };
}, []);
// World navigation handlers
@@ -362,6 +380,26 @@ export default function App() {
)}
+ {/* Post Composer Modal (for island posts) */}
+
+ {showPostComposer && (
+ {
+ setShowPostComposer(false);
+ setPostComposerIsland(null);
+ }}
+ onPostCreated={(newPost) => {
+ // Refresh wall posts if on map view
+ if (currentView === 'map') {
+ setWallPosts((prev) => [newPost, ...prev]);
+ }
+ }}
+ />
+ )}
+
+
{/* Floating Action Button for creating posts */}
diff --git a/src/components/Posts/PostComposer.jsx b/src/components/Posts/PostComposer.jsx
index 26684bd..406498e 100644
--- a/src/components/Posts/PostComposer.jsx
+++ b/src/components/Posts/PostComposer.jsx
@@ -15,7 +15,7 @@ const CATEGORIES = [
{ id: "weather", icon: "fa-cloud-sun", label: "Weather", color: "from-sky-500 to-blue-500" },
];
-export default function PostComposer({ onClose, onPostCreated }) {
+export default function PostComposer({ onClose, onPostCreated, islandUsername }) {
const { t } = useTranslation();
const { token, username, isAuthenticated } = useAuth();
const fileInputRef = useRef(null);
@@ -159,6 +159,11 @@ export default function PostComposer({ onClose, onPostCreated }) {
payload.location_name = locationName || "";
}
+ // Add island context if posting to an island
+ if (islandUsername) {
+ payload.island_username = islandUsername;
+ }
+
// Add media URLs
if (uploadedMedia.length > 0) {
const firstMedia = uploadedMedia[0];
@@ -493,10 +498,20 @@ export default function PostComposer({ onClose, onPostCreated }) {
}
// Floating Action Button for creating posts - triggers the map's create post flow
+// Context-aware: if viewing an island, includes island info
export function CreatePostFAB() {
const handleClick = () => {
- // Dispatch event to open the map's post creation modal
- window.dispatchEvent(new CustomEvent("sw:openMapPostCreator"));
+ // Check if we're viewing an island
+ const islandContext = window.__activeIslandContext;
+ if (islandContext && islandContext.isOwner) {
+ // Open post creator with island context
+ window.dispatchEvent(new CustomEvent("sw:openPostCreator", {
+ detail: { island_username: islandContext.username }
+ }));
+ } else {
+ // Default: open map's post creation modal
+ window.dispatchEvent(new CustomEvent("sw:openMapPostCreator"));
+ }
};
return (
diff --git a/src/components/World/IslandsWorld.jsx b/src/components/World/IslandsWorld.jsx
index da2182b..7ec9832 100644
--- a/src/components/World/IslandsWorld.jsx
+++ b/src/components/World/IslandsWorld.jsx
@@ -30,6 +30,21 @@ export default function IslandsWorld({ theme, onIslandClick, onOpenMap, onOpenPl
const [islandPosts, setIslandPosts] = useState([]);
const [loadingPosts, setLoadingPosts] = useState(false);
+ // Set global island context when zoomed (for FAB to use)
+ useEffect(() => {
+ if (zoomedIsland) {
+ window.__activeIslandContext = {
+ username: zoomedIsland.username,
+ isOwner: username && username.toLowerCase() === (zoomedIsland.username || '').toLowerCase()
+ };
+ } else {
+ window.__activeIslandContext = null;
+ }
+ return () => {
+ window.__activeIslandContext = null;
+ };
+ }, [zoomedIsland, username]);
+
// Fetch islands
useEffect(() => {
let mounted = true;
@@ -289,19 +304,9 @@ export default function IslandsWorld({ theme, onIslandClick, onOpenMap, onOpenPl
{username && username.toLowerCase() === (zoomedIsland.username || '').toLowerCase() && (
- <>
-
-
- >
+
)}
@@ -318,14 +323,7 @@ export default function IslandsWorld({ theme, onIslandClick, onOpenMap, onOpenPl
{t('worlds.emptyIsland')}
{username && username.toLowerCase() === (zoomedIsland.username || '').toLowerCase() && (
-
+ {t('worlds.useButtonToPost')}
)}
)}
@@ -334,20 +332,6 @@ export default function IslandsWorld({ theme, onIslandClick, onOpenMap, onOpenPl
))}
- {/* Floating create post button for island owner */}
- {username && username.toLowerCase() === (zoomedIsland.username || '').toLowerCase() && (
-
- )}
)}