Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added apps/web/public/eventools-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
84 changes: 84 additions & 0 deletions apps/web/src/components/DeprecationNoticeModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React from "react";
import { X, ExternalLink, Download, Server } from "lucide-react";

interface DeprecationNoticeModalProps {
isOpen: boolean;
onClose: () => void;
}

const DeprecationNoticeModal: React.FC<DeprecationNoticeModalProps> = ({ isOpen, onClose }) => {
if (!isOpen) return null;

return (
<div
className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4"
onClick={onClose}
>
<div
className="bg-gray-950/95 backdrop-blur-lg border border-gray-700 rounded-lg shadow-2xl shadow-indigo-900/20 max-w-lg w-full"
onClick={(e) => e.stopPropagation()}
>
<div className="p-6">
<div className="flex justify-end mb-2">
<button
onClick={onClose}
className="p-2 rounded-full hover:bg-gray-800 transition-colors"
>
<X className="h-5 w-5 text-gray-400" />
</button>
</div>

<div className="flex flex-col items-center text-center">
<img src="/eventools-logo.png" alt="eventools" className="h-16 w-16 mb-6" />

<h2 className="text-2xl font-bold text-white mb-4">We're Building Something New!</h2>

<div className="space-y-4 text-gray-300">
<p>
We're excited to announce that we're working on{" "}
<span className="text-indigo-400 font-semibold">eventools</span> — the next
generation of event production tools.
</p>

<p>SoundDocs will be transitioning to eventools in the near future.</p>

<div className="bg-gray-800/50 rounded-lg p-4 text-left">
<p className="text-white font-medium mb-3">Don't worry — we'll provide:</p>
<ul className="space-y-2">
<li className="flex items-start">
<Download className="h-5 w-5 text-indigo-400 mr-3 mt-0.5 flex-shrink-0" />
<span>Instructions for downloading your data</span>
</li>
<li className="flex items-start">
<Server className="h-5 w-5 text-indigo-400 mr-3 mt-0.5 flex-shrink-0" />
<span>Self-hosting documentation for SoundDocs</span>
</li>
</ul>
</div>
</div>

<div className="mt-6 flex flex-col sm:flex-row gap-3 w-full">
<a
href="https://eventools.io"
target="_blank"
rel="noopener noreferrer"
className="flex-1 inline-flex items-center justify-center px-6 py-3 bg-indigo-600 hover:bg-indigo-500 text-white font-semibold rounded-lg transition-colors"
>
Sign Up for eventools Beta
<ExternalLink className="h-4 w-4 ml-2" />
</a>
<button
onClick={onClose}
className="flex-1 px-6 py-3 bg-gray-800 hover:bg-gray-700 text-white rounded-lg transition-colors"
>
Got it, thanks
</button>
</div>
</div>
</div>
</div>
</div>
);
};

export default DeprecationNoticeModal;
21 changes: 21 additions & 0 deletions apps/web/src/hooks/useDeprecationNotice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useState, useEffect } from "react";

const DEPRECATION_NOTICE_KEY = "sounddocs-deprecation-notice-dismissed";

export const useDeprecationNotice = () => {
const [isOpen, setIsOpen] = useState(false);

useEffect(() => {
const dismissed = localStorage.getItem(DEPRECATION_NOTICE_KEY) === "true";
if (!dismissed) {
setIsOpen(true);
}
}, []);

const onClose = () => {
localStorage.setItem(DEPRECATION_NOTICE_KEY, "true");
setIsOpen(false);
};

return { isOpen, onClose };
};
5 changes: 5 additions & 0 deletions apps/web/src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import Header from "../components/Header";
import Footer from "../components/Footer";
import AcoustIqBanner from "../components/AcoustIqBanner";
import DeprecationNoticeModal from "@/components/DeprecationNoticeModal";
import { useDeprecationNotice } from "@/hooks/useDeprecationNotice";
import {
Info,
Loader,
Expand All @@ -21,6 +23,8 @@
const Dashboard = () => {
const navigate = useNavigate();
const { user: authUser, loading: authLoading } = useAuth();
const { isOpen: showDeprecationModal, onClose: handleDismissDeprecation } =
useDeprecationNotice();

const [loading, setLoading] = useState(true);
const [userName, setUserName] = useState<string>("");
Expand Down Expand Up @@ -85,7 +89,7 @@
if (error) throw error;
// userName will be updated by the useEffect listening to authUser changes
setIsEditingName(false);
} catch (error: any) {

Check failure on line 92 in apps/web/src/pages/Dashboard.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type
console.error("Error updating user name:", error);
setNameUpdateError(error.message || "Failed to update name. Please try again.");
} finally {
Expand Down Expand Up @@ -264,6 +268,7 @@
</div>
</main>
<Footer />
<DeprecationNoticeModal isOpen={showDeprecationModal} onClose={handleDismissDeprecation} />
</div>
);
};
Expand Down
6 changes: 6 additions & 0 deletions apps/web/src/pages/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ import Features from "../components/Features";
import TrustedBy from "../components/TrustedBy";
import GetStarted from "../components/GetStarted";
import Footer from "../components/Footer";
import DeprecationNoticeModal from "@/components/DeprecationNoticeModal";
import { useDeprecationNotice } from "@/hooks/useDeprecationNotice";

