v0.12.47 Add Child alias update
This commit is contained in:
@@ -16,6 +16,7 @@ import GlobalBar from '../components/GlobalBar.jsx';
|
||||
import AboutModal from '../components/AboutModal.jsx';
|
||||
import HelpModal from '../components/HelpModal.jsx';
|
||||
import NavDrawer from '../components/NavDrawer.jsx';
|
||||
import AddChildAliasModal from '../components/AddChildAliasModal.jsx';
|
||||
import SchedulePage from '../components/SchedulePage.jsx';
|
||||
import MobileGroupManager from '../components/MobileGroupManager.jsx';
|
||||
import './Chat.css';
|
||||
@@ -48,6 +49,9 @@ export default function Chat() {
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
const [features, setFeatures] = useState({ branding: false, groupManager: false, scheduleManager: false, appType: 'RosterChirp-Chat', teamToolManagers: [], isHostDomain: false, msgPublic: true, msgGroup: true, msgPrivateGroup: true, msgU2U: true });
|
||||
const [helpDismissed, setHelpDismissed] = useState(true); // true until status loaded
|
||||
const [addChildPending, setAddChildPending] = useState(false); // defer add-child popup until help closes
|
||||
const addChildCheckedRef = useRef(false); // only auto-check aliases once per session
|
||||
const modalRef = useRef(null); // always reflects current modal value in async callbacks
|
||||
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
|
||||
const [showSidebar, setShowSidebar] = useState(true);
|
||||
|
||||
@@ -80,28 +84,31 @@ export default function Chat() {
|
||||
// Keep groupsRef in sync so visibility/reconnect handlers can read current groups
|
||||
useEffect(() => { groupsRef.current = groups; }, [groups]);
|
||||
|
||||
// Load feature flags + current user's group memberships on mount
|
||||
// Load feature flags + current user's group memberships on mount (combined for consistent inGuardiansGroup)
|
||||
const loadFeatures = useCallback(() => {
|
||||
api.getSettings().then(({ settings }) => {
|
||||
setFeatures(prev => ({
|
||||
...prev,
|
||||
branding: settings.feature_branding === 'true',
|
||||
groupManager: settings.feature_group_manager === 'true',
|
||||
scheduleManager: settings.feature_schedule_manager === 'true',
|
||||
appType: settings.app_type || 'RosterChirp-Chat',
|
||||
teamToolManagers: JSON.parse(settings.team_tool_managers || settings.team_group_managers || '[]'),
|
||||
isHostDomain: settings.is_host_domain === 'true',
|
||||
msgPublic: settings.feature_msg_public !== 'false',
|
||||
msgGroup: settings.feature_msg_group !== 'false',
|
||||
msgPrivateGroup: settings.feature_msg_private_group !== 'false',
|
||||
msgU2U: settings.feature_msg_u2u !== 'false',
|
||||
loginType: settings.feature_login_type || 'all_ages',
|
||||
playersGroupId: settings.feature_players_group_id ? parseInt(settings.feature_players_group_id) : null,
|
||||
}));
|
||||
}).catch(() => {});
|
||||
api.getMyUserGroups().then(({ userGroups }) => {
|
||||
setFeatures(prev => ({ ...prev, userGroupMemberships: (userGroups || []).map(g => g.id) }));
|
||||
}).catch(() => {});
|
||||
Promise.all([api.getSettings(), api.getMyUserGroups()])
|
||||
.then(([{ settings: s }, { userGroups }]) => {
|
||||
const memberships = (userGroups || []).map(g => g.id);
|
||||
const guardiansGroupId = s.feature_guardians_group_id ? parseInt(s.feature_guardians_group_id) : null;
|
||||
setFeatures(prev => ({
|
||||
...prev,
|
||||
branding: s.feature_branding === 'true',
|
||||
groupManager: s.feature_group_manager === 'true',
|
||||
scheduleManager: s.feature_schedule_manager === 'true',
|
||||
appType: s.app_type || 'RosterChirp-Chat',
|
||||
teamToolManagers: JSON.parse(s.team_tool_managers || s.team_group_managers || '[]'),
|
||||
isHostDomain: s.is_host_domain === 'true',
|
||||
msgPublic: s.feature_msg_public !== 'false',
|
||||
msgGroup: s.feature_msg_group !== 'false',
|
||||
msgPrivateGroup: s.feature_msg_private_group !== 'false',
|
||||
msgU2U: s.feature_msg_u2u !== 'false',
|
||||
loginType: s.feature_login_type || 'all_ages',
|
||||
playersGroupId: s.feature_players_group_id ? parseInt(s.feature_players_group_id) : null,
|
||||
guardiansGroupId,
|
||||
userGroupMemberships: memberships,
|
||||
inGuardiansGroup: guardiansGroupId ? memberships.includes(guardiansGroupId) : false,
|
||||
}));
|
||||
}).catch(() => {});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -110,6 +117,35 @@ export default function Chat() {
|
||||
return () => window.removeEventListener('rosterchirp:settings-changed', loadFeatures);
|
||||
}, [loadFeatures]);
|
||||
|
||||
// Keep modalRef in sync so async callbacks can read current modal without stale closure
|
||||
useEffect(() => { modalRef.current = modal; }, [modal]);
|
||||
|
||||
// Auto-popup Add Child Alias modal when guardian_only user has no aliases yet
|
||||
useEffect(() => {
|
||||
if (addChildCheckedRef.current) return;
|
||||
if (features.loginType !== 'guardian_only' || !features.inGuardiansGroup) return;
|
||||
addChildCheckedRef.current = true;
|
||||
api.getAliases().then(({ aliases }) => {
|
||||
if (!(aliases || []).length) {
|
||||
if (modalRef.current === 'help') {
|
||||
setAddChildPending(true); // defer until help closes
|
||||
} else if (!modalRef.current) {
|
||||
setModal('addchild');
|
||||
}
|
||||
}
|
||||
}).catch(() => {});
|
||||
}, [features.loginType, features.inGuardiansGroup]);
|
||||
|
||||
// Close help — open deferred add-child popup if pending
|
||||
const handleHelpClose = useCallback(() => {
|
||||
if (addChildPending) {
|
||||
setAddChildPending(false);
|
||||
setModal('addchild');
|
||||
} else {
|
||||
setModal(null);
|
||||
}
|
||||
}, [addChildPending]);
|
||||
|
||||
// Register / refresh push subscription — FCM for Android/Chrome, Web Push for iOS
|
||||
useEffect(() => {
|
||||
if (!('serviceWorker' in navigator)) return;
|
||||
@@ -601,12 +637,14 @@ export default function Chat() {
|
||||
onSettings={() => { setDrawerOpen(false); setModal('settings'); }}
|
||||
onUsers={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('users'); }}
|
||||
onHostPanel={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('hostpanel'); }}
|
||||
onAddChild={() => { setDrawerOpen(false); setModal('addchild'); }}
|
||||
features={features} currentPage={page} isMobile={isMobile}
|
||||
unreadMessages={hasUnreadChat} unreadGroupMessages={hasUnreadGroupMessages} />
|
||||
{modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />}
|
||||
{modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />}
|
||||
{modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />}
|
||||
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
|
||||
{modal === 'help' && <HelpModal onClose={handleHelpClose} dismissed={helpDismissed} />}
|
||||
{modal === 'addchild' && <AddChildAliasModal onClose={() => setModal(null)} />}
|
||||
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
|
||||
|
||||
</div>
|
||||
@@ -630,12 +668,14 @@ export default function Chat() {
|
||||
onSettings={() => { setDrawerOpen(false); setModal('settings'); }}
|
||||
onUsers={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('users'); }}
|
||||
onHostPanel={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('hostpanel'); }}
|
||||
onAddChild={() => { setDrawerOpen(false); setModal('addchild'); }}
|
||||
features={features} currentPage={page} isMobile={isMobile}
|
||||
unreadMessages={hasUnreadChat} unreadGroupMessages={hasUnreadGroupMessages} />
|
||||
{modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />}
|
||||
{modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />}
|
||||
{modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />}
|
||||
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
|
||||
{modal === 'help' && <HelpModal onClose={handleHelpClose} dismissed={helpDismissed} />}
|
||||
{modal === 'addchild' && <AddChildAliasModal onClose={() => setModal(null)} />}
|
||||
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
|
||||
|
||||
</div>
|
||||
@@ -689,12 +729,14 @@ export default function Chat() {
|
||||
onSettings={() => { setDrawerOpen(false); setModal('settings'); }}
|
||||
onUsers={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('users'); }}
|
||||
onHostPanel={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('hostpanel'); }}
|
||||
onAddChild={() => { setDrawerOpen(false); setModal('addchild'); }}
|
||||
features={features} currentPage={page} isMobile={isMobile}
|
||||
unreadMessages={hasUnreadChat} unreadGroupMessages={hasUnreadGroupMessages} />
|
||||
{modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />}
|
||||
{modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />}
|
||||
{modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />}
|
||||
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
|
||||
{modal === 'help' && <HelpModal onClose={handleHelpClose} dismissed={helpDismissed} />}
|
||||
{modal === 'addchild' && <AddChildAliasModal onClose={() => setModal(null)} />}
|
||||
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
|
||||
{modal === 'newchat' && <NewChatModal features={features} onClose={() => setModal(null)} onCreated={(g) => { loadGroups(); setModal(null); setActiveGroupId(g.id); setPage('chat'); }} />}
|
||||
|
||||
@@ -721,6 +763,7 @@ export default function Chat() {
|
||||
onSettings={() => { setDrawerOpen(false); setModal('settings'); }}
|
||||
onUsers={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('users'); }}
|
||||
onHostPanel={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('hostpanel'); }}
|
||||
onAddChild={() => { setDrawerOpen(false); setModal('addchild'); }}
|
||||
features={features}
|
||||
currentPage={page}
|
||||
isMobile={isMobile}
|
||||
@@ -728,7 +771,8 @@ export default function Chat() {
|
||||
{modal === 'profile' && <ProfileModal onClose={() => setModal(null)} />}
|
||||
{modal === 'settings' && <SettingsModal onClose={() => setModal(null)} onFeaturesChanged={setFeatures} />}
|
||||
{modal === 'branding' && <BrandingModal onClose={() => setModal(null)} />}
|
||||
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
|
||||
{modal === 'help' && <HelpModal onClose={handleHelpClose} dismissed={helpDismissed} />}
|
||||
{modal === 'addchild' && <AddChildAliasModal onClose={() => setModal(null)} />}
|
||||
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
|
||||
|
||||
</div>
|
||||
@@ -760,6 +804,7 @@ export default function Chat() {
|
||||
onSettings={() => { setDrawerOpen(false); setModal('settings'); }}
|
||||
onUsers={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('users'); }}
|
||||
onHostPanel={() => { setDrawerOpen(false); setActiveGroupId(null); setChatHasText(false); setPage('hostpanel'); }}
|
||||
onAddChild={() => { setDrawerOpen(false); setModal('addchild'); }}
|
||||
features={features}
|
||||
currentPage={page}
|
||||
isMobile={isMobile}
|
||||
@@ -774,7 +819,8 @@ export default function Chat() {
|
||||
</div>
|
||||
)}
|
||||
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
|
||||
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
|
||||
{modal === 'help' && <HelpModal onClose={handleHelpClose} dismissed={helpDismissed} />}
|
||||
{modal === 'addchild' && <AddChildAliasModal onClose={() => setModal(null)} />}
|
||||
|
||||
</div>
|
||||
);
|
||||
@@ -842,7 +888,8 @@ export default function Chat() {
|
||||
|
||||
{modal === 'newchat' && <NewChatModal features={features} onClose={() => setModal(null)} onCreated={(g) => { loadGroups(); setModal(null); setActiveGroupId(g.id); }} />}
|
||||
{modal === 'about' && <AboutModal onClose={() => setModal(null)} />}
|
||||
{modal === 'help' && <HelpModal onClose={() => setModal(null)} dismissed={helpDismissed} />}
|
||||
{modal === 'help' && <HelpModal onClose={handleHelpClose} dismissed={helpDismissed} />}
|
||||
{modal === 'addchild' && <AddChildAliasModal onClose={() => setModal(null)} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user