diff --git a/src/app/components/message/layout/Base.tsx b/src/app/components/message/layout/Base.tsx
index ac196a5..35fa772 100644
--- a/src/app/components/message/layout/Base.tsx
+++ b/src/app/components/message/layout/Base.tsx
@@ -4,10 +4,10 @@ import classNames from 'classnames';
import * as css from './layout.css';
export const MessageBase = as<'div', css.MessageBaseVariants>(
- ({ className, highlight, selected, collapse, autoCollapse, space, ...props }, ref) => (
+ ({ className, highlight, selected, collapse, autoCollapse, space, newMessage, ...props }, ref) => (
isAvatarCached(src));
const useAuthentication = useMediaAuthentication();
const authenticatedSrc = useAuthenticatedMediaUrl(src, useAuthentication);
const handleLoad: ReactEventHandler
= (evt) => {
evt.currentTarget.setAttribute('data-image-loaded', 'true');
+ setLoaded(true);
+ cacheAvatar(src);
+ pruneAvatarCache();
};
+ // No src or error - show fallback only
if (!authenticatedSrc || error) {
return (
setError(true)}
+ onLoad={handleLoad}
+ draggable={false}
+ data-image-loaded="true"
+ />
+ );
+ }
+
+ // Loading state - render fallback with image overlay
return (
- setError(true)}
- onLoad={handleLoad}
- draggable={false}
- />
+
+
+ {renderFallback()}
+
+
setError(true)}
+ onLoad={handleLoad}
+ draggable={false}
+ />
+
);
}
diff --git a/src/app/components/title-bar/TitleBar.css.ts b/src/app/components/title-bar/TitleBar.css.ts
new file mode 100644
index 0000000..d0caf42
--- /dev/null
+++ b/src/app/components/title-bar/TitleBar.css.ts
@@ -0,0 +1,77 @@
+import { style, keyframes } from '@vanilla-extract/css';
+import { color, config } from 'folds';
+
+const wipeIn = keyframes({
+ '0%': {
+ clipPath: 'inset(0 100% 0 0)',
+ opacity: 0,
+ },
+ '100%': {
+ clipPath: 'inset(0 0 0 0)',
+ opacity: 1,
+ },
+});
+
+const wipeOut = keyframes({
+ '0%': {
+ clipPath: 'inset(0 0 0 0)',
+ opacity: 1,
+ },
+ '100%': {
+ clipPath: 'inset(0 100% 0 0)',
+ opacity: 0,
+ },
+});
+
+export const NewMessagePill = style({
+ display: 'flex',
+ alignItems: 'center',
+ gap: config.space.S100,
+ backgroundColor: '#2E7D32',
+ color: '#ffffff',
+ padding: `${config.space.S100} ${config.space.S200}`,
+ borderRadius: '999px',
+ cursor: 'pointer',
+ fontSize: '12px',
+ fontWeight: 500,
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ maxWidth: '200px',
+ animation: `${wipeIn} 0.3s ease-out forwards`,
+ transition: 'background-color 0.15s ease',
+ WebkitAppRegion: 'no-drag',
+ selectors: {
+ '&:hover': {
+ backgroundColor: '#388E3C',
+ },
+ },
+});
+
+export const NewMessagePillExiting = style({
+ animation: `${wipeOut} 0.2s ease-in forwards`,
+});
+
+export const TitleBar = style({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ height: '32px',
+ minHeight: '32px',
+ backgroundColor: color.Surface.Container,
+ borderBottom: `1px solid ${color.Surface.ContainerLine}`,
+ position: 'relative',
+ zIndex: 1000,
+ userSelect: 'none',
+ WebkitUserSelect: 'none',
+});
+
+export const TitleBarDragRegion = style({
+ display: 'flex',
+ alignItems: 'center',
+ height: '100%',
+ flexGrow: 1,
+ paddingLeft: config.space.S200,
+ cursor: 'default',
+ WebkitAppRegion: 'drag',
+ color: color.Surface.OnContainer,
+});
diff --git a/src/app/components/title-bar/TitleBar.tsx b/src/app/components/title-bar/TitleBar.tsx
new file mode 100644
index 0000000..3812f14
--- /dev/null
+++ b/src/app/components/title-bar/TitleBar.tsx
@@ -0,0 +1,244 @@
+import React, { ReactNode, useMemo, useEffect, useState, useCallback, useRef } from 'react';
+import { Box, Text } from 'folds';
+import { invoke } from '@tauri-apps/api/core';
+import { MatrixClient, RoomEvent, ClientEvent, MatrixEvent, Room } from 'matrix-js-sdk';
+import { useAtomValue } from 'jotai';
+import { useNavigate } from 'react-router-dom';
+import { WindowControls } from './WindowControls';
+import * as css from './TitleBar.css';
+import { getUnreadInfos, getOrphanParents, guessPerfectParent } from '../../utils/room';
+import { getCanonicalAliasOrRoomId } from '../../utils/matrix';
+import { activeRoomIdAtom } from '../../state/activeRoom';
+import { roomToParentsAtom } from '../../state/room/roomToParents';
+import { mDirectAtom } from '../../state/mDirectList';
+import { getDirectRoomPath, getHomeRoomPath, getSpaceRoomPath } from '../../pages/pathUtils';
+
+type NewMessageNotification = {
+ roomId: string;
+ eventId: string;
+ senderName: string;
+ preview: string;
+};
+
+export type TitleBarProps = {
+ mx?: MatrixClient;
+ children?: ReactNode;
+};
+
+export function TitleBar({ mx, children }: TitleBarProps) {
+ const [updateCounter, setUpdateCounter] = useState(0);
+ const roomId = useAtomValue(activeRoomIdAtom);
+ const [newMessage, setNewMessage] = useState(null);
+ const [isExiting, setIsExiting] = useState(false);
+ const dismissTimerRef = useRef | null>(null);
+ const navigate = useNavigate();
+ const roomToParents = useAtomValue(roomToParentsAtom);
+ const mDirects = useAtomValue(mDirectAtom);
+
+ // Clear dismiss timer on unmount
+ useEffect(() => {
+ return () => {
+ if (dismissTimerRef.current) {
+ clearTimeout(dismissTimerRef.current);
+ }
+ };
+ }, []);
+
+ // Auto-dismiss notification after 10 seconds
+ const scheduleDismiss = useCallback(() => {
+ if (dismissTimerRef.current) {
+ clearTimeout(dismissTimerRef.current);
+ }
+ dismissTimerRef.current = setTimeout(() => {
+ setIsExiting(true);
+ setTimeout(() => {
+ setNewMessage(null);
+ setIsExiting(false);
+ }, 200); // Wait for exit animation
+ }, 10000);
+ }, []);
+
+ // Navigate to the new message
+ const handleNotificationClick = useCallback((e: React.MouseEvent) => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ if (!newMessage || !mx) return;
+
+ const targetRoomId = newMessage.roomId;
+ const eventId = newMessage.eventId;
+
+ // Dismiss notification
+ setIsExiting(true);
+ setTimeout(() => {
+ setNewMessage(null);
+ setIsExiting(false);
+ }, 200);
+
+ if (dismissTimerRef.current) {
+ clearTimeout(dismissTimerRef.current);
+ }
+
+ // Simple navigation approach - just try all paths
+ try {
+ const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, targetRoomId);
+
+ // Check if it's a direct message
+ if (mDirects.has(targetRoomId)) {
+ const path = getDirectRoomPath(roomIdOrAlias, eventId);
+ console.log('Navigating to direct room:', path);
+ navigate(path);
+ return;
+ }
+
+ // Check if it belongs to a space
+ const orphanParents = getOrphanParents(roomToParents, targetRoomId);
+ if (orphanParents.length > 0) {
+ const parentSpace = guessPerfectParent(mx, targetRoomId, orphanParents) ?? orphanParents[0];
+ const pSpaceIdOrAlias = getCanonicalAliasOrRoomId(mx, parentSpace);
+ const path = getSpaceRoomPath(pSpaceIdOrAlias, roomIdOrAlias, eventId);
+ console.log('Navigating to space room:', path);
+ navigate(path);
+ return;
+ }
+
+ // Default to home room
+ const path = getHomeRoomPath(roomIdOrAlias, eventId);
+ console.log('Navigating to home room:', path);
+ navigate(path);
+ } catch (error) {
+ console.error('Error navigating to room:', error);
+ // Last resort - navigate without event ID
+ try {
+ const roomIdOrAlias = getCanonicalAliasOrRoomId(mx, targetRoomId);
+ navigate(getHomeRoomPath(roomIdOrAlias));
+ } catch (fallbackError) {
+ console.error('Fallback navigation also failed:', fallbackError);
+ }
+ }
+ }, [newMessage, mx, roomToParents, mDirects, navigate]);
+
+ // Subscribe to room changes for unread updates and new messages
+ useEffect(() => {
+ if (!mx) return;
+
+ const update = () => setUpdateCounter(c => c + 1);
+
+ const handleTimelineEvent = (event: MatrixEvent, room: Room | undefined) => {
+ update();
+
+ // Check if this is a new message we should notify about
+ if (!room || !event) return;
+
+ // Ignore if it's the currently active room
+ if (room.roomId === roomId) return;
+
+ // Ignore if it's our own message
+ if (event.getSender() === mx.getUserId()) return;
+
+ // Only notify for actual messages
+ if (event.getType() !== 'm.room.message') return;
+
+ // Get content
+ const content = event.getContent();
+ if (!content.body) return;
+
+ // Get sender display name
+ const sender = room.getMember(event.getSender() || '');
+ const senderName = sender?.name || event.getSender() || 'Unknown';
+
+ // Create preview (truncate if needed)
+ const preview = content.body.length > 30
+ ? content.body.substring(0, 30) + '...'
+ : content.body;
+
+ setNewMessage({
+ roomId: room.roomId,
+ eventId: event.getId() || '',
+ senderName,
+ preview,
+ });
+ setIsExiting(false);
+ scheduleDismiss();
+ };
+
+ mx.on(RoomEvent.Timeline, handleTimelineEvent);
+ mx.on(RoomEvent.Receipt, update);
+ mx.on(ClientEvent.Room, update);
+
+ return () => {
+ mx.off(RoomEvent.Timeline, handleTimelineEvent);
+ mx.off(RoomEvent.Receipt, update);
+ mx.off(ClientEvent.Room, update);
+ };
+ }, [mx, roomId, scheduleDismiss]);
+
+ // Get room name
+ const roomName = useMemo(() => {
+ if (!mx || !roomId) return null;
+ const room = mx.getRoom(roomId);
+ return room?.name || null;
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [mx, roomId, updateCounter]);
+
+ // Get total unread count
+ const totalUnread = useMemo(() => {
+ if (!mx) return 0;
+ const unreadInfos = getUnreadInfos(mx);
+ return unreadInfos.reduce((sum, info) => sum + info.total, 0);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [mx, updateCounter]);
+
+ // Build title parts
+ const titleParts = useMemo(() => {
+ let suffix = '';
+ if (roomName) {
+ suffix += ` - ${roomName}`;
+ }
+ if (totalUnread > 0) {
+ suffix += ` (${totalUnread})`;
+ }
+ return { suffix };
+ }, [roomName, totalUnread]);
+
+ const handleDragStart = async () => {
+ try {
+ await invoke('window_start_drag');
+ } catch (error) {
+ console.error('Failed to start window drag:', error);
+ }
+ };
+
+ // Only render on desktop (when Tauri is available)
+ if (typeof (window as any).__TAURI__ === 'undefined') {
+ return null;
+ }
+
+ return (
+
+
+
+ Paarrot{titleParts.suffix}
+
+ {newMessage && (
+ e.stopPropagation()}
+ title={`${newMessage.senderName}: ${newMessage.preview}`}
+ >
+ {newMessage.senderName}: {newMessage.preview}
+
+ )}
+ {children}
+
+
+
+ );
+}
diff --git a/src/app/components/title-bar/WindowControls.css.ts b/src/app/components/title-bar/WindowControls.css.ts
new file mode 100644
index 0000000..c07f3e1
--- /dev/null
+++ b/src/app/components/title-bar/WindowControls.css.ts
@@ -0,0 +1,45 @@
+import { style } from '@vanilla-extract/css';
+import { color } from 'folds';
+
+export const WindowControls = style({
+ display: 'flex',
+ alignItems: 'center',
+ height: '100%',
+ paddingRight: '8px',
+ gap: '8px',
+ flexShrink: 0,
+});
+
+export const WindowButton = style({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: '46px',
+ height: '32px',
+ border: 'none',
+ background: 'transparent',
+ color: color.Surface.OnContainer,
+ cursor: 'pointer',
+ transition: 'background-color 0.1s ease',
+ outline: 'none',
+
+ ':hover': {
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
+ },
+
+ ':active': {
+ backgroundColor: 'rgba(255, 255, 255, 0.05)',
+ },
+});
+
+export const WindowButtonClose = style([WindowButton, {
+ ':hover': {
+ backgroundColor: '#e81123',
+ color: '#ffffff',
+ },
+
+ ':active': {
+ backgroundColor: '#c50f1f',
+ color: '#ffffff',
+ },
+}]);
diff --git a/src/app/components/title-bar/WindowControls.tsx b/src/app/components/title-bar/WindowControls.tsx
new file mode 100644
index 0000000..fbb62dc
--- /dev/null
+++ b/src/app/components/title-bar/WindowControls.tsx
@@ -0,0 +1,105 @@
+import React, { useState, useEffect } from 'react';
+import { Box, IconButton, Icon } from 'folds';
+import { invoke } from '@tauri-apps/api/core';
+import * as css from './WindowControls.css';
+
+export function WindowControls() {
+ const [isMaximized, setIsMaximized] = useState(false);
+
+ // Check initial maximized state
+ useEffect(() => {
+ const checkMaximized = async () => {
+ try {
+ const maximized = await invoke('window_is_maximized');
+ setIsMaximized(maximized);
+ } catch (error) {
+ console.error('Failed to check window state:', error);
+ }
+ };
+ checkMaximized();
+ }, []);
+
+ const handleMinimize = async () => {
+ try {
+ await invoke('window_minimize');
+ } catch (error) {
+ console.error('Failed to minimize window:', error);
+ }
+ };
+
+ const handleMaximize = async () => {
+ try {
+ if (isMaximized) {
+ await invoke('window_unmaximize');
+ } else {
+ await invoke('window_maximize');
+ }
+ setIsMaximized(!isMaximized);
+ } catch (error) {
+ console.error('Failed to toggle maximize:', error);
+ }
+ };
+
+ const handleClose = async () => {
+ try {
+ await invoke('window_close');
+ } catch (error) {
+ console.error('Failed to close window:', error);
+ }
+ };
+
+ // Only render on desktop (when Tauri is available)
+ if (typeof (window as any).__TAURI__ === 'undefined') {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/components/title-bar/index.ts b/src/app/components/title-bar/index.ts
new file mode 100644
index 0000000..82e2bd1
--- /dev/null
+++ b/src/app/components/title-bar/index.ts
@@ -0,0 +1,3 @@
+export { TitleBar } from './TitleBar';
+export { WindowControls } from './WindowControls';
+export type { TitleBarProps } from './TitleBar';
diff --git a/src/app/components/user-avatar/UserAvatar.tsx b/src/app/components/user-avatar/UserAvatar.tsx
index 04cff39..1d7c560 100644
--- a/src/app/components/user-avatar/UserAvatar.tsx
+++ b/src/app/components/user-avatar/UserAvatar.tsx
@@ -5,6 +5,7 @@ import * as css from './UserAvatar.css';
import colorMXID from '../../../util/colorMXID';
import { useAuthenticatedMediaUrl } from '../../hooks/useAuthenticatedMediaUrl';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
+import { cacheAvatar, isAvatarCached, pruneAvatarCache } from '../../utils/avatarCache';
type UserAvatarProps = {
className?: string;
@@ -15,13 +16,18 @@ type UserAvatarProps = {
};
export function UserAvatar({ className, userId, src, alt, renderFallback }: UserAvatarProps) {
const [error, setError] = useState(false);
+ const [loaded, setLoaded] = useState(() => isAvatarCached(src));
const useAuthentication = useMediaAuthentication();
const authenticatedSrc = useAuthenticatedMediaUrl(src, useAuthentication);
const handleLoad: ReactEventHandler = (evt) => {
evt.currentTarget.setAttribute('data-image-loaded', 'true');
+ setLoaded(true);
+ cacheAvatar(src);
+ pruneAvatarCache();
};
+ // No src or error - show fallback only
if (!authenticatedSrc || error) {
return (
setError(true)}
+ onLoad={handleLoad}
+ draggable={false}
+ data-image-loaded="true"
+ />
+ );
+ }
+
+ // Loading state - render fallback with image overlay
return (
- setError(true)}
- onLoad={handleLoad}
- draggable={false}
- />
+
+
+ {renderFallback()}
+
+
setError(true)}
+ onLoad={handleLoad}
+ draggable={false}
+ />
+
);
}
diff --git a/src/app/features/call/CallService.ts b/src/app/features/call/CallService.ts
index 53a6c1c..d3924ad 100644
--- a/src/app/features/call/CallService.ts
+++ b/src/app/features/call/CallService.ts
@@ -41,6 +41,36 @@ const MEMBERSHIP_REFRESH_INTERVAL_MS = 45 * 60 * 1000;
/** Call membership expiry time (1 hour) */
const MEMBERSHIP_EXPIRY_MS = 60 * 60 * 1000;
+/**
+ * Check WebRTC capabilities and log diagnostic information
+ */
+function checkWebRTCSupport(): { supported: boolean; details: Record } {
+ const details: Record = {
+ userAgent: navigator.userAgent,
+ platform: navigator.platform,
+ };
+
+ // Check for key WebRTC APIs
+ details.hasGetUserMedia = !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
+ details.hasRTCPeerConnection = !!(window.RTCPeerConnection);
+ details.hasRTCDataChannel = !!(window.RTCPeerConnection && window.RTCPeerConnection.prototype.createDataChannel);
+
+ // Check WebKit-specific APIs
+ details.hasWebkitGetUserMedia = !!(navigator.getUserMedia || (navigator as any).webkitGetUserMedia);
+ details.hasWebkitRTCPeerConnection = !!((window as any).webkitRTCPeerConnection);
+
+ // Check if mediaDevices API exists
+ details.hasMediaDevices = !!navigator.mediaDevices;
+ details.hasEnumerateDevices = !!(navigator.mediaDevices && navigator.mediaDevices.enumerateDevices);
+
+ const supported = !!(
+ (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) &&
+ (window.RTCPeerConnection || (window as any).webkitRTCPeerConnection)
+ );
+
+ return { supported, details };
+}
+
/**
* Service for managing Matrix RTC calls via LiveKit
* Handles LiveKit connections, media streams, call state, and Matrix room signaling
@@ -283,6 +313,15 @@ export class CallService {
console.log('Got LiveKit JWT, connecting to:', this.livekitJwt.url);
console.log('LiveKit JWT response:', JSON.stringify(this.livekitJwt));
+ // Check WebRTC support before attempting connection
+ const webrtcCheck = checkWebRTCSupport();
+ console.log('WebRTC support check:', webrtcCheck);
+
+ if (!webrtcCheck.supported) {
+ console.warn('WebRTC may not be fully supported. Attempting connection anyway...');
+ console.warn('WebRTC details:', JSON.stringify(webrtcCheck.details, null, 2));
+ }
+
// Step 3: Create and connect to LiveKit room
this.livekitRoom = new Room({
adaptiveStream: true,
diff --git a/src/app/features/common-settings/general/LivekitConfig.tsx b/src/app/features/common-settings/general/LivekitConfig.tsx
new file mode 100644
index 0000000..caa503e
--- /dev/null
+++ b/src/app/features/common-settings/general/LivekitConfig.tsx
@@ -0,0 +1,156 @@
+import React, { FormEventHandler, useCallback, useState } from 'react';
+import {
+ Box,
+ Button,
+ color,
+ Input,
+ Spinner,
+ Text,
+} from 'folds';
+import { SequenceCard } from '../../../components/sequence-card';
+import { SequenceCardStyle } from '../../room-settings/styles.css';
+import { SettingTile } from '../../../components/setting-tile';
+import { useRoom } from '../../../hooks/useRoom';
+import { useStateEvent } from '../../../hooks/useStateEvent';
+import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
+import { useMatrixClient } from '../../../hooks/useMatrixClient';
+import { usePowerLevels } from '../../../hooks/usePowerLevels';
+import { useRoomCreators } from '../../../hooks/useRoomCreators';
+import { useRoomPermissions } from '../../../hooks/useRoomPermissions';
+import { StateEvent } from '../../../../types/matrix/room';
+
+interface LivekitConfigContent {
+ service_url?: string;
+}
+
+/**
+ * Room-specific LiveKit configuration component.
+ * Allows room admins to override the LiveKit service URL for calls in this room.
+ */
+export function LivekitConfig() {
+ const mx = useMatrixClient();
+ const room = useRoom();
+ const powerLevels = usePowerLevels(room);
+ const creators = useRoomCreators(room);
+ const permissions = useRoomPermissions(creators, powerLevels);
+
+ const stateEvent = useStateEvent(room, StateEvent.RoomLivekitConfig);
+ const currentConfig = stateEvent?.getContent();
+ const currentUrl = currentConfig?.service_url || '';
+
+ const [urlValue, setUrlValue] = useState(currentUrl);
+ const [urlError, setUrlError] = useState();
+
+ const [saveState, saveConfig] = useAsyncCallback(
+ useCallback(
+ async (serviceUrl: string) => {
+ const content: LivekitConfigContent = serviceUrl
+ ? { service_url: serviceUrl }
+ : {};
+
+ await mx.sendStateEvent(room.roomId, StateEvent.RoomLivekitConfig as any, content, '');
+ },
+ [mx, room]
+ )
+ );
+
+ const canEdit = permissions.stateEvent(StateEvent.RoomLivekitConfig, mx.getUserId()!);
+
+ const handleSave: FormEventHandler = async (evt) => {
+ evt.preventDefault();
+ const serviceUrl = urlValue.trim();
+
+ // Basic URL validation
+ if (serviceUrl && !serviceUrl.startsWith('http://') && !serviceUrl.startsWith('https://')) {
+ setUrlError('URL must start with http:// or https://');
+ return;
+ }
+
+ setUrlError(undefined);
+ await saveConfig(serviceUrl);
+ };
+
+ const handleClear = async () => {
+ setUrlValue('');
+ setUrlError(undefined);
+ await saveConfig('');
+ };
+
+ const hasChanges = urlValue !== currentUrl;
+ const isSaving = saveState.status === AsyncStatus.Loading;
+
+ return (
+
+
+
+ ) => {
+ setUrlValue(e.target.value);
+ setUrlError(undefined);
+ }}
+ placeholder="https://example.com/livekit/jwt"
+ size="300"
+ variant="Secondary"
+ radii="300"
+ disabled={!canEdit || isSaving}
+ style={{ width: '100%' }}
+ />
+ {urlError && (
+
+ {urlError}
+
+ )}
+ {saveState.status === AsyncStatus.Error && (
+
+ Failed to save: {saveState.error instanceof Error ? saveState.error.message : 'Unknown error'}
+
+ )}
+ {saveState.status === AsyncStatus.Success && !hasChanges && (
+
+ Configuration saved
+
+ )}
+
+ }
+ >
+ Save
+
+ {currentUrl && (
+
+ )}
+ {!canEdit && (
+
+ You don't have permission to change this setting
+
+ )}
+
+
+
+ );
+}
diff --git a/src/app/features/common-settings/general/index.ts b/src/app/features/common-settings/general/index.ts
index 9b2e2ac..cb9d8f0 100644
--- a/src/app/features/common-settings/general/index.ts
+++ b/src/app/features/common-settings/general/index.ts
@@ -1,4 +1,5 @@
export * from './EmbedFilters';
+export * from './LivekitConfig';
export * from './RoomAddress';
export * from './RoomEncryption';
export * from './RoomHistoryVisibility';
diff --git a/src/app/features/room-settings/general/General.tsx b/src/app/features/room-settings/general/General.tsx
index 92eb32e..2a4fc4a 100644
--- a/src/app/features/room-settings/general/General.tsx
+++ b/src/app/features/room-settings/general/General.tsx
@@ -5,6 +5,7 @@ import { usePowerLevels } from '../../../hooks/usePowerLevels';
import { useRoom } from '../../../hooks/useRoom';
import {
EmbedFilters,
+ LivekitConfig,
RoomProfile,
RoomEncryption,
RoomHistoryVisibility,
@@ -58,6 +59,10 @@ export function General({ requestClose }: GeneralProps) {
Link Previews
+
+ Voice & Video
+
+
Addresses
diff --git a/src/app/features/room/Room.tsx b/src/app/features/room/Room.tsx
index 24878d5..51db0d0 100644
--- a/src/app/features/room/Room.tsx
+++ b/src/app/features/room/Room.tsx
@@ -1,7 +1,8 @@
-import React, { useCallback } from 'react';
+import React, { useCallback, useEffect } from 'react';
import { Box, Line } from 'folds';
import { useParams } from 'react-router-dom';
import { isKeyHotkey } from 'is-hotkey';
+import { useSetAtom } from 'jotai';
import { RoomView } from './RoomView';
import { MembersDrawer } from './MembersDrawer';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
@@ -13,11 +14,13 @@ import { useKeyDown } from '../../hooks/useKeyDown';
import { markAsRead } from '../../utils/notifications';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useRoomMembers } from '../../hooks/useRoomMembers';
+import { activeRoomIdAtom } from '../../state/activeRoom';
export function Room() {
const { eventId } = useParams();
const room = useRoom();
const mx = useMatrixClient();
+ const setActiveRoomId = useSetAtom(activeRoomIdAtom);
const [isDrawer] = useSetting(settingsAtom, 'isPeopleDrawer');
const [hideActivity] = useSetting(settingsAtom, 'hideActivity');
@@ -25,6 +28,12 @@ export function Room() {
const powerLevels = usePowerLevels(room);
const members = useRoomMembers(mx, room.roomId);
+ // Update titlebar with current room ID
+ useEffect(() => {
+ setActiveRoomId(room.roomId);
+ return () => setActiveRoomId(undefined);
+ }, [room.roomId, setActiveRoomId]);
+
useKeyDown(
window,
useCallback(
diff --git a/src/app/features/room/RoomInput.tsx b/src/app/features/room/RoomInput.tsx
index 69b7400..3eecbce 100644
--- a/src/app/features/room/RoomInput.tsx
+++ b/src/app/features/room/RoomInput.tsx
@@ -174,6 +174,7 @@ export const RoomInput = forwardRef(
selectedFiles.map((f) => f.file)
);
const uploadBoardHandlers = useRef();
+ const editorRef = useRef(null);
const imagePackRooms: Room[] = useImagePackRooms(roomId, roomToParents);
@@ -384,7 +385,7 @@ export const RoomInput = forwardRef(
resetEditorHistory(editor);
setReplyDraft(undefined);
sendTypingStatus(false);
- }, [mx, roomId, editor, replyDraft, sendTypingStatus, setReplyDraft, isMarkdown, commands]);
+ }, [mx, roomId, editor, replyDraft, sendTypingStatus, setReplyDraft, isMarkdown, commands, editorRef]);
const handleKeyDown: KeyboardEventHandler = useCallback(
(evt) => {
@@ -544,6 +545,7 @@ export const RoomInput = forwardRef(
/>
)}
{
+ const getMessageData = (eventId: string) => {
+ const timelineSet = room.getUnfilteredTimelineSet();
+ const evtTimeline = timelineSet.getTimelineForEvent(eventId);
+ if (!evtTimeline) return null;
+ const mEvent = evtTimeline.getEvents().find((e) => e.getId() === eventId);
+ if (!mEvent) return null;
+ const sender = getMemberDisplayName(room, mEvent.getSender() ?? '')
+ ?? getMxIdLocalPart(mEvent.getSender() ?? '')
+ ?? mEvent.getSender()
+ ?? 'Unknown';
+ const content = mEvent.getContent().body ?? '';
+ return {
+ sender,
+ ts: mEvent.getTs(),
+ content,
+ };
+ };
+ return setupCopyHandler(scrollRef, getMessageData, hour24Clock);
+ }, [room, hour24Clock]);
+
const handleJumpToLatest = () => {
if (eventId) {
navigateRoom(room.roomId, undefined, { replace: true });
diff --git a/src/app/features/room/message/Message.tsx b/src/app/features/room/message/Message.tsx
index 03bd18d..be1c958 100644
--- a/src/app/features/room/message/Message.tsx
+++ b/src/app/features/room/message/Message.tsx
@@ -28,6 +28,7 @@ import React, {
MouseEventHandler,
ReactNode,
useCallback,
+ useEffect,
useState,
} from 'react';
import FocusTrap from 'focus-trap-react';
@@ -353,6 +354,42 @@ export const MessageCopyLinkItem = as<
);
});
+export const MessageCopyRawTextItem = as<
+ 'button',
+ {
+ mEvent: MatrixEvent;
+ onClose?: () => void;
+ }
+>(({ mEvent, onClose, ...props }, ref) => {
+ const handleCopy = () => {
+ const content = mEvent.getContent();
+ const rawText = content.body ?? '';
+ if (rawText) {
+ copyToClipboard(rawText);
+ }
+ onClose?.();
+ };
+
+ // Only show for text messages
+ const content = mEvent.getContent();
+ if (!content.body || mEvent.isRedacted()) return null;
+
+ return (
+ }
+ radii="300"
+ onClick={handleCopy}
+ {...props}
+ ref={ref}
+ >
+
+ Copy Raw Text
+
+
+ );
+});
+
export const MessagePinItem = as<
'button',
{
@@ -742,6 +779,23 @@ export const Message = as<'div', MessageProps>(
const { focusWithinProps } = useFocusWithin({ onFocusWithinChange: setHover });
const [menuAnchor, setMenuAnchor] = useState();
const [emojiBoardAnchor, setEmojiBoardAnchor] = useState();
+ const [shiftHeld, setShiftHeld] = useState(false);
+
+ // Track shift key state
+ useEffect(() => {
+ const handleKeyDown = (e: KeyboardEvent) => {
+ if (e.key === 'Shift') setShiftHeld(true);
+ };
+ const handleKeyUp = (e: KeyboardEvent) => {
+ if (e.key === 'Shift') setShiftHeld(false);
+ };
+ window.addEventListener('keydown', handleKeyDown);
+ window.addEventListener('keyup', handleKeyUp);
+ return () => {
+ window.removeEventListener('keydown', handleKeyDown);
+ window.removeEventListener('keyup', handleKeyUp);
+ };
+ }, []);
const senderDisplayName =
getMemberDisplayName(room, senderId) ?? getMxIdLocalPart(senderId) ?? senderId;
@@ -986,6 +1040,36 @@ export const Message = as<'div', MessageProps>(
)}
+ {mEvent.getContent().body && !mEvent.isRedacted() && (
+ {
+ const rawText = mEvent.getContent().body ?? '';
+ if (rawText) copyToClipboard(rawText);
+ }}
+ variant="SurfaceVariant"
+ size="300"
+ radii="300"
+ title="Copy Raw Text"
+ >
+
+
+ )}
+ {shiftHeld && canDelete && (
+ {
+ const eventId = mEvent.getId();
+ if (eventId) {
+ mx.redactEvent(room.roomId, eventId);
+ }
+ }}
+ variant="Critical"
+ size="300"
+ radii="300"
+ title="Delete Message (Shift held)"
+ >
+
+
+ )}
(
/>
)}
+
{canPinEvent && (
)}
@@ -1281,6 +1366,7 @@ export const Event = as<'div', EventProps>(
/>
)}
+
{((!mEvent.isRedacted() && canDelete && !stateEvent) ||
(mEvent.getSender() !== mx.getUserId() && !stateEvent)) && (
diff --git a/src/app/features/room/message/styles.css.ts b/src/app/features/room/message/styles.css.ts
index 0546842..705e986 100644
--- a/src/app/features/room/message/styles.css.ts
+++ b/src/app/features/room/message/styles.css.ts
@@ -15,6 +15,9 @@ export const MessageOptionsBase = style([
top: toRem(-30),
right: 0,
zIndex: 1,
+ // Extend hitbox to the left for easier hover targeting
+ paddingLeft: toRem(100),
+ marginLeft: toRem(-100),
},
]);
export const MessageOptionsBar = style([
diff --git a/src/app/features/settings/audio/Audio.tsx b/src/app/features/settings/audio/Audio.tsx
index 6a44f6e..79485a7 100644
--- a/src/app/features/settings/audio/Audio.tsx
+++ b/src/app/features/settings/audio/Audio.tsx
@@ -8,6 +8,7 @@ import {
Icon,
IconButton,
Icons,
+ Input,
Menu,
MenuItem,
PopOut,
@@ -450,6 +451,7 @@ export function Audio({ requestClose }: AudioProps) {
const [settings, setSettings] = useState(loadAudioSettings);
const [permissionStatus, setPermissionStatus] = useState<'granted' | 'denied' | 'prompt'>('prompt');
const [showRemoteCursor, setShowRemoteCursor] = useSetting(settingsAtom, 'showRemoteCursor');
+ const [livekitServiceUrl, setLivekitServiceUrl] = useSetting(settingsAtom, 'livekitServiceUrl');
useEffect(() => {
const loadDevices = async () => {
@@ -813,6 +815,33 @@ export function Audio({ requestClose }: AudioProps) {
/>
+
+
+
+ LiveKit Configuration
+
+
+ setLivekitServiceUrl(e.target.value || undefined)}
+ placeholder="https://example.com/livekit/jwt"
+ style={{ minWidth: toRem(300) }}
+ />
+ }
+ />
+
+
+
{mx && }
{loading && }
{(loadState.status === AsyncStatus.Error || startState.status === AsyncStatus.Error) && (
diff --git a/src/app/state/activeRoom.ts b/src/app/state/activeRoom.ts
new file mode 100644
index 0000000..bd1a437
--- /dev/null
+++ b/src/app/state/activeRoom.ts
@@ -0,0 +1,4 @@
+import { atom } from 'jotai';
+
+// Atom to track the currently active room ID for the titlebar
+export const activeRoomIdAtom = atom(undefined);
diff --git a/src/app/state/settings.ts b/src/app/state/settings.ts
index d273ede..420962a 100644
--- a/src/app/state/settings.ts
+++ b/src/app/state/settings.ts
@@ -52,6 +52,8 @@ export interface Settings {
developerTools: boolean;
autoJoinSpaceRooms: boolean;
+
+ livekitServiceUrl?: string;
}
const defaultSettings: Settings = {
@@ -91,6 +93,8 @@ const defaultSettings: Settings = {
developerTools: false,
autoJoinSpaceRooms: true,
+
+ livekitServiceUrl: undefined,
};
export const getSettings = () => {
diff --git a/src/app/utils/avatarCache.ts b/src/app/utils/avatarCache.ts
new file mode 100644
index 0000000..5bb5e00
--- /dev/null
+++ b/src/app/utils/avatarCache.ts
@@ -0,0 +1,31 @@
+// Simple in-memory cache for avatar URLs that have been successfully loaded
+// This prevents the flicker when avatars re-render
+
+const loadedAvatars = new Set();
+
+export function isAvatarCached(url: string | undefined): boolean {
+ if (!url) return false;
+ return loadedAvatars.has(url);
+}
+
+export function cacheAvatar(url: string | undefined): void {
+ if (url) {
+ loadedAvatars.add(url);
+ }
+}
+
+// Optional: limit cache size to prevent memory issues
+const MAX_CACHE_SIZE = 1000;
+
+export function pruneAvatarCache(): void {
+ if (loadedAvatars.size > MAX_CACHE_SIZE) {
+ const iterator = loadedAvatars.values();
+ // Remove oldest entries (first added)
+ for (let i = 0; i < loadedAvatars.size - MAX_CACHE_SIZE; i++) {
+ const result = iterator.next();
+ if (!result.done) {
+ loadedAvatars.delete(result.value);
+ }
+ }
+ }
+}
diff --git a/src/app/utils/copyHandler.ts b/src/app/utils/copyHandler.ts
new file mode 100644
index 0000000..788fa85
--- /dev/null
+++ b/src/app/utils/copyHandler.ts
@@ -0,0 +1,102 @@
+import { timeHourMinute } from './time';
+
+/**
+ * Processes selected text from the chat timeline and formats it as:
+ * "Username - Time: Message"
+ *
+ * This intercepts the copy event on the timeline and reformats the copied text.
+ */
+export const setupCopyHandler = (
+ containerRef: React.RefObject,
+ getMessageData: (eventId: string) => { sender: string; ts: number; content: string } | null,
+ hour24Clock: boolean
+): (() => void) => {
+ const container = containerRef.current;
+ if (!container) return () => {};
+
+ const handleCopy = (event: ClipboardEvent) => {
+ const selection = window.getSelection();
+ if (!selection || selection.isCollapsed) return;
+
+ const range = selection.getRangeAt(0);
+ const selectedContainer = range.commonAncestorContainer;
+
+ // Only process if selection is within our container
+ if (!container.contains(selectedContainer)) return;
+
+ // Find all message elements within the selection
+ const messages: Array<{ sender: string; time: string; content: string }> = [];
+
+ // Get all message elements in the container
+ const messageElements = container.querySelectorAll('[data-message-id]');
+
+ messageElements.forEach((msgEl) => {
+ // Check if this message element intersects with the selection
+ if (!selection.containsNode(msgEl, true)) return;
+
+ const eventId = msgEl.getAttribute('data-message-id');
+ if (!eventId) return;
+
+ const data = getMessageData(eventId);
+ if (!data) return;
+
+ // Get the selected text content within this message
+ const tempRange = document.createRange();
+ tempRange.selectNodeContents(msgEl);
+
+ // Check if the selection overlaps with this message
+ const intersects = range.compareBoundaryPoints(Range.END_TO_START, tempRange) <= 0 &&
+ range.compareBoundaryPoints(Range.START_TO_END, tempRange) >= 0;
+
+ if (!intersects) return;
+
+ // Format the time
+ const timeStr = timeHourMinute(data.ts, hour24Clock);
+
+ // Get the text content that was selected from this message
+ // Use the original content if the message is fully selected, otherwise get selected portion
+ let selectedText = '';
+
+ // Find the message content element (the actual text, not header)
+ const contentElement = msgEl.querySelector('[class*="MessageTextBody"], [class*="message-content"]');
+ if (contentElement) {
+ const clonedRange = range.cloneRange();
+ clonedRange.selectNodeContents(contentElement);
+
+ // Intersect with selection
+ if (range.compareBoundaryPoints(Range.START_TO_START, clonedRange) > 0) {
+ clonedRange.setStart(range.startContainer, range.startOffset);
+ }
+ if (range.compareBoundaryPoints(Range.END_TO_END, clonedRange) < 0) {
+ clonedRange.setEnd(range.endContainer, range.endOffset);
+ }
+
+ selectedText = clonedRange.toString().trim();
+ } else {
+ // Fallback: use all selected text in this message
+ selectedText = range.toString().trim();
+ }
+
+ if (selectedText) {
+ messages.push({
+ sender: data.sender,
+ time: timeStr,
+ content: selectedText,
+ });
+ }
+ });
+
+ // If we found formatted messages, use our format
+ if (messages.length > 0) {
+ const formattedText = messages
+ .map((msg) => `${msg.sender} - ${msg.time}: ${msg.content}`)
+ .join('\n');
+
+ event.preventDefault();
+ event.clipboardData?.setData('text/plain', formattedText);
+ }
+ };
+
+ container.addEventListener('copy', handleCopy);
+ return () => container.removeEventListener('copy', handleCopy);
+};
diff --git a/src/client/initMatrix.ts b/src/client/initMatrix.ts
index 487c3f1..8cfe09b 100644
--- a/src/client/initMatrix.ts
+++ b/src/client/initMatrix.ts
@@ -35,6 +35,17 @@ export const initClient = async (session: Session): Promise => {
await mx.initRustCrypto();
mx.setMaxListeners(50);
+
+ // Increase max listeners for User objects to prevent warnings when many components
+ // subscribe to presence events (e.g., in member lists)
+ const originalGetUser = mx.getUser.bind(mx);
+ mx.getUser = (userId: string) => {
+ const user = originalGetUser(userId);
+ if (user) {
+ user.setMaxListeners(50);
+ }
+ return user;
+ };
return mx;
};
diff --git a/src/index.css b/src/index.css
index 7704600..d963b2e 100644
--- a/src/index.css
+++ b/src/index.css
@@ -69,6 +69,9 @@ html {
--safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
--safe-area-inset-left: env(safe-area-inset-left, 0px);
--safe-area-inset-right: env(safe-area-inset-right, 0px);
+ /* Window rounding for borderless window */
+ border-radius: 4px;
+ overflow: hidden;
}
body {
@@ -85,6 +88,9 @@ body {
font-weight: 400;
/* Default to dark theme background for safe areas */
background-color: #1A1A1A;
+ /* Window rounding */
+ border-radius: 4px;
+ overflow: hidden;
/*Why font-variant-ligatures => https://github.com/rsms/inter/issues/222 */
font-variant-ligatures: no-contextual;
@@ -108,6 +114,8 @@ body.butter-theme {
height: 100%;
display: flex;
flex-direction: column;
+ border-radius: 4px;
+ overflow: hidden;
}
*,
diff --git a/src/types/matrix/room.ts b/src/types/matrix/room.ts
index d3c3d05..fa58acc 100644
--- a/src/types/matrix/room.ts
+++ b/src/types/matrix/room.ts
@@ -42,6 +42,9 @@ export enum StateEvent {
/** Room-wide link embed filter patterns (admin-controlled) */
RoomEmbedFilters = 'im.paarrot.room.embed_filters',
+ /** Room-specific LiveKit service URL (admin-controlled) */
+ RoomLivekitConfig = 'im.paarrot.room.livekit_config',
+
/** Matrix RTC call membership (MSC3401) */
CallMember = 'org.matrix.msc3401.call.member',
}
diff --git a/vite.config.js.timestamp-1771641468415-046b313db8c4b.mjs b/vite.config.js.timestamp-1771641468415-046b313db8c4b.mjs
new file mode 100644
index 0000000..2e2889a
--- /dev/null
+++ b/vite.config.js.timestamp-1771641468415-046b313db8c4b.mjs
@@ -0,0 +1,165 @@
+// vite.config.js
+import { defineConfig } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite/dist/node/index.js";
+import react from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vitejs/plugin-react/dist/index.mjs";
+import { wasm } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-wasm/dist/es/index.js";
+import { viteStaticCopy } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-static-copy/dist/index.js";
+import { vanillaExtractPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vanilla-extract/vite-plugin/dist/vanilla-extract-vite-plugin.cjs.js";
+import { NodeGlobalsPolyfillPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@esbuild-plugins/node-globals-polyfill/dist/index.js";
+import inject from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-inject/dist/es/index.js";
+import topLevelAwait from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-top-level-await/exports/import.mjs";
+import { VitePWA } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-pwa/dist/index.js";
+import fs from "fs";
+import path from "path";
+
+// build.config.ts
+var build_config_default = {
+ base: "/"
+};
+
+// vite.config.js
+var copyFiles = {
+ targets: [
+ {
+ src: "node_modules/pdfjs-dist/build/pdf.worker.min.mjs",
+ dest: "",
+ rename: "pdf.worker.min.js"
+ },
+ {
+ src: "node_modules/gif.js/dist/gif.worker.js",
+ dest: ""
+ },
+ {
+ src: "netlify.toml",
+ dest: ""
+ },
+ {
+ src: "config.json",
+ dest: ""
+ },
+ {
+ src: "public/manifest.json",
+ dest: ""
+ },
+ {
+ src: "public/res/android",
+ dest: "public/"
+ },
+ {
+ src: "public/locales",
+ dest: "public/"
+ }
+ ]
+};
+function serverMatrixSdkCryptoWasm(wasmFilePath) {
+ return {
+ name: "vite-plugin-serve-matrix-sdk-crypto-wasm",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === wasmFilePath) {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.wasm");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/wasm");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+function serveGifWorker() {
+ return {
+ name: "vite-plugin-serve-gif-worker",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === "/gif.worker.js") {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/gif.js/dist/gif.worker.js");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+var vite_config_default = defineConfig({
+ appType: "spa",
+ publicDir: false,
+ base: build_config_default.base,
+ server: {
+ port: 8080,
+ host: "0.0.0.0",
+ fs: {
+ // Allow serving files from one level up to the project root
+ allow: [".."]
+ }
+ },
+ plugins: [
+ serverMatrixSdkCryptoWasm("/node_modules/.vite/deps/pkg/matrix_sdk_crypto_wasm_bg.wasm"),
+ serveGifWorker(),
+ topLevelAwait({
+ // The export name of top-level await promise for each chunk module
+ promiseExportName: "__tla",
+ // The function to generate import names of top-level await promise in each chunk module
+ promiseImportName: (i) => `__tla_${i}`
+ }),
+ viteStaticCopy(copyFiles),
+ vanillaExtractPlugin(),
+ wasm(),
+ react(),
+ VitePWA({
+ srcDir: "src",
+ filename: "sw.ts",
+ strategies: "injectManifest",
+ injectRegister: false,
+ manifest: false,
+ injectManifest: {
+ injectionPoint: void 0
+ },
+ devOptions: {
+ enabled: false,
+ type: "module"
+ }
+ })
+ ],
+ optimizeDeps: {
+ esbuildOptions: {
+ define: {
+ global: "globalThis"
+ },
+ plugins: [
+ // Enable esbuild polyfill plugins
+ NodeGlobalsPolyfillPlugin({
+ process: false,
+ buffer: true
+ })
+ ]
+ }
+ },
+ build: {
+ outDir: "dist",
+ sourcemap: true,
+ copyPublicDir: false,
+ rollupOptions: {
+ plugins: [inject({ Buffer: ["buffer", "Buffer"] })]
+ }
+ }
+});
+export {
+ vite_config_default as default
+};
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAiYnVpbGQuY29uZmlnLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3QnO1xuaW1wb3J0IHsgd2FzbSB9IGZyb20gJ0Byb2xsdXAvcGx1Z2luLXdhc20nO1xuaW1wb3J0IHsgdml0ZVN0YXRpY0NvcHkgfSBmcm9tICd2aXRlLXBsdWdpbi1zdGF0aWMtY29weSc7XG5pbXBvcnQgeyB2YW5pbGxhRXh0cmFjdFBsdWdpbiB9IGZyb20gJ0B2YW5pbGxhLWV4dHJhY3Qvdml0ZS1wbHVnaW4nO1xuaW1wb3J0IHsgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbiB9IGZyb20gJ0Blc2J1aWxkLXBsdWdpbnMvbm9kZS1nbG9iYWxzLXBvbHlmaWxsJztcbmltcG9ydCBpbmplY3QgZnJvbSAnQHJvbGx1cC9wbHVnaW4taW5qZWN0JztcbmltcG9ydCB0b3BMZXZlbEF3YWl0IGZyb20gJ3ZpdGUtcGx1Z2luLXRvcC1sZXZlbC1hd2FpdCc7XG5pbXBvcnQgeyBWaXRlUFdBIH0gZnJvbSAndml0ZS1wbHVnaW4tcHdhJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBidWlsZENvbmZpZyBmcm9tICcuL2J1aWxkLmNvbmZpZyc7XG5cbmNvbnN0IGNvcHlGaWxlcyA9IHtcbiAgdGFyZ2V0czogW1xuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9wZGZqcy1kaXN0L2J1aWxkL3BkZi53b3JrZXIubWluLm1qcycsXG4gICAgICBkZXN0OiAnJyxcbiAgICAgIHJlbmFtZTogJ3BkZi53b3JrZXIubWluLmpzJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnbmV0bGlmeS50b21sJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnY29uZmlnLmpzb24nLFxuICAgICAgZGVzdDogJycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbWFuaWZlc3QuanNvbicsXG4gICAgICBkZXN0OiAnJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ3B1YmxpYy9yZXMvYW5kcm9pZCcsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbG9jYWxlcycsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgXSxcbn07XG5cbmZ1bmN0aW9uIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20od2FzbUZpbGVQYXRoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLW1hdHJpeC1zZGstY3J5cHRvLXdhc20nLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSB3YXNtRmlsZVBhdGgpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSBwYXRoLmpvaW4ocGF0aC5yZXNvbHZlKCksIFwiL25vZGVfbW9kdWxlcy9AbWF0cml4LW9yZy9tYXRyaXgtc2RrLWNyeXB0by13YXNtL3BrZy9tYXRyaXhfc2RrX2NyeXB0b193YXNtX2JnLndhc21cIik7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vd2FzbScpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2VydmVHaWZXb3JrZXIoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLWdpZi13b3JrZXInLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSAnL2dpZi53b3JrZXIuanMnKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcGF0aC5qb2luKHBhdGgucmVzb2x2ZSgpLCAnL25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyk7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vamF2YXNjcmlwdCcpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgYXBwVHlwZTogJ3NwYScsXG4gIHB1YmxpY0RpcjogZmFsc2UsXG4gIGJhc2U6IGJ1aWxkQ29uZmlnLmJhc2UsXG4gIHNlcnZlcjoge1xuICAgIHBvcnQ6IDgwODAsXG4gICAgaG9zdDogJzAuMC4wLjAnLFxuICAgIGZzOiB7XG4gICAgICAvLyBBbGxvdyBzZXJ2aW5nIGZpbGVzIGZyb20gb25lIGxldmVsIHVwIHRvIHRoZSBwcm9qZWN0IHJvb3RcbiAgICAgIGFsbG93OiBbJy4uJ10sXG4gICAgfSxcbiAgfSxcbiAgcGx1Z2luczogW1xuICAgIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20oJy9ub2RlX21vZHVsZXMvLnZpdGUvZGVwcy9wa2cvbWF0cml4X3Nka19jcnlwdG9fd2FzbV9iZy53YXNtJyksXG4gICAgc2VydmVHaWZXb3JrZXIoKSxcbiAgICB0b3BMZXZlbEF3YWl0KHtcbiAgICAgIC8vIFRoZSBleHBvcnQgbmFtZSBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBmb3IgZWFjaCBjaHVuayBtb2R1bGVcbiAgICAgIHByb21pc2VFeHBvcnROYW1lOiAnX190bGEnLFxuICAgICAgLy8gVGhlIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGltcG9ydCBuYW1lcyBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBpbiBlYWNoIGNodW5rIG1vZHVsZVxuICAgICAgcHJvbWlzZUltcG9ydE5hbWU6IChpKSA9PiBgX190bGFfJHtpfWAsXG4gICAgfSksXG4gICAgdml0ZVN0YXRpY0NvcHkoY29weUZpbGVzKSxcbiAgICB2YW5pbGxhRXh0cmFjdFBsdWdpbigpLFxuICAgIHdhc20oKSxcbiAgICByZWFjdCgpLFxuICAgIFZpdGVQV0Eoe1xuICAgICAgc3JjRGlyOiAnc3JjJyxcbiAgICAgIGZpbGVuYW1lOiAnc3cudHMnLFxuICAgICAgc3RyYXRlZ2llczogJ2luamVjdE1hbmlmZXN0JyxcbiAgICAgIGluamVjdFJlZ2lzdGVyOiBmYWxzZSxcbiAgICAgIG1hbmlmZXN0OiBmYWxzZSxcbiAgICAgIGluamVjdE1hbmlmZXN0OiB7XG4gICAgICAgIGluamVjdGlvblBvaW50OiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgICAgZGV2T3B0aW9uczoge1xuICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgdHlwZTogJ21vZHVsZSdcbiAgICAgIH1cbiAgICB9KSxcbiAgXSxcbiAgb3B0aW1pemVEZXBzOiB7XG4gICAgZXNidWlsZE9wdGlvbnM6IHtcbiAgICAgIGRlZmluZToge1xuICAgICAgICBnbG9iYWw6ICdnbG9iYWxUaGlzJyxcbiAgICAgIH0sXG4gICAgICBwbHVnaW5zOiBbXG4gICAgICAgIC8vIEVuYWJsZSBlc2J1aWxkIHBvbHlmaWxsIHBsdWdpbnNcbiAgICAgICAgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbih7XG4gICAgICAgICAgcHJvY2VzczogZmFsc2UsXG4gICAgICAgICAgYnVmZmVyOiB0cnVlLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSxcbiAgfSxcbiAgYnVpbGQ6IHtcbiAgICBvdXREaXI6ICdkaXN0JyxcbiAgICBzb3VyY2VtYXA6IHRydWUsXG4gICAgY29weVB1YmxpY0RpcjogZmFsc2UsXG4gICAgcm9sbHVwT3B0aW9uczoge1xuICAgICAgcGx1Z2luczogW2luamVjdCh7IEJ1ZmZlcjogWydidWZmZXInLCAnQnVmZmVyJ10gfSldLFxuICAgIH0sXG4gIH0sXG59KTtcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L2J1aWxkLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9saXRydXYvRGV2ZWxvcG1lbnQvY2lubnktZGVza3RvcC9jaW5ueS9idWlsZC5jb25maWcudHNcIjtleHBvcnQgZGVmYXVsdCB7XG4gIGJhc2U6ICcvJyxcbn07XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXNULFNBQVMsb0JBQW9CO0FBQ25WLE9BQU8sV0FBVztBQUNsQixTQUFTLFlBQVk7QUFDckIsU0FBUyxzQkFBc0I7QUFDL0IsU0FBUyw0QkFBNEI7QUFDckMsU0FBUyxpQ0FBaUM7QUFDMUMsT0FBTyxZQUFZO0FBQ25CLE9BQU8sbUJBQW1CO0FBQzFCLFNBQVMsZUFBZTtBQUN4QixPQUFPLFFBQVE7QUFDZixPQUFPLFVBQVU7OztBQ1Z1UyxJQUFPLHVCQUFRO0FBQUEsRUFDclUsTUFBTTtBQUNSOzs7QURXQSxJQUFNLFlBQVk7QUFBQSxFQUNoQixTQUFT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
diff --git a/vite.config.js.timestamp-1771641863062-566dfacb5223d.mjs b/vite.config.js.timestamp-1771641863062-566dfacb5223d.mjs
new file mode 100644
index 0000000..2e2889a
--- /dev/null
+++ b/vite.config.js.timestamp-1771641863062-566dfacb5223d.mjs
@@ -0,0 +1,165 @@
+// vite.config.js
+import { defineConfig } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite/dist/node/index.js";
+import react from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vitejs/plugin-react/dist/index.mjs";
+import { wasm } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-wasm/dist/es/index.js";
+import { viteStaticCopy } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-static-copy/dist/index.js";
+import { vanillaExtractPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vanilla-extract/vite-plugin/dist/vanilla-extract-vite-plugin.cjs.js";
+import { NodeGlobalsPolyfillPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@esbuild-plugins/node-globals-polyfill/dist/index.js";
+import inject from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-inject/dist/es/index.js";
+import topLevelAwait from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-top-level-await/exports/import.mjs";
+import { VitePWA } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-pwa/dist/index.js";
+import fs from "fs";
+import path from "path";
+
+// build.config.ts
+var build_config_default = {
+ base: "/"
+};
+
+// vite.config.js
+var copyFiles = {
+ targets: [
+ {
+ src: "node_modules/pdfjs-dist/build/pdf.worker.min.mjs",
+ dest: "",
+ rename: "pdf.worker.min.js"
+ },
+ {
+ src: "node_modules/gif.js/dist/gif.worker.js",
+ dest: ""
+ },
+ {
+ src: "netlify.toml",
+ dest: ""
+ },
+ {
+ src: "config.json",
+ dest: ""
+ },
+ {
+ src: "public/manifest.json",
+ dest: ""
+ },
+ {
+ src: "public/res/android",
+ dest: "public/"
+ },
+ {
+ src: "public/locales",
+ dest: "public/"
+ }
+ ]
+};
+function serverMatrixSdkCryptoWasm(wasmFilePath) {
+ return {
+ name: "vite-plugin-serve-matrix-sdk-crypto-wasm",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === wasmFilePath) {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.wasm");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/wasm");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+function serveGifWorker() {
+ return {
+ name: "vite-plugin-serve-gif-worker",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === "/gif.worker.js") {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/gif.js/dist/gif.worker.js");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+var vite_config_default = defineConfig({
+ appType: "spa",
+ publicDir: false,
+ base: build_config_default.base,
+ server: {
+ port: 8080,
+ host: "0.0.0.0",
+ fs: {
+ // Allow serving files from one level up to the project root
+ allow: [".."]
+ }
+ },
+ plugins: [
+ serverMatrixSdkCryptoWasm("/node_modules/.vite/deps/pkg/matrix_sdk_crypto_wasm_bg.wasm"),
+ serveGifWorker(),
+ topLevelAwait({
+ // The export name of top-level await promise for each chunk module
+ promiseExportName: "__tla",
+ // The function to generate import names of top-level await promise in each chunk module
+ promiseImportName: (i) => `__tla_${i}`
+ }),
+ viteStaticCopy(copyFiles),
+ vanillaExtractPlugin(),
+ wasm(),
+ react(),
+ VitePWA({
+ srcDir: "src",
+ filename: "sw.ts",
+ strategies: "injectManifest",
+ injectRegister: false,
+ manifest: false,
+ injectManifest: {
+ injectionPoint: void 0
+ },
+ devOptions: {
+ enabled: false,
+ type: "module"
+ }
+ })
+ ],
+ optimizeDeps: {
+ esbuildOptions: {
+ define: {
+ global: "globalThis"
+ },
+ plugins: [
+ // Enable esbuild polyfill plugins
+ NodeGlobalsPolyfillPlugin({
+ process: false,
+ buffer: true
+ })
+ ]
+ }
+ },
+ build: {
+ outDir: "dist",
+ sourcemap: true,
+ copyPublicDir: false,
+ rollupOptions: {
+ plugins: [inject({ Buffer: ["buffer", "Buffer"] })]
+ }
+ }
+});
+export {
+ vite_config_default as default
+};
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAiYnVpbGQuY29uZmlnLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3QnO1xuaW1wb3J0IHsgd2FzbSB9IGZyb20gJ0Byb2xsdXAvcGx1Z2luLXdhc20nO1xuaW1wb3J0IHsgdml0ZVN0YXRpY0NvcHkgfSBmcm9tICd2aXRlLXBsdWdpbi1zdGF0aWMtY29weSc7XG5pbXBvcnQgeyB2YW5pbGxhRXh0cmFjdFBsdWdpbiB9IGZyb20gJ0B2YW5pbGxhLWV4dHJhY3Qvdml0ZS1wbHVnaW4nO1xuaW1wb3J0IHsgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbiB9IGZyb20gJ0Blc2J1aWxkLXBsdWdpbnMvbm9kZS1nbG9iYWxzLXBvbHlmaWxsJztcbmltcG9ydCBpbmplY3QgZnJvbSAnQHJvbGx1cC9wbHVnaW4taW5qZWN0JztcbmltcG9ydCB0b3BMZXZlbEF3YWl0IGZyb20gJ3ZpdGUtcGx1Z2luLXRvcC1sZXZlbC1hd2FpdCc7XG5pbXBvcnQgeyBWaXRlUFdBIH0gZnJvbSAndml0ZS1wbHVnaW4tcHdhJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBidWlsZENvbmZpZyBmcm9tICcuL2J1aWxkLmNvbmZpZyc7XG5cbmNvbnN0IGNvcHlGaWxlcyA9IHtcbiAgdGFyZ2V0czogW1xuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9wZGZqcy1kaXN0L2J1aWxkL3BkZi53b3JrZXIubWluLm1qcycsXG4gICAgICBkZXN0OiAnJyxcbiAgICAgIHJlbmFtZTogJ3BkZi53b3JrZXIubWluLmpzJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnbmV0bGlmeS50b21sJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnY29uZmlnLmpzb24nLFxuICAgICAgZGVzdDogJycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbWFuaWZlc3QuanNvbicsXG4gICAgICBkZXN0OiAnJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ3B1YmxpYy9yZXMvYW5kcm9pZCcsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbG9jYWxlcycsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgXSxcbn07XG5cbmZ1bmN0aW9uIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20od2FzbUZpbGVQYXRoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLW1hdHJpeC1zZGstY3J5cHRvLXdhc20nLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSB3YXNtRmlsZVBhdGgpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSBwYXRoLmpvaW4ocGF0aC5yZXNvbHZlKCksIFwiL25vZGVfbW9kdWxlcy9AbWF0cml4LW9yZy9tYXRyaXgtc2RrLWNyeXB0by13YXNtL3BrZy9tYXRyaXhfc2RrX2NyeXB0b193YXNtX2JnLndhc21cIik7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vd2FzbScpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2VydmVHaWZXb3JrZXIoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLWdpZi13b3JrZXInLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSAnL2dpZi53b3JrZXIuanMnKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcGF0aC5qb2luKHBhdGgucmVzb2x2ZSgpLCAnL25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyk7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vamF2YXNjcmlwdCcpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgYXBwVHlwZTogJ3NwYScsXG4gIHB1YmxpY0RpcjogZmFsc2UsXG4gIGJhc2U6IGJ1aWxkQ29uZmlnLmJhc2UsXG4gIHNlcnZlcjoge1xuICAgIHBvcnQ6IDgwODAsXG4gICAgaG9zdDogJzAuMC4wLjAnLFxuICAgIGZzOiB7XG4gICAgICAvLyBBbGxvdyBzZXJ2aW5nIGZpbGVzIGZyb20gb25lIGxldmVsIHVwIHRvIHRoZSBwcm9qZWN0IHJvb3RcbiAgICAgIGFsbG93OiBbJy4uJ10sXG4gICAgfSxcbiAgfSxcbiAgcGx1Z2luczogW1xuICAgIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20oJy9ub2RlX21vZHVsZXMvLnZpdGUvZGVwcy9wa2cvbWF0cml4X3Nka19jcnlwdG9fd2FzbV9iZy53YXNtJyksXG4gICAgc2VydmVHaWZXb3JrZXIoKSxcbiAgICB0b3BMZXZlbEF3YWl0KHtcbiAgICAgIC8vIFRoZSBleHBvcnQgbmFtZSBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBmb3IgZWFjaCBjaHVuayBtb2R1bGVcbiAgICAgIHByb21pc2VFeHBvcnROYW1lOiAnX190bGEnLFxuICAgICAgLy8gVGhlIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGltcG9ydCBuYW1lcyBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBpbiBlYWNoIGNodW5rIG1vZHVsZVxuICAgICAgcHJvbWlzZUltcG9ydE5hbWU6IChpKSA9PiBgX190bGFfJHtpfWAsXG4gICAgfSksXG4gICAgdml0ZVN0YXRpY0NvcHkoY29weUZpbGVzKSxcbiAgICB2YW5pbGxhRXh0cmFjdFBsdWdpbigpLFxuICAgIHdhc20oKSxcbiAgICByZWFjdCgpLFxuICAgIFZpdGVQV0Eoe1xuICAgICAgc3JjRGlyOiAnc3JjJyxcbiAgICAgIGZpbGVuYW1lOiAnc3cudHMnLFxuICAgICAgc3RyYXRlZ2llczogJ2luamVjdE1hbmlmZXN0JyxcbiAgICAgIGluamVjdFJlZ2lzdGVyOiBmYWxzZSxcbiAgICAgIG1hbmlmZXN0OiBmYWxzZSxcbiAgICAgIGluamVjdE1hbmlmZXN0OiB7XG4gICAgICAgIGluamVjdGlvblBvaW50OiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgICAgZGV2T3B0aW9uczoge1xuICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgdHlwZTogJ21vZHVsZSdcbiAgICAgIH1cbiAgICB9KSxcbiAgXSxcbiAgb3B0aW1pemVEZXBzOiB7XG4gICAgZXNidWlsZE9wdGlvbnM6IHtcbiAgICAgIGRlZmluZToge1xuICAgICAgICBnbG9iYWw6ICdnbG9iYWxUaGlzJyxcbiAgICAgIH0sXG4gICAgICBwbHVnaW5zOiBbXG4gICAgICAgIC8vIEVuYWJsZSBlc2J1aWxkIHBvbHlmaWxsIHBsdWdpbnNcbiAgICAgICAgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbih7XG4gICAgICAgICAgcHJvY2VzczogZmFsc2UsXG4gICAgICAgICAgYnVmZmVyOiB0cnVlLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSxcbiAgfSxcbiAgYnVpbGQ6IHtcbiAgICBvdXREaXI6ICdkaXN0JyxcbiAgICBzb3VyY2VtYXA6IHRydWUsXG4gICAgY29weVB1YmxpY0RpcjogZmFsc2UsXG4gICAgcm9sbHVwT3B0aW9uczoge1xuICAgICAgcGx1Z2luczogW2luamVjdCh7IEJ1ZmZlcjogWydidWZmZXInLCAnQnVmZmVyJ10gfSldLFxuICAgIH0sXG4gIH0sXG59KTtcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L2J1aWxkLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9saXRydXYvRGV2ZWxvcG1lbnQvY2lubnktZGVza3RvcC9jaW5ueS9idWlsZC5jb25maWcudHNcIjtleHBvcnQgZGVmYXVsdCB7XG4gIGJhc2U6ICcvJyxcbn07XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXNULFNBQVMsb0JBQW9CO0FBQ25WLE9BQU8sV0FBVztBQUNsQixTQUFTLFlBQVk7QUFDckIsU0FBUyxzQkFBc0I7QUFDL0IsU0FBUyw0QkFBNEI7QUFDckMsU0FBUyxpQ0FBaUM7QUFDMUMsT0FBTyxZQUFZO0FBQ25CLE9BQU8sbUJBQW1CO0FBQzFCLFNBQVMsZUFBZTtBQUN4QixPQUFPLFFBQVE7QUFDZixPQUFPLFVBQVU7OztBQ1Z1UyxJQUFPLHVCQUFRO0FBQUEsRUFDclUsTUFBTTtBQUNSOzs7QURXQSxJQUFNLFlBQVk7QUFBQSxFQUNoQixTQUFT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
diff --git a/vite.config.js.timestamp-1771642098574-00e5d9a55dc42.mjs b/vite.config.js.timestamp-1771642098574-00e5d9a55dc42.mjs
new file mode 100644
index 0000000..2e2889a
--- /dev/null
+++ b/vite.config.js.timestamp-1771642098574-00e5d9a55dc42.mjs
@@ -0,0 +1,165 @@
+// vite.config.js
+import { defineConfig } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite/dist/node/index.js";
+import react from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vitejs/plugin-react/dist/index.mjs";
+import { wasm } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-wasm/dist/es/index.js";
+import { viteStaticCopy } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-static-copy/dist/index.js";
+import { vanillaExtractPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vanilla-extract/vite-plugin/dist/vanilla-extract-vite-plugin.cjs.js";
+import { NodeGlobalsPolyfillPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@esbuild-plugins/node-globals-polyfill/dist/index.js";
+import inject from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-inject/dist/es/index.js";
+import topLevelAwait from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-top-level-await/exports/import.mjs";
+import { VitePWA } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-pwa/dist/index.js";
+import fs from "fs";
+import path from "path";
+
+// build.config.ts
+var build_config_default = {
+ base: "/"
+};
+
+// vite.config.js
+var copyFiles = {
+ targets: [
+ {
+ src: "node_modules/pdfjs-dist/build/pdf.worker.min.mjs",
+ dest: "",
+ rename: "pdf.worker.min.js"
+ },
+ {
+ src: "node_modules/gif.js/dist/gif.worker.js",
+ dest: ""
+ },
+ {
+ src: "netlify.toml",
+ dest: ""
+ },
+ {
+ src: "config.json",
+ dest: ""
+ },
+ {
+ src: "public/manifest.json",
+ dest: ""
+ },
+ {
+ src: "public/res/android",
+ dest: "public/"
+ },
+ {
+ src: "public/locales",
+ dest: "public/"
+ }
+ ]
+};
+function serverMatrixSdkCryptoWasm(wasmFilePath) {
+ return {
+ name: "vite-plugin-serve-matrix-sdk-crypto-wasm",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === wasmFilePath) {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.wasm");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/wasm");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+function serveGifWorker() {
+ return {
+ name: "vite-plugin-serve-gif-worker",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === "/gif.worker.js") {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/gif.js/dist/gif.worker.js");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+var vite_config_default = defineConfig({
+ appType: "spa",
+ publicDir: false,
+ base: build_config_default.base,
+ server: {
+ port: 8080,
+ host: "0.0.0.0",
+ fs: {
+ // Allow serving files from one level up to the project root
+ allow: [".."]
+ }
+ },
+ plugins: [
+ serverMatrixSdkCryptoWasm("/node_modules/.vite/deps/pkg/matrix_sdk_crypto_wasm_bg.wasm"),
+ serveGifWorker(),
+ topLevelAwait({
+ // The export name of top-level await promise for each chunk module
+ promiseExportName: "__tla",
+ // The function to generate import names of top-level await promise in each chunk module
+ promiseImportName: (i) => `__tla_${i}`
+ }),
+ viteStaticCopy(copyFiles),
+ vanillaExtractPlugin(),
+ wasm(),
+ react(),
+ VitePWA({
+ srcDir: "src",
+ filename: "sw.ts",
+ strategies: "injectManifest",
+ injectRegister: false,
+ manifest: false,
+ injectManifest: {
+ injectionPoint: void 0
+ },
+ devOptions: {
+ enabled: false,
+ type: "module"
+ }
+ })
+ ],
+ optimizeDeps: {
+ esbuildOptions: {
+ define: {
+ global: "globalThis"
+ },
+ plugins: [
+ // Enable esbuild polyfill plugins
+ NodeGlobalsPolyfillPlugin({
+ process: false,
+ buffer: true
+ })
+ ]
+ }
+ },
+ build: {
+ outDir: "dist",
+ sourcemap: true,
+ copyPublicDir: false,
+ rollupOptions: {
+ plugins: [inject({ Buffer: ["buffer", "Buffer"] })]
+ }
+ }
+});
+export {
+ vite_config_default as default
+};
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAiYnVpbGQuY29uZmlnLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3QnO1xuaW1wb3J0IHsgd2FzbSB9IGZyb20gJ0Byb2xsdXAvcGx1Z2luLXdhc20nO1xuaW1wb3J0IHsgdml0ZVN0YXRpY0NvcHkgfSBmcm9tICd2aXRlLXBsdWdpbi1zdGF0aWMtY29weSc7XG5pbXBvcnQgeyB2YW5pbGxhRXh0cmFjdFBsdWdpbiB9IGZyb20gJ0B2YW5pbGxhLWV4dHJhY3Qvdml0ZS1wbHVnaW4nO1xuaW1wb3J0IHsgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbiB9IGZyb20gJ0Blc2J1aWxkLXBsdWdpbnMvbm9kZS1nbG9iYWxzLXBvbHlmaWxsJztcbmltcG9ydCBpbmplY3QgZnJvbSAnQHJvbGx1cC9wbHVnaW4taW5qZWN0JztcbmltcG9ydCB0b3BMZXZlbEF3YWl0IGZyb20gJ3ZpdGUtcGx1Z2luLXRvcC1sZXZlbC1hd2FpdCc7XG5pbXBvcnQgeyBWaXRlUFdBIH0gZnJvbSAndml0ZS1wbHVnaW4tcHdhJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBidWlsZENvbmZpZyBmcm9tICcuL2J1aWxkLmNvbmZpZyc7XG5cbmNvbnN0IGNvcHlGaWxlcyA9IHtcbiAgdGFyZ2V0czogW1xuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9wZGZqcy1kaXN0L2J1aWxkL3BkZi53b3JrZXIubWluLm1qcycsXG4gICAgICBkZXN0OiAnJyxcbiAgICAgIHJlbmFtZTogJ3BkZi53b3JrZXIubWluLmpzJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnbmV0bGlmeS50b21sJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnY29uZmlnLmpzb24nLFxuICAgICAgZGVzdDogJycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbWFuaWZlc3QuanNvbicsXG4gICAgICBkZXN0OiAnJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ3B1YmxpYy9yZXMvYW5kcm9pZCcsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbG9jYWxlcycsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgXSxcbn07XG5cbmZ1bmN0aW9uIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20od2FzbUZpbGVQYXRoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLW1hdHJpeC1zZGstY3J5cHRvLXdhc20nLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSB3YXNtRmlsZVBhdGgpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSBwYXRoLmpvaW4ocGF0aC5yZXNvbHZlKCksIFwiL25vZGVfbW9kdWxlcy9AbWF0cml4LW9yZy9tYXRyaXgtc2RrLWNyeXB0by13YXNtL3BrZy9tYXRyaXhfc2RrX2NyeXB0b193YXNtX2JnLndhc21cIik7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vd2FzbScpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2VydmVHaWZXb3JrZXIoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLWdpZi13b3JrZXInLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSAnL2dpZi53b3JrZXIuanMnKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcGF0aC5qb2luKHBhdGgucmVzb2x2ZSgpLCAnL25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyk7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vamF2YXNjcmlwdCcpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgYXBwVHlwZTogJ3NwYScsXG4gIHB1YmxpY0RpcjogZmFsc2UsXG4gIGJhc2U6IGJ1aWxkQ29uZmlnLmJhc2UsXG4gIHNlcnZlcjoge1xuICAgIHBvcnQ6IDgwODAsXG4gICAgaG9zdDogJzAuMC4wLjAnLFxuICAgIGZzOiB7XG4gICAgICAvLyBBbGxvdyBzZXJ2aW5nIGZpbGVzIGZyb20gb25lIGxldmVsIHVwIHRvIHRoZSBwcm9qZWN0IHJvb3RcbiAgICAgIGFsbG93OiBbJy4uJ10sXG4gICAgfSxcbiAgfSxcbiAgcGx1Z2luczogW1xuICAgIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20oJy9ub2RlX21vZHVsZXMvLnZpdGUvZGVwcy9wa2cvbWF0cml4X3Nka19jcnlwdG9fd2FzbV9iZy53YXNtJyksXG4gICAgc2VydmVHaWZXb3JrZXIoKSxcbiAgICB0b3BMZXZlbEF3YWl0KHtcbiAgICAgIC8vIFRoZSBleHBvcnQgbmFtZSBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBmb3IgZWFjaCBjaHVuayBtb2R1bGVcbiAgICAgIHByb21pc2VFeHBvcnROYW1lOiAnX190bGEnLFxuICAgICAgLy8gVGhlIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGltcG9ydCBuYW1lcyBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBpbiBlYWNoIGNodW5rIG1vZHVsZVxuICAgICAgcHJvbWlzZUltcG9ydE5hbWU6IChpKSA9PiBgX190bGFfJHtpfWAsXG4gICAgfSksXG4gICAgdml0ZVN0YXRpY0NvcHkoY29weUZpbGVzKSxcbiAgICB2YW5pbGxhRXh0cmFjdFBsdWdpbigpLFxuICAgIHdhc20oKSxcbiAgICByZWFjdCgpLFxuICAgIFZpdGVQV0Eoe1xuICAgICAgc3JjRGlyOiAnc3JjJyxcbiAgICAgIGZpbGVuYW1lOiAnc3cudHMnLFxuICAgICAgc3RyYXRlZ2llczogJ2luamVjdE1hbmlmZXN0JyxcbiAgICAgIGluamVjdFJlZ2lzdGVyOiBmYWxzZSxcbiAgICAgIG1hbmlmZXN0OiBmYWxzZSxcbiAgICAgIGluamVjdE1hbmlmZXN0OiB7XG4gICAgICAgIGluamVjdGlvblBvaW50OiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgICAgZGV2T3B0aW9uczoge1xuICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgdHlwZTogJ21vZHVsZSdcbiAgICAgIH1cbiAgICB9KSxcbiAgXSxcbiAgb3B0aW1pemVEZXBzOiB7XG4gICAgZXNidWlsZE9wdGlvbnM6IHtcbiAgICAgIGRlZmluZToge1xuICAgICAgICBnbG9iYWw6ICdnbG9iYWxUaGlzJyxcbiAgICAgIH0sXG4gICAgICBwbHVnaW5zOiBbXG4gICAgICAgIC8vIEVuYWJsZSBlc2J1aWxkIHBvbHlmaWxsIHBsdWdpbnNcbiAgICAgICAgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbih7XG4gICAgICAgICAgcHJvY2VzczogZmFsc2UsXG4gICAgICAgICAgYnVmZmVyOiB0cnVlLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSxcbiAgfSxcbiAgYnVpbGQ6IHtcbiAgICBvdXREaXI6ICdkaXN0JyxcbiAgICBzb3VyY2VtYXA6IHRydWUsXG4gICAgY29weVB1YmxpY0RpcjogZmFsc2UsXG4gICAgcm9sbHVwT3B0aW9uczoge1xuICAgICAgcGx1Z2luczogW2luamVjdCh7IEJ1ZmZlcjogWydidWZmZXInLCAnQnVmZmVyJ10gfSldLFxuICAgIH0sXG4gIH0sXG59KTtcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L2J1aWxkLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9saXRydXYvRGV2ZWxvcG1lbnQvY2lubnktZGVza3RvcC9jaW5ueS9idWlsZC5jb25maWcudHNcIjtleHBvcnQgZGVmYXVsdCB7XG4gIGJhc2U6ICcvJyxcbn07XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXNULFNBQVMsb0JBQW9CO0FBQ25WLE9BQU8sV0FBVztBQUNsQixTQUFTLFlBQVk7QUFDckIsU0FBUyxzQkFBc0I7QUFDL0IsU0FBUyw0QkFBNEI7QUFDckMsU0FBUyxpQ0FBaUM7QUFDMUMsT0FBTyxZQUFZO0FBQ25CLE9BQU8sbUJBQW1CO0FBQzFCLFNBQVMsZUFBZTtBQUN4QixPQUFPLFFBQVE7QUFDZixPQUFPLFVBQVU7OztBQ1Z1UyxJQUFPLHVCQUFRO0FBQUEsRUFDclUsTUFBTTtBQUNSOzs7QURXQSxJQUFNLFlBQVk7QUFBQSxFQUNoQixTQUFT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
diff --git a/vite.config.js.timestamp-1771642338922-3a8734296d3bf.mjs b/vite.config.js.timestamp-1771642338922-3a8734296d3bf.mjs
new file mode 100644
index 0000000..2e2889a
--- /dev/null
+++ b/vite.config.js.timestamp-1771642338922-3a8734296d3bf.mjs
@@ -0,0 +1,165 @@
+// vite.config.js
+import { defineConfig } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite/dist/node/index.js";
+import react from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vitejs/plugin-react/dist/index.mjs";
+import { wasm } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-wasm/dist/es/index.js";
+import { viteStaticCopy } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-static-copy/dist/index.js";
+import { vanillaExtractPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vanilla-extract/vite-plugin/dist/vanilla-extract-vite-plugin.cjs.js";
+import { NodeGlobalsPolyfillPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@esbuild-plugins/node-globals-polyfill/dist/index.js";
+import inject from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-inject/dist/es/index.js";
+import topLevelAwait from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-top-level-await/exports/import.mjs";
+import { VitePWA } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-pwa/dist/index.js";
+import fs from "fs";
+import path from "path";
+
+// build.config.ts
+var build_config_default = {
+ base: "/"
+};
+
+// vite.config.js
+var copyFiles = {
+ targets: [
+ {
+ src: "node_modules/pdfjs-dist/build/pdf.worker.min.mjs",
+ dest: "",
+ rename: "pdf.worker.min.js"
+ },
+ {
+ src: "node_modules/gif.js/dist/gif.worker.js",
+ dest: ""
+ },
+ {
+ src: "netlify.toml",
+ dest: ""
+ },
+ {
+ src: "config.json",
+ dest: ""
+ },
+ {
+ src: "public/manifest.json",
+ dest: ""
+ },
+ {
+ src: "public/res/android",
+ dest: "public/"
+ },
+ {
+ src: "public/locales",
+ dest: "public/"
+ }
+ ]
+};
+function serverMatrixSdkCryptoWasm(wasmFilePath) {
+ return {
+ name: "vite-plugin-serve-matrix-sdk-crypto-wasm",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === wasmFilePath) {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.wasm");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/wasm");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+function serveGifWorker() {
+ return {
+ name: "vite-plugin-serve-gif-worker",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === "/gif.worker.js") {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/gif.js/dist/gif.worker.js");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+var vite_config_default = defineConfig({
+ appType: "spa",
+ publicDir: false,
+ base: build_config_default.base,
+ server: {
+ port: 8080,
+ host: "0.0.0.0",
+ fs: {
+ // Allow serving files from one level up to the project root
+ allow: [".."]
+ }
+ },
+ plugins: [
+ serverMatrixSdkCryptoWasm("/node_modules/.vite/deps/pkg/matrix_sdk_crypto_wasm_bg.wasm"),
+ serveGifWorker(),
+ topLevelAwait({
+ // The export name of top-level await promise for each chunk module
+ promiseExportName: "__tla",
+ // The function to generate import names of top-level await promise in each chunk module
+ promiseImportName: (i) => `__tla_${i}`
+ }),
+ viteStaticCopy(copyFiles),
+ vanillaExtractPlugin(),
+ wasm(),
+ react(),
+ VitePWA({
+ srcDir: "src",
+ filename: "sw.ts",
+ strategies: "injectManifest",
+ injectRegister: false,
+ manifest: false,
+ injectManifest: {
+ injectionPoint: void 0
+ },
+ devOptions: {
+ enabled: false,
+ type: "module"
+ }
+ })
+ ],
+ optimizeDeps: {
+ esbuildOptions: {
+ define: {
+ global: "globalThis"
+ },
+ plugins: [
+ // Enable esbuild polyfill plugins
+ NodeGlobalsPolyfillPlugin({
+ process: false,
+ buffer: true
+ })
+ ]
+ }
+ },
+ build: {
+ outDir: "dist",
+ sourcemap: true,
+ copyPublicDir: false,
+ rollupOptions: {
+ plugins: [inject({ Buffer: ["buffer", "Buffer"] })]
+ }
+ }
+});
+export {
+ vite_config_default as default
+};
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAiYnVpbGQuY29uZmlnLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3QnO1xuaW1wb3J0IHsgd2FzbSB9IGZyb20gJ0Byb2xsdXAvcGx1Z2luLXdhc20nO1xuaW1wb3J0IHsgdml0ZVN0YXRpY0NvcHkgfSBmcm9tICd2aXRlLXBsdWdpbi1zdGF0aWMtY29weSc7XG5pbXBvcnQgeyB2YW5pbGxhRXh0cmFjdFBsdWdpbiB9IGZyb20gJ0B2YW5pbGxhLWV4dHJhY3Qvdml0ZS1wbHVnaW4nO1xuaW1wb3J0IHsgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbiB9IGZyb20gJ0Blc2J1aWxkLXBsdWdpbnMvbm9kZS1nbG9iYWxzLXBvbHlmaWxsJztcbmltcG9ydCBpbmplY3QgZnJvbSAnQHJvbGx1cC9wbHVnaW4taW5qZWN0JztcbmltcG9ydCB0b3BMZXZlbEF3YWl0IGZyb20gJ3ZpdGUtcGx1Z2luLXRvcC1sZXZlbC1hd2FpdCc7XG5pbXBvcnQgeyBWaXRlUFdBIH0gZnJvbSAndml0ZS1wbHVnaW4tcHdhJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBidWlsZENvbmZpZyBmcm9tICcuL2J1aWxkLmNvbmZpZyc7XG5cbmNvbnN0IGNvcHlGaWxlcyA9IHtcbiAgdGFyZ2V0czogW1xuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9wZGZqcy1kaXN0L2J1aWxkL3BkZi53b3JrZXIubWluLm1qcycsXG4gICAgICBkZXN0OiAnJyxcbiAgICAgIHJlbmFtZTogJ3BkZi53b3JrZXIubWluLmpzJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnbmV0bGlmeS50b21sJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnY29uZmlnLmpzb24nLFxuICAgICAgZGVzdDogJycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbWFuaWZlc3QuanNvbicsXG4gICAgICBkZXN0OiAnJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ3B1YmxpYy9yZXMvYW5kcm9pZCcsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbG9jYWxlcycsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgXSxcbn07XG5cbmZ1bmN0aW9uIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20od2FzbUZpbGVQYXRoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLW1hdHJpeC1zZGstY3J5cHRvLXdhc20nLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSB3YXNtRmlsZVBhdGgpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSBwYXRoLmpvaW4ocGF0aC5yZXNvbHZlKCksIFwiL25vZGVfbW9kdWxlcy9AbWF0cml4LW9yZy9tYXRyaXgtc2RrLWNyeXB0by13YXNtL3BrZy9tYXRyaXhfc2RrX2NyeXB0b193YXNtX2JnLndhc21cIik7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vd2FzbScpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2VydmVHaWZXb3JrZXIoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLWdpZi13b3JrZXInLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSAnL2dpZi53b3JrZXIuanMnKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcGF0aC5qb2luKHBhdGgucmVzb2x2ZSgpLCAnL25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyk7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vamF2YXNjcmlwdCcpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgYXBwVHlwZTogJ3NwYScsXG4gIHB1YmxpY0RpcjogZmFsc2UsXG4gIGJhc2U6IGJ1aWxkQ29uZmlnLmJhc2UsXG4gIHNlcnZlcjoge1xuICAgIHBvcnQ6IDgwODAsXG4gICAgaG9zdDogJzAuMC4wLjAnLFxuICAgIGZzOiB7XG4gICAgICAvLyBBbGxvdyBzZXJ2aW5nIGZpbGVzIGZyb20gb25lIGxldmVsIHVwIHRvIHRoZSBwcm9qZWN0IHJvb3RcbiAgICAgIGFsbG93OiBbJy4uJ10sXG4gICAgfSxcbiAgfSxcbiAgcGx1Z2luczogW1xuICAgIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20oJy9ub2RlX21vZHVsZXMvLnZpdGUvZGVwcy9wa2cvbWF0cml4X3Nka19jcnlwdG9fd2FzbV9iZy53YXNtJyksXG4gICAgc2VydmVHaWZXb3JrZXIoKSxcbiAgICB0b3BMZXZlbEF3YWl0KHtcbiAgICAgIC8vIFRoZSBleHBvcnQgbmFtZSBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBmb3IgZWFjaCBjaHVuayBtb2R1bGVcbiAgICAgIHByb21pc2VFeHBvcnROYW1lOiAnX190bGEnLFxuICAgICAgLy8gVGhlIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGltcG9ydCBuYW1lcyBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBpbiBlYWNoIGNodW5rIG1vZHVsZVxuICAgICAgcHJvbWlzZUltcG9ydE5hbWU6IChpKSA9PiBgX190bGFfJHtpfWAsXG4gICAgfSksXG4gICAgdml0ZVN0YXRpY0NvcHkoY29weUZpbGVzKSxcbiAgICB2YW5pbGxhRXh0cmFjdFBsdWdpbigpLFxuICAgIHdhc20oKSxcbiAgICByZWFjdCgpLFxuICAgIFZpdGVQV0Eoe1xuICAgICAgc3JjRGlyOiAnc3JjJyxcbiAgICAgIGZpbGVuYW1lOiAnc3cudHMnLFxuICAgICAgc3RyYXRlZ2llczogJ2luamVjdE1hbmlmZXN0JyxcbiAgICAgIGluamVjdFJlZ2lzdGVyOiBmYWxzZSxcbiAgICAgIG1hbmlmZXN0OiBmYWxzZSxcbiAgICAgIGluamVjdE1hbmlmZXN0OiB7XG4gICAgICAgIGluamVjdGlvblBvaW50OiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgICAgZGV2T3B0aW9uczoge1xuICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgdHlwZTogJ21vZHVsZSdcbiAgICAgIH1cbiAgICB9KSxcbiAgXSxcbiAgb3B0aW1pemVEZXBzOiB7XG4gICAgZXNidWlsZE9wdGlvbnM6IHtcbiAgICAgIGRlZmluZToge1xuICAgICAgICBnbG9iYWw6ICdnbG9iYWxUaGlzJyxcbiAgICAgIH0sXG4gICAgICBwbHVnaW5zOiBbXG4gICAgICAgIC8vIEVuYWJsZSBlc2J1aWxkIHBvbHlmaWxsIHBsdWdpbnNcbiAgICAgICAgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbih7XG4gICAgICAgICAgcHJvY2VzczogZmFsc2UsXG4gICAgICAgICAgYnVmZmVyOiB0cnVlLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSxcbiAgfSxcbiAgYnVpbGQ6IHtcbiAgICBvdXREaXI6ICdkaXN0JyxcbiAgICBzb3VyY2VtYXA6IHRydWUsXG4gICAgY29weVB1YmxpY0RpcjogZmFsc2UsXG4gICAgcm9sbHVwT3B0aW9uczoge1xuICAgICAgcGx1Z2luczogW2luamVjdCh7IEJ1ZmZlcjogWydidWZmZXInLCAnQnVmZmVyJ10gfSldLFxuICAgIH0sXG4gIH0sXG59KTtcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L2J1aWxkLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9saXRydXYvRGV2ZWxvcG1lbnQvY2lubnktZGVza3RvcC9jaW5ueS9idWlsZC5jb25maWcudHNcIjtleHBvcnQgZGVmYXVsdCB7XG4gIGJhc2U6ICcvJyxcbn07XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXNULFNBQVMsb0JBQW9CO0FBQ25WLE9BQU8sV0FBVztBQUNsQixTQUFTLFlBQVk7QUFDckIsU0FBUyxzQkFBc0I7QUFDL0IsU0FBUyw0QkFBNEI7QUFDckMsU0FBUyxpQ0FBaUM7QUFDMUMsT0FBTyxZQUFZO0FBQ25CLE9BQU8sbUJBQW1CO0FBQzFCLFNBQVMsZUFBZTtBQUN4QixPQUFPLFFBQVE7QUFDZixPQUFPLFVBQVU7OztBQ1Z1UyxJQUFPLHVCQUFRO0FBQUEsRUFDclUsTUFBTTtBQUNSOzs7QURXQSxJQUFNLFlBQVk7QUFBQSxFQUNoQixTQUFT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
diff --git a/vite.config.js.timestamp-1771642553007-3bf56500344a6.mjs b/vite.config.js.timestamp-1771642553007-3bf56500344a6.mjs
new file mode 100644
index 0000000..2e2889a
--- /dev/null
+++ b/vite.config.js.timestamp-1771642553007-3bf56500344a6.mjs
@@ -0,0 +1,165 @@
+// vite.config.js
+import { defineConfig } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite/dist/node/index.js";
+import react from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vitejs/plugin-react/dist/index.mjs";
+import { wasm } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-wasm/dist/es/index.js";
+import { viteStaticCopy } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-static-copy/dist/index.js";
+import { vanillaExtractPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@vanilla-extract/vite-plugin/dist/vanilla-extract-vite-plugin.cjs.js";
+import { NodeGlobalsPolyfillPlugin } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@esbuild-plugins/node-globals-polyfill/dist/index.js";
+import inject from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/@rollup/plugin-inject/dist/es/index.js";
+import topLevelAwait from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-top-level-await/exports/import.mjs";
+import { VitePWA } from "file:///home/litruv/Development/cinny-desktop/cinny/node_modules/vite-plugin-pwa/dist/index.js";
+import fs from "fs";
+import path from "path";
+
+// build.config.ts
+var build_config_default = {
+ base: "/"
+};
+
+// vite.config.js
+var copyFiles = {
+ targets: [
+ {
+ src: "node_modules/pdfjs-dist/build/pdf.worker.min.mjs",
+ dest: "",
+ rename: "pdf.worker.min.js"
+ },
+ {
+ src: "node_modules/gif.js/dist/gif.worker.js",
+ dest: ""
+ },
+ {
+ src: "netlify.toml",
+ dest: ""
+ },
+ {
+ src: "config.json",
+ dest: ""
+ },
+ {
+ src: "public/manifest.json",
+ dest: ""
+ },
+ {
+ src: "public/res/android",
+ dest: "public/"
+ },
+ {
+ src: "public/locales",
+ dest: "public/"
+ }
+ ]
+};
+function serverMatrixSdkCryptoWasm(wasmFilePath) {
+ return {
+ name: "vite-plugin-serve-matrix-sdk-crypto-wasm",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === wasmFilePath) {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/@matrix-org/matrix-sdk-crypto-wasm/pkg/matrix_sdk_crypto_wasm_bg.wasm");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/wasm");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+function serveGifWorker() {
+ return {
+ name: "vite-plugin-serve-gif-worker",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ if (req.url === "/gif.worker.js") {
+ const resolvedPath = path.join(path.resolve(), "/node_modules/gif.js/dist/gif.worker.js");
+ if (fs.existsSync(resolvedPath)) {
+ res.setHeader("Content-Type", "application/javascript");
+ res.setHeader("Cache-Control", "no-cache");
+ const fileStream = fs.createReadStream(resolvedPath);
+ fileStream.pipe(res);
+ } else {
+ res.writeHead(404);
+ res.end("File not found");
+ }
+ } else {
+ next();
+ }
+ });
+ }
+ };
+}
+var vite_config_default = defineConfig({
+ appType: "spa",
+ publicDir: false,
+ base: build_config_default.base,
+ server: {
+ port: 8080,
+ host: "0.0.0.0",
+ fs: {
+ // Allow serving files from one level up to the project root
+ allow: [".."]
+ }
+ },
+ plugins: [
+ serverMatrixSdkCryptoWasm("/node_modules/.vite/deps/pkg/matrix_sdk_crypto_wasm_bg.wasm"),
+ serveGifWorker(),
+ topLevelAwait({
+ // The export name of top-level await promise for each chunk module
+ promiseExportName: "__tla",
+ // The function to generate import names of top-level await promise in each chunk module
+ promiseImportName: (i) => `__tla_${i}`
+ }),
+ viteStaticCopy(copyFiles),
+ vanillaExtractPlugin(),
+ wasm(),
+ react(),
+ VitePWA({
+ srcDir: "src",
+ filename: "sw.ts",
+ strategies: "injectManifest",
+ injectRegister: false,
+ manifest: false,
+ injectManifest: {
+ injectionPoint: void 0
+ },
+ devOptions: {
+ enabled: false,
+ type: "module"
+ }
+ })
+ ],
+ optimizeDeps: {
+ esbuildOptions: {
+ define: {
+ global: "globalThis"
+ },
+ plugins: [
+ // Enable esbuild polyfill plugins
+ NodeGlobalsPolyfillPlugin({
+ process: false,
+ buffer: true
+ })
+ ]
+ }
+ },
+ build: {
+ outDir: "dist",
+ sourcemap: true,
+ copyPublicDir: false,
+ rollupOptions: {
+ plugins: [inject({ Buffer: ["buffer", "Buffer"] })]
+ }
+ }
+});
+export {
+ vite_config_default as default
+};
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAiYnVpbGQuY29uZmlnLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L3ZpdGUuY29uZmlnLmpzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSc7XG5pbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3QnO1xuaW1wb3J0IHsgd2FzbSB9IGZyb20gJ0Byb2xsdXAvcGx1Z2luLXdhc20nO1xuaW1wb3J0IHsgdml0ZVN0YXRpY0NvcHkgfSBmcm9tICd2aXRlLXBsdWdpbi1zdGF0aWMtY29weSc7XG5pbXBvcnQgeyB2YW5pbGxhRXh0cmFjdFBsdWdpbiB9IGZyb20gJ0B2YW5pbGxhLWV4dHJhY3Qvdml0ZS1wbHVnaW4nO1xuaW1wb3J0IHsgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbiB9IGZyb20gJ0Blc2J1aWxkLXBsdWdpbnMvbm9kZS1nbG9iYWxzLXBvbHlmaWxsJztcbmltcG9ydCBpbmplY3QgZnJvbSAnQHJvbGx1cC9wbHVnaW4taW5qZWN0JztcbmltcG9ydCB0b3BMZXZlbEF3YWl0IGZyb20gJ3ZpdGUtcGx1Z2luLXRvcC1sZXZlbC1hd2FpdCc7XG5pbXBvcnQgeyBWaXRlUFdBIH0gZnJvbSAndml0ZS1wbHVnaW4tcHdhJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBidWlsZENvbmZpZyBmcm9tICcuL2J1aWxkLmNvbmZpZyc7XG5cbmNvbnN0IGNvcHlGaWxlcyA9IHtcbiAgdGFyZ2V0czogW1xuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9wZGZqcy1kaXN0L2J1aWxkL3BkZi53b3JrZXIubWluLm1qcycsXG4gICAgICBkZXN0OiAnJyxcbiAgICAgIHJlbmFtZTogJ3BkZi53b3JrZXIubWluLmpzJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnbmV0bGlmeS50b21sJyxcbiAgICAgIGRlc3Q6ICcnLFxuICAgIH0sXG4gICAge1xuICAgICAgc3JjOiAnY29uZmlnLmpzb24nLFxuICAgICAgZGVzdDogJycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbWFuaWZlc3QuanNvbicsXG4gICAgICBkZXN0OiAnJyxcbiAgICB9LFxuICAgIHtcbiAgICAgIHNyYzogJ3B1YmxpYy9yZXMvYW5kcm9pZCcsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgICB7XG4gICAgICBzcmM6ICdwdWJsaWMvbG9jYWxlcycsXG4gICAgICBkZXN0OiAncHVibGljLycsXG4gICAgfSxcbiAgXSxcbn07XG5cbmZ1bmN0aW9uIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20od2FzbUZpbGVQYXRoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLW1hdHJpeC1zZGstY3J5cHRvLXdhc20nLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSB3YXNtRmlsZVBhdGgpIHtcbiAgICAgICAgICBjb25zdCByZXNvbHZlZFBhdGggPSBwYXRoLmpvaW4ocGF0aC5yZXNvbHZlKCksIFwiL25vZGVfbW9kdWxlcy9AbWF0cml4LW9yZy9tYXRyaXgtc2RrLWNyeXB0by13YXNtL3BrZy9tYXRyaXhfc2RrX2NyeXB0b193YXNtX2JnLndhc21cIik7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vd2FzbScpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2VydmVHaWZXb3JrZXIoKSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogJ3ZpdGUtcGx1Z2luLXNlcnZlLWdpZi13b3JrZXInLFxuICAgIGNvbmZpZ3VyZVNlcnZlcihzZXJ2ZXIpIHtcbiAgICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgIGlmIChyZXEudXJsID09PSAnL2dpZi53b3JrZXIuanMnKSB7XG4gICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcGF0aC5qb2luKHBhdGgucmVzb2x2ZSgpLCAnL25vZGVfbW9kdWxlcy9naWYuanMvZGlzdC9naWYud29ya2VyLmpzJyk7XG5cbiAgICAgICAgICBpZiAoZnMuZXhpc3RzU3luYyhyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdDb250ZW50LVR5cGUnLCAnYXBwbGljYXRpb24vamF2YXNjcmlwdCcpO1xuICAgICAgICAgICAgcmVzLnNldEhlYWRlcignQ2FjaGUtQ29udHJvbCcsICduby1jYWNoZScpO1xuXG4gICAgICAgICAgICBjb25zdCBmaWxlU3RyZWFtID0gZnMuY3JlYXRlUmVhZFN0cmVhbShyZXNvbHZlZFBhdGgpO1xuICAgICAgICAgICAgZmlsZVN0cmVhbS5waXBlKHJlcyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcy53cml0ZUhlYWQoNDA0KTtcbiAgICAgICAgICAgIHJlcy5lbmQoJ0ZpbGUgbm90IGZvdW5kJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgYXBwVHlwZTogJ3NwYScsXG4gIHB1YmxpY0RpcjogZmFsc2UsXG4gIGJhc2U6IGJ1aWxkQ29uZmlnLmJhc2UsXG4gIHNlcnZlcjoge1xuICAgIHBvcnQ6IDgwODAsXG4gICAgaG9zdDogJzAuMC4wLjAnLFxuICAgIGZzOiB7XG4gICAgICAvLyBBbGxvdyBzZXJ2aW5nIGZpbGVzIGZyb20gb25lIGxldmVsIHVwIHRvIHRoZSBwcm9qZWN0IHJvb3RcbiAgICAgIGFsbG93OiBbJy4uJ10sXG4gICAgfSxcbiAgfSxcbiAgcGx1Z2luczogW1xuICAgIHNlcnZlck1hdHJpeFNka0NyeXB0b1dhc20oJy9ub2RlX21vZHVsZXMvLnZpdGUvZGVwcy9wa2cvbWF0cml4X3Nka19jcnlwdG9fd2FzbV9iZy53YXNtJyksXG4gICAgc2VydmVHaWZXb3JrZXIoKSxcbiAgICB0b3BMZXZlbEF3YWl0KHtcbiAgICAgIC8vIFRoZSBleHBvcnQgbmFtZSBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBmb3IgZWFjaCBjaHVuayBtb2R1bGVcbiAgICAgIHByb21pc2VFeHBvcnROYW1lOiAnX190bGEnLFxuICAgICAgLy8gVGhlIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGltcG9ydCBuYW1lcyBvZiB0b3AtbGV2ZWwgYXdhaXQgcHJvbWlzZSBpbiBlYWNoIGNodW5rIG1vZHVsZVxuICAgICAgcHJvbWlzZUltcG9ydE5hbWU6IChpKSA9PiBgX190bGFfJHtpfWAsXG4gICAgfSksXG4gICAgdml0ZVN0YXRpY0NvcHkoY29weUZpbGVzKSxcbiAgICB2YW5pbGxhRXh0cmFjdFBsdWdpbigpLFxuICAgIHdhc20oKSxcbiAgICByZWFjdCgpLFxuICAgIFZpdGVQV0Eoe1xuICAgICAgc3JjRGlyOiAnc3JjJyxcbiAgICAgIGZpbGVuYW1lOiAnc3cudHMnLFxuICAgICAgc3RyYXRlZ2llczogJ2luamVjdE1hbmlmZXN0JyxcbiAgICAgIGluamVjdFJlZ2lzdGVyOiBmYWxzZSxcbiAgICAgIG1hbmlmZXN0OiBmYWxzZSxcbiAgICAgIGluamVjdE1hbmlmZXN0OiB7XG4gICAgICAgIGluamVjdGlvblBvaW50OiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgICAgZGV2T3B0aW9uczoge1xuICAgICAgICBlbmFibGVkOiBmYWxzZSxcbiAgICAgICAgdHlwZTogJ21vZHVsZSdcbiAgICAgIH1cbiAgICB9KSxcbiAgXSxcbiAgb3B0aW1pemVEZXBzOiB7XG4gICAgZXNidWlsZE9wdGlvbnM6IHtcbiAgICAgIGRlZmluZToge1xuICAgICAgICBnbG9iYWw6ICdnbG9iYWxUaGlzJyxcbiAgICAgIH0sXG4gICAgICBwbHVnaW5zOiBbXG4gICAgICAgIC8vIEVuYWJsZSBlc2J1aWxkIHBvbHlmaWxsIHBsdWdpbnNcbiAgICAgICAgTm9kZUdsb2JhbHNQb2x5ZmlsbFBsdWdpbih7XG4gICAgICAgICAgcHJvY2VzczogZmFsc2UsXG4gICAgICAgICAgYnVmZmVyOiB0cnVlLFxuICAgICAgICB9KSxcbiAgICAgIF0sXG4gICAgfSxcbiAgfSxcbiAgYnVpbGQ6IHtcbiAgICBvdXREaXI6ICdkaXN0JyxcbiAgICBzb3VyY2VtYXA6IHRydWUsXG4gICAgY29weVB1YmxpY0RpcjogZmFsc2UsXG4gICAgcm9sbHVwT3B0aW9uczoge1xuICAgICAgcGx1Z2luczogW2luamVjdCh7IEJ1ZmZlcjogWydidWZmZXInLCAnQnVmZmVyJ10gfSldLFxuICAgIH0sXG4gIH0sXG59KTtcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL2hvbWUvbGl0cnV2L0RldmVsb3BtZW50L2Npbm55LWRlc2t0b3AvY2lubnlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIi9ob21lL2xpdHJ1di9EZXZlbG9wbWVudC9jaW5ueS1kZXNrdG9wL2Npbm55L2J1aWxkLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vaG9tZS9saXRydXYvRGV2ZWxvcG1lbnQvY2lubnktZGVza3RvcC9jaW5ueS9idWlsZC5jb25maWcudHNcIjtleHBvcnQgZGVmYXVsdCB7XG4gIGJhc2U6ICcvJyxcbn07XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXNULFNBQVMsb0JBQW9CO0FBQ25WLE9BQU8sV0FBVztBQUNsQixTQUFTLFlBQVk7QUFDckIsU0FBUyxzQkFBc0I7QUFDL0IsU0FBUyw0QkFBNEI7QUFDckMsU0FBUyxpQ0FBaUM7QUFDMUMsT0FBTyxZQUFZO0FBQ25CLE9BQU8sbUJBQW1CO0FBQzFCLFNBQVMsZUFBZTtBQUN4QixPQUFPLFFBQVE7QUFDZixPQUFPLFVBQVU7OztBQ1Z1UyxJQUFPLHVCQUFRO0FBQUEsRUFDclUsTUFBTTtBQUNSOzs7QURXQSxJQUFNLFlBQVk7QUFBQSxFQUNoQixTQUFT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