const Landing: React.FC = () => {
const { isOpen: showDeprecationModal, onClose: handleDismissDeprecation } =
useDeprecationNotice();

// On page load or when changing themes, best practice for accessibility
useEffect(() => {
document.title = "SoundDocs | Pro Audio & Event Production Documentation";
Expand All @@ -34,6 +39,7 @@ const Landing: React.FC = () => {
<GetStarted />
</main>
<Footer />
<DeprecationNoticeModal isOpen={showDeprecationModal} onClose={handleDismissDeprecation} />
</>
);
};
Expand Down
74 changes: 37 additions & 37 deletions apps/web/src/pages/StagePlotEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
// const screenSize = useScreenSize(); // Removed
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [stagePlot, setStagePlot] = useState<{ stage_size?: string; [k: string]: any } | null>(

Check failure on line 117 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type
null,
);
const [stageSize, setStageSize] = useState<StageSize>(parseStageSize("medium-wide"));
Expand All @@ -129,7 +129,7 @@
const [isDraggingImage, setIsDraggingImage] = useState(false);
const [imageUrl, setImageUrl] = useState<string | null>(null);
const [isSharedEdit, setIsSharedEdit] = useState(false);
const [shareLink, setShareLink] = useState<any>(null);

Check failure on line 132 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type

// Collaboration state
const [showHistory, setShowHistory] = useState(false);
Expand Down Expand Up @@ -158,43 +158,6 @@
// Screen size no longer forces view mode.
}, [location.pathname]);

// Initialize local name from stagePlot.name when document loads
useEffect(() => {
if (stagePlot?.name && !localNameInitialized) {
setLocalName(stagePlot.name);
setLocalNameInitialized(true);
}
}, [stagePlot?.name, localNameInitialized]);

// Debounced sync: Update stagePlot.name after user stops typing (500ms delay)
useEffect(() => {
if (!localNameInitialized) return;

const handler = setTimeout(() => {
if (localName !== stagePlot?.name) {
setStagePlot((prev: any) => ({ ...prev, name: localName }));

// Broadcast name change to other collaborators
if (collaborationEnabled && broadcast) {
broadcast({
type: "field_update",
field: "name",
value: localName,
});
}
}
}, 500);

return () => clearTimeout(handler);
}, [
localName,
localNameInitialized,
stagePlot?.name,
setStagePlot,
collaborationEnabled,
broadcast,
]);

// Enable collaboration for existing documents (including edit-mode shared links)
// For shared links, id will be undefined, so we check stagePlot?.id instead
// For edit-mode shared links, allow collaboration even without authentication
Expand Down Expand Up @@ -287,7 +250,7 @@
if (payload.type === "field_update" && payload.field) {
// Handle different field updates
if (payload.field === "name") {
setStagePlot((prev: any) => ({ ...prev, name: payload.value }));

Check failure on line 253 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type
// Update local name state when remote changes arrive
setLocalName(payload.value);
} else if (payload.field === "elements") {
Expand All @@ -301,7 +264,7 @@
} else if (payload.field === "backgroundOpacity") {
setBackgroundOpacity(payload.value);
} else {
setStagePlot((prev: any) => ({

Check failure on line 267 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type
...prev,
[payload.field!]: payload.value,
}));
Expand All @@ -311,11 +274,48 @@
});

// Presence hook
const { setEditingField } = usePresence({

Check failure on line 277 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

'setEditingField' is assigned a value but never used
channel: null, // Will be set up when collaboration channels are ready
userId: effectiveUserId,
});

// Initialize local name from stagePlot.name when document loads
useEffect(() => {
if (stagePlot?.name && !localNameInitialized) {
setLocalName(stagePlot.name);
setLocalNameInitialized(true);
}
}, [stagePlot?.name, localNameInitialized]);

// Debounced sync: Update stagePlot.name after user stops typing (500ms delay)
useEffect(() => {
if (!localNameInitialized) return;

const handler = setTimeout(() => {
if (localName !== stagePlot?.name) {
setStagePlot((prev: any) => ({ ...prev, name: localName }));

Check failure on line 296 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type

// Broadcast name change to other collaborators
if (collaborationEnabled && broadcast) {
broadcast({
type: "field_update",
field: "name",
value: localName,
});
}
}
}, 500);

return () => clearTimeout(handler);
}, [
localName,
localNameInitialized,
stagePlot?.name,
setStagePlot,
collaborationEnabled,
broadcast,
]);

// Real-time database subscription for syncing changes across users
useEffect(() => {
if (!collaborationEnabled || !stagePlot?.id) {
Expand Down Expand Up @@ -367,16 +367,16 @@
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [forceSave, collaborationEnabled, isViewMode]);

Check warning on line 370 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

React Hook useEffect has a missing dependency: 'handleSave'. Either include it or remove the dependency array

useEffect(() => {
const fetchStagePlotData = async () => {
setLoading(true);
const currentPathIsSharedEdit = location.pathname.includes("/shared/stage-plot/edit/");

const processFetchedElements = (fetchedElements: any[] | undefined) => {

Check failure on line 377 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type
if (fetchedElements && Array.isArray(fetchedElements)) {
return fetchedElements.map((el: any) => ({

Check failure on line 379 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

Unexpected any. Specify a different type
...el,
icon: undefined,
labelVisible: el.labelVisible === undefined ? true : el.labelVisible,
Expand Down Expand Up @@ -425,7 +425,7 @@
// setIsSharedEdit(true); // Already set in the other useEffect
setLoading(false);
return;
} catch (error: any) {

Check failure on line 428 in apps/web/src/pages/StagePlotEditor.tsx

View workflow job for this annotation

GitHub Actions / typescript-checks

'error' is defined but never used
navigate("/dashboard");
setLoading(false);
return;
Expand Down
Loading