Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
b0c0b2c543
commit
941107f71d
@ -1,11 +1,11 @@
|
||||
vite.svg,499162500000,699a02e0e68a579f687d364bbbe7633161244f35af068220aee37b1b33dfb3c7
|
||||
index.html,1752878330027,5f203c00faf9fcc6e4b55be0b7ffa09282fc25dc3a7624baf25b7f6b43a06595
|
||||
assets/swipe-back-g3JVbAcT.js,1752878330027,07abc4e68422342d6ba852b5cf93f08d37d594a29c0f8172471242ecbecacd47
|
||||
assets/status-tap-C7usLbRw.js,1752878330027,faeed28b943d98d69228f71c2de4d6d63c177dc89155e315f482c62bf188ab19
|
||||
assets/md.transition-B9W-8lgj.js,1752878330027,78652f50e41d7eff5a7fd00e89bb7e334a7374fa046174e39398a874d2c15fdc
|
||||
assets/input-shims-DVm_rrIi.js,1752878330027,541fc90a960a383cbfa6fd1a75c3c9f17455f20614e82362aa83aeb89ee1cad1
|
||||
assets/ios.transition-BIV5Z5Yc.js,1752878330027,b3510ecbd37d95bcce04934d72822d2f2b4d8c64fa0eff6262fa3b5bd20d4490
|
||||
assets/index7-CZh37Dt9.js,1752878330027,036646be1f60e2114fbfd8a091b9e395ffa6ebf3188331bf54f576e62b393e8d
|
||||
assets/index-B7vPvsG_.css,1752878330026,dbc57fb127dc9dde819d6ce6a258663f05013f29ec8905f282fe0087d44faaff
|
||||
assets/focus-visible-supuXXMI.js,1752878330028,df9266429356671847fa2c8123e1564bae645f75df3094f0055c365fa2beae28
|
||||
assets/index-D2b6SXwC.js,1752878330028,184886780ed3e8ccad54be62237fcb6fc9fefcec6110306d8f46184faebe69a9
|
||||
index.html,1752880425099,3a9ff00c2fe67bff1d22bcc3cc350fe57f13ce7d96e0a0b0831b810c3ae4f383
|
||||
assets/swipe-back-Cn4amxp6.js,1752880425099,293102efce4c0ebfa19f0113958fb5c5b38654c7e86ba695e2ab773ddf43825a
|
||||
assets/status-tap-oQwstaDy.js,1752880425099,7801b76a10c12c5e19d0aaf9ad8966e816479d4ac5ec10270999be4a7c2c6609
|
||||
assets/ios.transition-B2qy1sQZ.js,1752880425103,bc9e64075ed6cea888f669b0814ccc5b444a8e3c0e16e2faa2abc738c8bfe2f4
|
||||
assets/md.transition-BsNej5jc.js,1752880425102,7aa0dc9dabdd1b380bed881251283974f97b2579f3c291326ace89d21e44a9eb
|
||||
assets/input-shims-Do83niGH.js,1752880425099,6fe1bea0b42a375dccb36a672f85ce47ffba6269f2eff1d006e241c615733144
|
||||
assets/index7-Tu8W0Nty.js,1752880425099,b5ab642da21be8211c86d4d3711e683192a1e7c5abe533782aa2735277254993
|
||||
assets/focus-visible-supuXXMI.js,1752880425104,df9266429356671847fa2c8123e1564bae645f75df3094f0055c365fa2beae28
|
||||
assets/index-CIlFtBnY.css,1752880425099,8249b3e00a114a2826408f28ca203fd75157b2e0c376588cc30170ebb5c4cb18
|
||||
assets/index-C9D3R5Ik.js,1752880425100,e69e0e2e53eddc844e5f71df421c9bfd01f054468db1f97053cca0462591b178
|
||||
|
||||
@ -64,16 +64,29 @@ const Navigation: React.FC = () => {
|
||||
top: 0,
|
||||
height: '100vh',
|
||||
width: '256px',
|
||||
backgroundColor: 'white',
|
||||
backgroundColor: 'var(--ion-background-color)',
|
||||
boxShadow: '2px 0 8px rgba(0,0,0,0.1)',
|
||||
zIndex: 1000,
|
||||
borderRight: '1px solid #e5e7eb',
|
||||
borderRight: '1px solid var(--ion-border-color)',
|
||||
overflowY: 'auto'
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: '16px', borderBottom: '1px solid #e5e7eb', backgroundColor: '#f9fafb' }}>
|
||||
<h2 style={{ fontSize: '18px', fontWeight: '600', color: '#1f2937', margin: 0 }}>Karaoke</h2>
|
||||
<p style={{ fontSize: '14px', color: '#6b7280', margin: '4px 0 0 0' }}>Singer: Matt</p>
|
||||
<div style={{
|
||||
padding: '16px',
|
||||
borderBottom: '1px solid var(--ion-border-color)',
|
||||
backgroundColor: 'var(--ion-color-light)'
|
||||
}}>
|
||||
<h2 style={{
|
||||
fontSize: '18px',
|
||||
fontWeight: '600',
|
||||
color: 'var(--ion-text-color)',
|
||||
margin: 0
|
||||
}}>Karaoke</h2>
|
||||
<p style={{
|
||||
fontSize: '14px',
|
||||
color: 'var(--ion-color-medium)',
|
||||
margin: '4px 0 0 0'
|
||||
}}>Singer: Matt</p>
|
||||
</div>
|
||||
<nav style={{ marginTop: '16px' }}>
|
||||
{navItems.map((item) => (
|
||||
@ -85,14 +98,14 @@ const Navigation: React.FC = () => {
|
||||
alignItems: 'center',
|
||||
padding: '12px 16px',
|
||||
cursor: 'pointer',
|
||||
backgroundColor: location.pathname === item.path ? '#dbeafe' : 'transparent',
|
||||
color: location.pathname === item.path ? '#2563eb' : '#374151',
|
||||
borderRight: location.pathname === item.path ? '2px solid #2563eb' : 'none',
|
||||
backgroundColor: location.pathname === item.path ? 'var(--ion-color-primary-tint)' : 'transparent',
|
||||
color: location.pathname === item.path ? 'var(--ion-color-primary)' : 'var(--ion-text-color)',
|
||||
borderRight: location.pathname === item.path ? '2px solid var(--ion-color-primary)' : 'none',
|
||||
transition: 'background-color 0.2s, color 0.2s'
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
if (location.pathname !== item.path) {
|
||||
e.currentTarget.style.backgroundColor = '#f3f4f6';
|
||||
e.currentTarget.style.backgroundColor = 'var(--ion-color-light)';
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
@ -115,7 +128,7 @@ const Navigation: React.FC = () => {
|
||||
|
||||
{/* Player Controls */}
|
||||
<div style={{ marginTop: 'auto', padding: '16px' }}>
|
||||
<PlayerControls variant="dark" />
|
||||
<PlayerControls />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -135,9 +148,22 @@ const Navigation: React.FC = () => {
|
||||
>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<div style={{ padding: '16px', borderBottom: '1px solid #e5e7eb', backgroundColor: '#f9fafb' }}>
|
||||
<h2 style={{ fontSize: '18px', fontWeight: '600', color: '#1f2937', margin: 0 }}>Karaoke</h2>
|
||||
<p style={{ fontSize: '14px', color: '#6b7280', margin: '4px 0 0 0' }}>Singer: Matt</p>
|
||||
<div style={{
|
||||
padding: '16px',
|
||||
borderBottom: '1px solid var(--ion-border-color)',
|
||||
backgroundColor: 'var(--ion-color-light)'
|
||||
}}>
|
||||
<h2 style={{
|
||||
fontSize: '18px',
|
||||
fontWeight: '600',
|
||||
color: 'var(--ion-text-color)',
|
||||
margin: 0
|
||||
}}>Karaoke</h2>
|
||||
<p style={{
|
||||
fontSize: '14px',
|
||||
color: 'var(--ion-color-medium)',
|
||||
margin: '4px 0 0 0'
|
||||
}}>Singer: Matt</p>
|
||||
</div>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
@ -158,7 +184,7 @@ const Navigation: React.FC = () => {
|
||||
|
||||
{/* Player Controls for Mobile */}
|
||||
<div style={{ padding: '16px' }}>
|
||||
<PlayerControls variant="dark" />
|
||||
<PlayerControls />
|
||||
</div>
|
||||
</IonContent>
|
||||
</IonMenu>
|
||||
|
||||
@ -1,25 +1,23 @@
|
||||
import React from 'react';
|
||||
import { IonCard, IonCardContent, IonChip, IonIcon } from '@ionic/react';
|
||||
import { playOutline, pauseOutline, stopOutline, play, pause, stop } from 'ionicons/icons';
|
||||
import ActionButton from './ActionButton';
|
||||
import { play, pause, stop } from 'ionicons/icons';
|
||||
import { useAppSelector } from '../../redux';
|
||||
import { selectPlayerState, selectIsAdmin, selectQueueLength } from '../../redux';
|
||||
import { selectIsAdmin, selectPlayerState, selectQueueLength, selectControllerName } from '../../redux';
|
||||
import { playerService } from '../../firebase/services';
|
||||
import { selectControllerName } from '../../redux';
|
||||
import { debugLog } from '../../utils/logger';
|
||||
import { useToast } from '../../hooks/useToast';
|
||||
import { PlayerState } from '../../types';
|
||||
import ActionButton from './ActionButton';
|
||||
import { useToast } from '../../hooks/useToast';
|
||||
import { debugLog } from '../../utils/logger';
|
||||
|
||||
interface PlayerControlsProps {
|
||||
className?: string;
|
||||
variant?: 'light' | 'dark';
|
||||
}
|
||||
|
||||
const PlayerControls: React.FC<PlayerControlsProps> = ({ className = '', variant = 'light' }) => {
|
||||
const playerState = useAppSelector(selectPlayerState);
|
||||
const PlayerControls: React.FC<PlayerControlsProps> = ({ className = '' }) => {
|
||||
const isAdmin = useAppSelector(selectIsAdmin);
|
||||
const controllerName = useAppSelector(selectControllerName);
|
||||
const playerState = useAppSelector(selectPlayerState);
|
||||
const queueLength = useAppSelector(selectQueueLength);
|
||||
const controllerName = useAppSelector(selectControllerName);
|
||||
const { showSuccess, showError } = useToast();
|
||||
|
||||
// Debug logging
|
||||
@ -85,92 +83,12 @@ const PlayerControls: React.FC<PlayerControlsProps> = ({ className = '', variant
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusText = () => {
|
||||
switch (currentState) {
|
||||
case PlayerState.playing:
|
||||
return 'Currently Playing';
|
||||
case PlayerState.paused:
|
||||
return 'Currently Paused';
|
||||
default:
|
||||
return 'Currently Stopped';
|
||||
}
|
||||
};
|
||||
|
||||
// Dark mode variant
|
||||
if (variant === 'dark') {
|
||||
return (
|
||||
<div className={`bg-black text-white ${className}`}>
|
||||
{/* Status Text */}
|
||||
<h3 className="text-lg font-bold">{getStatusText()}</h3>
|
||||
|
||||
{/* Control Buttons */}
|
||||
<div>
|
||||
{currentState === PlayerState.playing ? (
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:bg-gray-800"
|
||||
style={{ padding: '12px 0px' }}
|
||||
onClick={handlePause}
|
||||
>
|
||||
<IonIcon
|
||||
icon={pauseOutline}
|
||||
style={{
|
||||
marginRight: '12px',
|
||||
fontSize: '24px'
|
||||
}}
|
||||
/>
|
||||
<span style={{ fontWeight: '500' }}>Pause</span>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:bg-gray-800"
|
||||
style={{ padding: '12px 0px' }}
|
||||
onClick={handlePlay}
|
||||
>
|
||||
<IonIcon
|
||||
icon={playOutline}
|
||||
style={{
|
||||
marginRight: '12px',
|
||||
fontSize: '24px'
|
||||
}}
|
||||
/>
|
||||
<span style={{ fontWeight: '500' }}>Play</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{currentState !== PlayerState.stopped && (
|
||||
<div
|
||||
className="flex items-center cursor-pointer hover:bg-gray-800"
|
||||
style={{ padding: '12px 0px' }}
|
||||
onClick={handleStop}
|
||||
>
|
||||
<IonIcon
|
||||
icon={stopOutline}
|
||||
style={{
|
||||
marginRight: '12px',
|
||||
fontSize: '24px'
|
||||
}}
|
||||
/>
|
||||
<span style={{ fontWeight: '500' }}>Stop</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!hasSongsInQueue && (
|
||||
<div style={{ padding: '12px 0px' }} className="text-xs text-gray-400">
|
||||
Add songs to queue to enable playback controls
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Light mode variant (original)
|
||||
return (
|
||||
<IonCard className={className}>
|
||||
<IonCardContent>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<h3 className="text-lg font-medium text-gray-900">Player Controls</h3>
|
||||
<h3 className="text-lg font-medium">Player Controls</h3>
|
||||
<IonChip color={getStateColor()}>
|
||||
{currentState}
|
||||
</IonChip>
|
||||
@ -208,7 +126,7 @@ const PlayerControls: React.FC<PlayerControlsProps> = ({ className = '', variant
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 text-xs text-gray-500 text-center">
|
||||
<div className="mt-3 text-xs text-center">
|
||||
Admin controls - Only visible to admin users
|
||||
{!hasSongsInQueue && (
|
||||
<div className="mt-1 text-orange-600">
|
||||
|
||||
@ -11,11 +11,26 @@
|
||||
@import '@ionic/react/css/flex-utils.css';
|
||||
@import '@ionic/react/css/display.css';
|
||||
|
||||
/* Dark mode support - system preference */
|
||||
@import '@ionic/react/css/palettes/dark.system.css';
|
||||
|
||||
/* Tailwind CSS - comes after Ionic to avoid overriding essential Ionic styles */
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* Dark mode detection */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--ion-color-primary: #3880ff;
|
||||
--ion-color-primary-rgb: 56, 128, 255;
|
||||
--ion-color-primary-contrast: #ffffff;
|
||||
--ion-color-primary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-shade: #3171e0;
|
||||
--ion-color-primary-tint: #4c8dff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure menu button is visible */
|
||||
ion-menu-button {
|
||||
--color: var(--ion-color-primary);
|
||||
@ -36,7 +51,7 @@ ion-menu {
|
||||
|
||||
/* Ensure modal content is visible */
|
||||
ion-modal ion-content {
|
||||
--background: var(--ion-background-color, #ffffff);
|
||||
--background: var(--ion-background-color);
|
||||
}
|
||||
|
||||
ion-modal ion-list {
|
||||
@ -45,7 +60,7 @@ ion-modal ion-list {
|
||||
|
||||
/* Ensure content is visible and properly styled */
|
||||
ion-content {
|
||||
--background: var(--ion-background-color, #ffffff);
|
||||
--background: var(--ion-background-color);
|
||||
}
|
||||
|
||||
ion-list {
|
||||
@ -55,7 +70,7 @@ ion-list {
|
||||
/* Ensure items are properly displayed */
|
||||
ion-item {
|
||||
--background: transparent;
|
||||
--color: var(--ion-text-color, #000000);
|
||||
--color: var(--ion-text-color);
|
||||
}
|
||||
|
||||
/* Settings page specific styling */
|
||||
@ -107,7 +122,7 @@ ion-modal .ion-input-label,
|
||||
ion-modal ion-label {
|
||||
font-weight: bold !important;
|
||||
font-size: 1rem !important;
|
||||
color: #111827 !important;
|
||||
color: var(--ion-text-color) !important;
|
||||
margin-bottom: 0.5rem !important;
|
||||
display: block !important;
|
||||
}
|
||||
@ -123,7 +138,7 @@ ion-modal ion-button {
|
||||
.bold-label {
|
||||
font-weight: bold !important;
|
||||
font-size: 1rem !important;
|
||||
color: #111827 !important;
|
||||
color: var(--ion-text-color) !important;
|
||||
margin-bottom: 0.5rem !important;
|
||||
display: block !important;
|
||||
}
|
||||
@ -131,27 +146,25 @@ ion-modal ion-button {
|
||||
/* Bold song title styling */
|
||||
.bold-title {
|
||||
font-weight: bold !important;
|
||||
color: #111827 !important;
|
||||
color: var(--ion-text-color) !important;
|
||||
}
|
||||
|
||||
/* Override Ionic label text color for song titles */
|
||||
ion-item ion-label .bold-title {
|
||||
color: #111827 !important;
|
||||
color: var(--ion-text-color) !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Input field styling to match search box */
|
||||
.visible-input {
|
||||
border: 1px solid #d1d5db !important;
|
||||
border: 1px solid var(--ion-border-color, #d1d5db) !important;
|
||||
border-radius: 8px !important;
|
||||
padding: 0 12px !important;
|
||||
background: #ffffff !important;
|
||||
background: var(--ion-background-color) !important;
|
||||
}
|
||||
|
||||
.visible-input ion-input {
|
||||
border: 1px solid #d1d5db !important;
|
||||
border: 1px solid var(--ion-border-color, #d1d5db) !important;
|
||||
border-radius: 8px !important;
|
||||
padding: 0 12px !important;
|
||||
background: #ffffff !important;
|
||||
background: var(--ion-background-color) !important;
|
||||
}
|
||||
|
||||
11
src/main.tsx
11
src/main.tsx
@ -6,8 +6,15 @@ import App from './App.tsx'
|
||||
import { Provider } from 'react-redux';
|
||||
import { store } from './redux/store';
|
||||
|
||||
// Initialize Ionic React
|
||||
setupIonicReact();
|
||||
// Initialize Ionic React with dark mode support
|
||||
setupIonicReact({
|
||||
mode: 'ios', // Use iOS mode for consistent styling
|
||||
innerHTMLTemplatesEnabled: true,
|
||||
// Enable automatic dark mode detection
|
||||
_forceStatusbarPadding: false,
|
||||
// Enable dark mode
|
||||
animated: true,
|
||||
});
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user