feat: Add a large collection of emoji and other frontend assets, including a sound file, and a backend package.json.

This commit is contained in:
Bryan1029384756
2026-01-06 17:58:56 -06:00
parent f531301863
commit abedd78893
3795 changed files with 10981 additions and 229 deletions

View File

@@ -0,0 +1,218 @@
import React, { useState, useEffect } from 'react';
const ScreenShareModal = ({ onClose, onSelectSource }) => {
const [activeTab, setActiveTab] = useState('applications'); // applications | screens | devices
const [sources, setSources] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadSources();
}, []);
const loadSources = async () => {
setLoading(true);
try {
// Get screen/window sources from Electron
const desktopSources = await window.cryptoAPI.getScreenSources();
// Get video input devices (webcams)
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter(d => d.kind === 'videoinput');
// Categorize
const apps = desktopSources.filter(s => s.id.startsWith('window'));
const screens = desktopSources.filter(s => s.id.startsWith('screen'));
const formattedDevices = videoDevices.map(d => ({
id: d.deviceId,
name: d.label || `Camera ${d.deviceId.substring(0, 4)}...`,
isDevice: true,
thumbnail: null // Devices don't have static thumbnails easily referencable without opening stream
}));
setSources({
applications: apps,
screens: screens,
devices: formattedDevices
});
} catch (err) {
console.error("Failed to load sources:", err);
} finally {
setLoading(false);
}
};
const handleSelect = (source) => {
// If device, pass constraints differently
if (source.isDevice) {
onSelectSource({ deviceId: source.id, type: 'device' });
} else {
onSelectSource({ sourceId: source.id, type: 'screen' });
}
onClose();
};
const renderGrid = (items) => {
if (!items || items.length === 0) return <div style={{ color: '#b9bbbe', padding: 20, textAlign: 'center' }}>No sources found.</div>;
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px', padding: '16px' }}>
{items.map(item => (
<div
key={item.id}
onClick={() => handleSelect(item)}
style={{
cursor: 'pointer',
borderRadius: '4px',
padding: '8px',
}}
>
<div style={{ position: 'relative', width: '100%', height: '250px', width: '450px', borderRadius: '8px', overflow: 'hidden', marginBottom: '8px' }}>
{/* Thumbnail/Placeholder */}
{item.thumbnail ? (
<img src={item.thumbnail} alt={item.name} style={{ width: '100%', height: '100%', borderRadius: '8px', objectFit: 'cover', display: 'block' }} />
) : (
<div style={{ width: '100%', height: '100%', backgroundColor: '#202225', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#b9bbbe' }}>
📷
</div>
)}
{/* Hover Overlay */}
<div
className="share-overlay"
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0,0,0,0.5)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
opacity: 0,
transition: 'opacity 0.2s'
}}
onMouseEnter={(e) => e.currentTarget.style.opacity = 1}
onMouseLeave={(e) => e.currentTarget.style.opacity = 0}
>
<button style={{
backgroundColor: '#5865F2',
color: 'white',
border: 'none',
padding: '8px 16px',
borderRadius: '4px',
fontWeight: 'bold',
cursor: 'pointer',
fontSize: '14px',
boxShadow: '0 4px 6px rgba(0,0,0,0.3)'
}}>
Share Screen
</button>
</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', marginTop: '4px', maxWidth: '450px' }}>
{item.appIcon && (
<img src={item.appIcon} alt="" style={{ width: '20px', height: '20px', marginRight: '8px' }} />
)}
<div style={{ color: '#dcddde', fontSize: '14px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', fontWeight: '500' }}>
{item.name}
</div>
</div>
</div>
))}
</div>
);
};
return (
<div style={{
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0,0,0,0.7)',
zIndex: 10000,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}} onClick={onClose}>
<style>{`
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
`}</style>
<div style={{
backgroundColor: '#242429',
borderRadius: '8px',
width: '965px',
height: '740px',
maxWidth: '95vw',
maxHeight: '95vh',
display: 'flex',
flexDirection: 'column',
boxShadow: '0 8px 16px rgba(0,0,0,0.24)'
}} onClick={e => e.stopPropagation()}>
{/* Header/Tabs */}
<div style={{ display: 'flex', borderBottom: '1px solid #2f3136', padding: '16px 16px 0 16px', flexShrink: 0 }}>
<div
onClick={() => setActiveTab('applications')}
style={{
padding: '8px 16px',
cursor: 'pointer',
borderBottom: activeTab === 'applications' ? '2px solid white' : '2px solid transparent',
color: activeTab === 'applications' ? 'white' : '#b9bbbe',
fontWeight: '500'
}}
>
Applications
</div>
<div
onClick={() => setActiveTab('screens')}
style={{
padding: '8px 16px',
cursor: 'pointer',
borderBottom: activeTab === 'screens' ? '2px solid white' : '2px solid transparent',
color: activeTab === 'screens' ? 'white' : '#b9bbbe',
fontWeight: '500'
}}
>
Screens
</div>
<div
onClick={() => setActiveTab('devices')}
style={{
padding: '8px 16px',
cursor: 'pointer',
borderBottom: activeTab === 'devices' ? '2px solid white' : '2px solid transparent',
color: activeTab === 'devices' ? 'white' : '#b9bbbe',
fontWeight: '500'
}}
>
Devices
</div>
</div>
{/* Content */}
<div className="no-scrollbar" style={{ flex: 1, overflowY: 'auto' }}>
{loading ? (
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%', color: '#b9bbbe' }}>
Loading sources...
</div>
) : (
renderGrid(sources[activeTab])
)}
</div>
</div>
</div>
);
};
export default ScreenShareModal;