Resruiin
This commit is contained in:
12
src/app.html
12
src/app.html
@@ -1,13 +1,14 @@
|
||||
<!doctype html>
|
||||
|
||||
<html lang="%paraglide.lang%">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
|
||||
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
@@ -22,4 +23,5 @@
|
||||
<body data-sveltekit-preload-data="tap">
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
@@ -2,6 +2,9 @@
|
||||
import { Button, Input } from "$lib/components/ui";
|
||||
import { createRoom } from "$lib/matrix";
|
||||
import { toasts } from "$lib/stores/ui";
|
||||
import { createLogger, getErrorMessage } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger('matrix:room');
|
||||
import { syncRoomsFromEvent, selectRoom } from "$lib/stores/matrix";
|
||||
|
||||
interface Props {
|
||||
@@ -35,9 +38,9 @@
|
||||
roomName = "";
|
||||
isDirect = false;
|
||||
onClose();
|
||||
} catch (e: any) {
|
||||
console.error("Failed to create room:", e);
|
||||
toasts.error(e.message || "Failed to create room");
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to create room', { error: e });
|
||||
toasts.error(getErrorMessage(e, 'Failed to create room'));
|
||||
} finally {
|
||||
isCreating = false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
import { Button, Input } from "$lib/components/ui";
|
||||
import { createSpace, getSpaces } from "$lib/matrix";
|
||||
import { toasts } from "$lib/stores/ui";
|
||||
import { createLogger, getErrorMessage } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger('matrix:space');
|
||||
import { syncRoomsFromEvent } from "$lib/stores/matrix";
|
||||
|
||||
interface Props {
|
||||
@@ -45,9 +48,9 @@
|
||||
spaceTopic = "";
|
||||
isPublic = false;
|
||||
onClose();
|
||||
} catch (e: any) {
|
||||
console.error("Failed to create space:", e);
|
||||
toasts.error(e.message || "Failed to create space");
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to create space', { error: e });
|
||||
toasts.error(getErrorMessage(e, 'Failed to create space'));
|
||||
} finally {
|
||||
isCreating = false;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
import EmojiPicker from "$lib/components/ui/EmojiPicker.svelte";
|
||||
import { convertEmojiShortcodes } from "$lib/utils/emojiData";
|
||||
import { getTwemojiUrl } from "$lib/utils/twemoji";
|
||||
import { createLogger, getErrorMessage } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger('matrix:input');
|
||||
|
||||
// Emoji detection regex
|
||||
const emojiRegex =
|
||||
@@ -134,11 +137,11 @@
|
||||
}
|
||||
|
||||
// Send typing indicator
|
||||
setTyping(roomId, true).catch(console.error);
|
||||
setTyping(roomId, true).catch((e) => log.error('Failed to send typing', { error: e }));
|
||||
|
||||
// Stop typing after 3 seconds of no input
|
||||
typingTimeout = setTimeout(() => {
|
||||
setTyping(roomId, false).catch(console.error);
|
||||
setTyping(roomId, false).catch((e) => log.error('Failed to stop typing', { error: e }));
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
@@ -416,7 +419,7 @@
|
||||
clearTimeout(typingTimeout);
|
||||
typingTimeout = null;
|
||||
}
|
||||
setTyping(roomId, false).catch(console.error);
|
||||
setTyping(roomId, false).catch((e) => log.error('Failed to stop typing', { error: e }));
|
||||
|
||||
// Create a temporary event ID for the pending message
|
||||
const tempEventId = `pending-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
@@ -462,11 +465,11 @@
|
||||
// If no event ID returned, just mark as not pending
|
||||
confirmPendingMessage(roomId, tempEventId, tempEventId);
|
||||
}
|
||||
} catch (e: any) {
|
||||
console.error("Failed to send message:", e);
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to send message', { error: e });
|
||||
// Remove the pending message on failure
|
||||
removePendingMessage(roomId, tempEventId);
|
||||
toasts.error(e.message || "Failed to send message");
|
||||
toasts.error(getErrorMessage(e, 'Failed to send message'));
|
||||
} finally {
|
||||
isSending = false;
|
||||
// Refocus after DOM settles from optimistic update
|
||||
@@ -497,9 +500,9 @@
|
||||
const contentUri = await uploadFile(file);
|
||||
await sendFileMessage(roomId, file, contentUri);
|
||||
toasts.success("File sent!");
|
||||
} catch (e: any) {
|
||||
console.error("Failed to upload file:", e);
|
||||
toasts.error(e.message || "Failed to upload file");
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to upload file', { error: e });
|
||||
toasts.error(getErrorMessage(e, 'Failed to upload file'));
|
||||
} finally {
|
||||
isUploading = false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
import { Avatar } from "$lib/components/ui";
|
||||
import { setRoomName, setRoomTopic, setRoomAvatar } from "$lib/matrix";
|
||||
import { toasts } from "$lib/stores/ui";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger('matrix:settings');
|
||||
import { syncRoomsFromEvent } from "$lib/stores/matrix";
|
||||
import type { RoomSummary } from "$lib/matrix/types";
|
||||
|
||||
@@ -55,7 +58,7 @@
|
||||
toasts.success("Room settings updated");
|
||||
onClose();
|
||||
} catch (e) {
|
||||
console.error("Failed to update room settings:", e);
|
||||
log.error('Failed to update room settings', { error: e });
|
||||
toasts.error("Failed to update room settings");
|
||||
} finally {
|
||||
isSaving = false;
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
import { Avatar } from '$lib/components/ui';
|
||||
import { searchUsers, createDirectMessage } from '$lib/matrix';
|
||||
import { toasts } from '$lib/stores/ui';
|
||||
import { createLogger, getErrorMessage } from '$lib/utils/logger';
|
||||
|
||||
const log = createLogger('matrix:dm');
|
||||
|
||||
interface Props {
|
||||
onClose: () => void;
|
||||
@@ -29,7 +32,7 @@
|
||||
try {
|
||||
searchResults = await searchUsers(searchQuery);
|
||||
} catch (e) {
|
||||
console.error('Search failed:', e);
|
||||
log.error('Search failed', { error: e });
|
||||
} finally {
|
||||
isSearching = false;
|
||||
}
|
||||
@@ -43,9 +46,9 @@
|
||||
toasts.success('Direct message started!');
|
||||
onDMCreated(roomId);
|
||||
onClose();
|
||||
} catch (e: any) {
|
||||
console.error('Failed to create DM:', e);
|
||||
toasts.error(e.message || 'Failed to start direct message');
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to create DM', { error: e });
|
||||
toasts.error(getErrorMessage(e, 'Failed to start direct message'));
|
||||
} finally {
|
||||
isCreating = false;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { syncState, syncError, clearState } from "$lib/stores/matrix";
|
||||
import { clearAllCache } from "$lib/cache";
|
||||
import { createLogger } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger('matrix:sync');
|
||||
|
||||
interface Props {
|
||||
onHardRefresh?: () => void;
|
||||
@@ -43,7 +46,7 @@
|
||||
// Reload the page for clean state
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
console.error("[SyncRecovery] Hard refresh failed:", error);
|
||||
log.error('Hard refresh failed', { error });
|
||||
isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
import { createDirectMessage } from '$lib/matrix';
|
||||
import { userPresence } from '$lib/stores/matrix';
|
||||
import { toasts } from '$lib/stores/ui';
|
||||
import { createLogger } from '$lib/utils/logger';
|
||||
|
||||
const log = createLogger('matrix:profile');
|
||||
import type { RoomMember } from '$lib/matrix/types';
|
||||
|
||||
interface Props {
|
||||
@@ -35,7 +38,7 @@
|
||||
onStartDM?.(roomId);
|
||||
onClose();
|
||||
} catch (e) {
|
||||
console.error('Failed to start DM:', e);
|
||||
log.error('Failed to start DM', { error: e });
|
||||
toasts.error('Failed to start direct message');
|
||||
} finally {
|
||||
isStartingDM = false;
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
{#if showAddItemModal}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div class="fixed inset-0 z-[60] bg-black/60 flex items-center justify-center p-4" onclick={() => (showAddItemModal = false)} onkeydown={(e) => e.key === 'Escape' && (showAddItemModal = false)}>
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
|
||||
<div class="bg-surface rounded-2xl border border-light/10 p-5 w-full max-w-md space-y-4" onclick={(e) => e.stopPropagation()}>
|
||||
<h3 class="text-body font-heading text-white">{editingItem ? 'Edit' : 'Add'} Budget Item</h3>
|
||||
|
||||
@@ -384,7 +384,7 @@
|
||||
{#if showAddCategoryModal}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div class="fixed inset-0 z-[60] bg-black/60 flex items-center justify-center p-4" onclick={() => (showAddCategoryModal = false)} onkeydown={(e) => e.key === 'Escape' && (showAddCategoryModal = false)}>
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
|
||||
<div class="bg-surface rounded-2xl border border-light/10 p-5 w-full max-w-sm space-y-4" onclick={(e) => e.stopPropagation()}>
|
||||
<h3 class="text-body font-heading text-white">Add Category</h3>
|
||||
|
||||
@@ -399,10 +399,11 @@
|
||||
<div class="flex gap-1.5">
|
||||
{#each CATEGORY_COLORS as color}
|
||||
<button
|
||||
class="w-6 h-6 rounded-full border-2 transition-all {newCategoryColor === color ? 'border-white scale-110' : 'border-transparent'}"
|
||||
style="background-color: {color}"
|
||||
onclick={() => (newCategoryColor = color)}
|
||||
></button>
|
||||
class="w-6 h-6 rounded-full border-2 transition-all {newCategoryColor === color ? 'border-white scale-110' : 'border-transparent'}"
|
||||
style="background-color: {color}"
|
||||
onclick={() => (newCategoryColor = color)}
|
||||
aria-label="Select color {color}"
|
||||
></button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -422,7 +422,7 @@
|
||||
{#if showAddSponsorModal}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div class="fixed inset-0 z-[60] bg-black/60 flex items-center justify-center p-4" onclick={() => (showAddSponsorModal = false)} onkeydown={(e) => e.key === 'Escape' && (showAddSponsorModal = false)}>
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
|
||||
<div class="bg-surface rounded-2xl border border-light/10 p-5 w-full max-w-md space-y-4 max-h-[80vh] overflow-auto" onclick={(e) => e.stopPropagation()}>
|
||||
<h3 class="text-body font-heading text-white">{editingSponsor ? 'Edit' : 'Add'} Sponsor</h3>
|
||||
|
||||
@@ -508,7 +508,7 @@
|
||||
{#if showAddTierModal}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div class="fixed inset-0 z-[60] bg-black/60 flex items-center justify-center p-4" onclick={() => (showAddTierModal = false)} onkeydown={(e) => e.key === 'Escape' && (showAddTierModal = false)}>
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events -->
|
||||
<div class="bg-surface rounded-2xl border border-light/10 p-5 w-full max-w-sm space-y-4" onclick={(e) => e.stopPropagation()}>
|
||||
<h3 class="text-body font-heading text-white">Manage Tiers</h3>
|
||||
|
||||
@@ -528,10 +528,11 @@
|
||||
<div class="flex gap-1.5">
|
||||
{#each TIER_COLORS as color}
|
||||
<button
|
||||
class="w-6 h-6 rounded-full border-2 transition-all {tierColor === color ? 'border-white scale-110' : 'border-transparent'}"
|
||||
style="background-color: {color}"
|
||||
onclick={() => (tierColor = color)}
|
||||
></button>
|
||||
class="w-6 h-6 rounded-full border-2 transition-all {tierColor === color ? 'border-white scale-110' : 'border-transparent'}"
|
||||
style="background-color: {color}"
|
||||
onclick={() => (tierColor = color)}
|
||||
aria-label="Select color {color}"
|
||||
></button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,9 @@ import {
|
||||
type PinnedEventsContent,
|
||||
type RoomAvatarContent,
|
||||
} from './sdk-types';
|
||||
import { createLogger } from '$lib/utils/logger';
|
||||
|
||||
const log = createLogger('matrix:client');
|
||||
|
||||
// Matrix message content types
|
||||
interface MessageContent extends IContent {
|
||||
@@ -81,7 +84,7 @@ export interface LoginWithPasswordParams {
|
||||
*/
|
||||
export async function initMatrixClient(credentials: LoginCredentials): Promise<MatrixClient> {
|
||||
if (client) {
|
||||
console.warn('Matrix client already initialized, stopping existing client');
|
||||
log.warn('Matrix client already initialized, stopping existing client');
|
||||
await stopClient();
|
||||
}
|
||||
|
||||
@@ -103,11 +106,11 @@ export async function initMatrixClient(credentials: LoginCredentials): Promise<M
|
||||
// Check if crypto module is available before trying to init
|
||||
if (typeof client.initRustCrypto === 'function') {
|
||||
await client.initRustCrypto();
|
||||
console.log('E2EE crypto initialized successfully');
|
||||
log.info('E2EE crypto initialized successfully');
|
||||
}
|
||||
} catch (e) {
|
||||
// This is expected in dev mode - WASM loading can be problematic
|
||||
console.info('Crypto not available - encrypted rooms will show encrypted messages');
|
||||
log.info('Crypto not available - encrypted rooms will show encrypted messages');
|
||||
}
|
||||
|
||||
// Start the client (begins sync loop)
|
||||
@@ -204,7 +207,7 @@ export async function logout(): Promise<void> {
|
||||
try {
|
||||
await client.logout();
|
||||
} catch (e) {
|
||||
console.error('Error during logout:', e);
|
||||
log.error('Error during logout', { error: e });
|
||||
}
|
||||
await stopClient();
|
||||
}
|
||||
@@ -551,7 +554,7 @@ export async function setRoomNotificationLevel(roomId: string, level: Notificati
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to set notification level:', e);
|
||||
log.error('Failed to set notification level', { error: e });
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -628,7 +631,7 @@ export async function loadMoreMessages(roomId: string, limit = 50): Promise<{ ha
|
||||
|
||||
return { hasMore, loaded };
|
||||
} catch (e) {
|
||||
console.error('Failed to load more messages:', e);
|
||||
log.error('Failed to load more messages', { error: e });
|
||||
return { hasMore: false, loaded: 0 };
|
||||
}
|
||||
}
|
||||
@@ -697,7 +700,7 @@ export async function sendFileMessage(
|
||||
content.info.w = dimensions.width;
|
||||
content.info.h = dimensions.height;
|
||||
} catch (e) {
|
||||
console.warn('Failed to get image dimensions:', e);
|
||||
log.warn('Failed to get image dimensions', { error: e });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -782,7 +785,7 @@ export async function getAuthenticatedMediaUrl(mxcUrl: string): Promise<string |
|
||||
|
||||
return blobUrl;
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch authenticated media:', e);
|
||||
log.error('Failed to fetch authenticated media', { error: e });
|
||||
// Fallback to unauthenticated URL
|
||||
return client.mxcUrlToHttp(mxcUrl);
|
||||
}
|
||||
@@ -834,7 +837,7 @@ export async function getAuthenticatedThumbnailUrl(
|
||||
|
||||
return blobUrl;
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch authenticated thumbnail:', e);
|
||||
log.error('Failed to fetch authenticated thumbnail', { error: e });
|
||||
return client.mxcUrlToHttp(mxcUrl, width, height, 'scale');
|
||||
}
|
||||
}
|
||||
@@ -936,7 +939,7 @@ export async function searchUsers(query: string, limit = 10): Promise<Array<{
|
||||
avatarUrl: user.avatar_url ? client!.mxcUrlToHttp(user.avatar_url, 40, 40, 'crop') : null,
|
||||
}));
|
||||
} catch (e) {
|
||||
console.error('User search failed:', e);
|
||||
log.error('User search failed', { error: e });
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -1080,7 +1083,7 @@ export async function setPresence(presence: 'online' | 'offline' | 'unavailable'
|
||||
try {
|
||||
await client.setPresence({ presence, status_msg: statusMsg });
|
||||
} catch (e) {
|
||||
console.error('Failed to set presence:', e);
|
||||
log.error('Failed to set presence', { error: e });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ function loadTheme(): ThemeState {
|
||||
return { ...defaultTheme, ...JSON.parse(stored) };
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Failed to load theme:', e);
|
||||
// Theme load failure is non-critical, fall through to default
|
||||
}
|
||||
return defaultTheme;
|
||||
}
|
||||
|
||||
@@ -195,6 +195,19 @@ export function clearRecentLogs() {
|
||||
* Format recent logs as a copyable string for bug reports.
|
||||
* User can paste this to you for debugging.
|
||||
*/
|
||||
/**
|
||||
* Safely extract an error message from an unknown caught value.
|
||||
* Use in catch blocks: `catch (e: unknown) { toasts.error(getErrorMessage(e, 'fallback')) }`
|
||||
*/
|
||||
export function getErrorMessage(e: unknown, fallback = 'An unexpected error occurred'): string {
|
||||
if (e instanceof Error) return e.message;
|
||||
if (typeof e === 'string') return e;
|
||||
if (e && typeof e === 'object' && 'message' in e && typeof (e as { message: unknown }).message === 'string') {
|
||||
return (e as { message: string }).message;
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
export function dumpLogs(): string {
|
||||
return recentLogs
|
||||
.map((e) => {
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
import { clearBlobUrlCache } from "$lib/cache/mediaCache";
|
||||
import type { Message } from "$lib/matrix/types";
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import { createLogger, getErrorMessage } from "$lib/utils/logger";
|
||||
|
||||
const log = createLogger('chat:page');
|
||||
|
||||
const supabase = getContext<SupabaseClient>("supabase");
|
||||
let data = $derived(page.data);
|
||||
@@ -120,7 +123,7 @@
|
||||
await initCache();
|
||||
await cleanupCache(7 * 24 * 60 * 60 * 1000);
|
||||
} catch (e) {
|
||||
console.warn("Cache initialization failed:", e);
|
||||
log.warn('Cache initialization failed', { error: e });
|
||||
}
|
||||
|
||||
// Try to load credentials from Supabase
|
||||
@@ -141,7 +144,7 @@
|
||||
isInitializing = false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Failed to load Matrix credentials:", e);
|
||||
log.error('Failed to load Matrix credentials', { error: e });
|
||||
showJoinScreen = true;
|
||||
isInitializing = false;
|
||||
}
|
||||
@@ -164,7 +167,7 @@
|
||||
// Check if org has a Matrix Space, auto-create if not
|
||||
await ensureOrgSpace(credentials);
|
||||
} catch (e: unknown) {
|
||||
console.error("Failed to init Matrix client:", e);
|
||||
log.error('Failed to init Matrix client', { error: e });
|
||||
toasts.error(m.chat_join_error());
|
||||
showJoinScreen = true;
|
||||
} finally {
|
||||
@@ -196,7 +199,7 @@
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("Failed to ensure org space:", e);
|
||||
log.warn('Failed to ensure org space', { error: e });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,8 +226,8 @@
|
||||
if (result.provisioned) {
|
||||
toasts.success(m.chat_join_success());
|
||||
}
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || m.chat_join_error());
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, m.chat_join_error()));
|
||||
} finally {
|
||||
isProvisioning = false;
|
||||
}
|
||||
@@ -297,8 +300,8 @@
|
||||
await editMessage($selectedRoomId, editingMsg.eventId, newContent);
|
||||
editingMsg = null;
|
||||
toasts.success("Message edited");
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to edit message");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to edit message'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,8 +315,8 @@
|
||||
try {
|
||||
await deleteMessage($selectedRoomId, messageId);
|
||||
toasts.success("Message deleted");
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to delete message");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to delete message'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,8 +358,8 @@
|
||||
const contentUri = await uploadFile(file);
|
||||
await sendFileMessage($selectedRoomId, file, contentUri);
|
||||
toasts.success("File sent!");
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to upload file");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to upload file'));
|
||||
} finally {
|
||||
isUploadingDrop = false;
|
||||
}
|
||||
@@ -369,8 +372,8 @@
|
||||
const result = await loadMoreMessages($selectedRoomId);
|
||||
loadRoomMessages($selectedRoomId);
|
||||
if (!result.hasMore) toasts.info("No more messages to load");
|
||||
} catch (e: any) {
|
||||
console.error("Failed to load more messages:", e);
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to load more messages', { error: e });
|
||||
} finally {
|
||||
isLoadingMore = false;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ export const load: PageServerLoad = async ({ params, locals, url }) => {
|
||||
try {
|
||||
const events = await fetchEvents(locals.supabase, org.id, statusFilter);
|
||||
return { events, statusFilter };
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to load events', { error: e, data: { orgId: org.id } });
|
||||
return { events: [], statusFilter };
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import type { Database } from "$lib/supabase/types";
|
||||
import { toasts } from "$lib/stores/ui";
|
||||
import { getErrorMessage } from "$lib/utils/logger";
|
||||
import * as m from "$lib/paraglide/messages";
|
||||
|
||||
interface EventItem {
|
||||
@@ -100,8 +101,8 @@
|
||||
showCreateModal = false;
|
||||
resetForm();
|
||||
goto(`/${data.org.slug}/events/${created.slug}`);
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to create event");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to create event'));
|
||||
} finally {
|
||||
creating = false;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ export const load: LayoutServerLoad = async ({ params, locals, parent }) => {
|
||||
]);
|
||||
|
||||
return { event, eventMembers: members, eventRoles: roles, eventDepartments: departments };
|
||||
} catch (e: any) {
|
||||
if (e?.status === 404) throw e;
|
||||
} catch (e: unknown) {
|
||||
if (e && typeof e === 'object' && 'status' in e && (e as { status: number }).status === 404) throw e;
|
||||
log.error('Failed to load event', { error: e, data: { orgId, eventSlug: params.eventSlug } });
|
||||
error(500, 'Failed to load event');
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import type { Database } from "$lib/supabase/types";
|
||||
import { toasts } from "$lib/stores/ui";
|
||||
import { getErrorMessage } from "$lib/utils/logger";
|
||||
import type { Event, EventMemberWithDetails, EventRole, EventDepartment } from "$lib/api/events";
|
||||
import * as m from "$lib/paraglide/messages";
|
||||
|
||||
@@ -173,8 +174,8 @@
|
||||
goto(`/${data.org.slug}/events/${data.event.slug}`, {
|
||||
invalidateAll: true,
|
||||
});
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to update event");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to update event'));
|
||||
} finally {
|
||||
saving = false;
|
||||
}
|
||||
@@ -192,8 +193,8 @@
|
||||
|
||||
toasts.success(m.events_deleted());
|
||||
goto(`/${data.org.slug}/events`);
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to delete event");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to delete event'));
|
||||
} finally {
|
||||
deleting = false;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ export const load: PageServerLoad = async ({ params, locals, parent }) => {
|
||||
sponsors,
|
||||
sponsorDeliverables,
|
||||
};
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to load department dashboard', { error: e, data: { deptId: params.deptId } });
|
||||
error(500, 'Failed to load department dashboard');
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import type { Database } from "$lib/supabase/types";
|
||||
import { toasts } from "$lib/stores/ui";
|
||||
import { getErrorMessage } from "$lib/utils/logger";
|
||||
import type {
|
||||
Event,
|
||||
EventMemberWithDetails,
|
||||
@@ -260,8 +261,8 @@
|
||||
selectedRoleId = "";
|
||||
selectedDeptIds = [];
|
||||
addNotes = "";
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to add member");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to add member'));
|
||||
} finally {
|
||||
adding = false;
|
||||
}
|
||||
@@ -327,8 +328,8 @@
|
||||
|
||||
toasts.success(m.team_updated());
|
||||
editingMember = null;
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to update member");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to update member'));
|
||||
} finally {
|
||||
updatingMember = false;
|
||||
}
|
||||
@@ -349,8 +350,8 @@
|
||||
teamMembers = teamMembers.filter((tm) => tm.id !== memberToRemove!.id);
|
||||
toasts.success(m.team_removed({ name }));
|
||||
memberToRemove = null;
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to remove member");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to remove member'));
|
||||
} finally {
|
||||
removing = false;
|
||||
}
|
||||
@@ -398,8 +399,8 @@
|
||||
toasts.success(m.team_dept_created());
|
||||
}
|
||||
showDeptModal = false;
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to save department");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to save department'));
|
||||
} finally {
|
||||
savingDept = false;
|
||||
}
|
||||
@@ -419,8 +420,8 @@
|
||||
departments: tm.departments.filter((d) => d.id !== dept.id),
|
||||
}));
|
||||
toasts.success(m.team_dept_deleted());
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to delete department");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to delete department'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,8 +465,8 @@
|
||||
toasts.success(m.team_role_created());
|
||||
}
|
||||
showRoleModal = false;
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to save role");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to save role'));
|
||||
} finally {
|
||||
savingRole = false;
|
||||
}
|
||||
@@ -486,8 +487,8 @@
|
||||
: tm,
|
||||
);
|
||||
toasts.success(m.team_role_deleted());
|
||||
} catch (e: any) {
|
||||
toasts.error(e.message || "Failed to delete role");
|
||||
} catch (e: unknown) {
|
||||
toasts.error(getErrorMessage(e, 'Failed to delete role'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -621,8 +621,9 @@
|
||||
<Input label="Name" name="name" bind:value={editEventModal.name} />
|
||||
<Input label="Slug" name="slug" bind:value={editEventModal.slug} />
|
||||
<div>
|
||||
<label class="block text-body-sm text-light/60 mb-1">Status</label>
|
||||
<label for="event-status" class="block text-body-sm text-light/60 mb-1">Status</label>
|
||||
<select
|
||||
id="event-status"
|
||||
name="status"
|
||||
bind:value={editEventModal.status}
|
||||
class="w-full bg-dark/50 border border-light/10 rounded-xl px-3 py-2 text-body-sm text-white focus:outline-none focus:border-primary/50"
|
||||
@@ -634,8 +635,9 @@
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-body-sm text-light/60 mb-1">Start Date</label>
|
||||
<label for="event-start-date" class="block text-body-sm text-light/60 mb-1">Start Date</label>
|
||||
<input
|
||||
id="event-start-date"
|
||||
type="date"
|
||||
name="start_date"
|
||||
bind:value={editEventModal.start_date}
|
||||
@@ -643,8 +645,9 @@
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-body-sm text-light/60 mb-1">End Date</label>
|
||||
<label for="event-end-date" class="block text-body-sm text-light/60 mb-1">End Date</label>
|
||||
<input
|
||||
id="event-end-date"
|
||||
type="date"
|
||||
name="end_date"
|
||||
bind:value={editEventModal.end_date}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import { env } from '$env/dynamic/private';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { createLogger } from '$lib/utils/logger';
|
||||
|
||||
const log = createLogger('api:matrix-provision');
|
||||
|
||||
/**
|
||||
* POST /api/matrix-provision
|
||||
@@ -83,7 +86,7 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
|
||||
if (!registerRes.ok) {
|
||||
const err = await registerRes.json().catch(() => ({}));
|
||||
console.error('Matrix register failed:', registerRes.status, err);
|
||||
log.error('Matrix register failed', { data: { status: registerRes.status }, error: err });
|
||||
return json({ error: 'Failed to create Matrix account' }, { status: 500 });
|
||||
}
|
||||
|
||||
@@ -104,7 +107,7 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
|
||||
if (!loginRes.ok) {
|
||||
const err = await loginRes.json().catch(() => ({}));
|
||||
console.error('Matrix login failed:', loginRes.status, err);
|
||||
log.error('Matrix login failed', { data: { status: loginRes.status }, error: err });
|
||||
return json({ error: 'Failed to login to Matrix account' }, { status: 500 });
|
||||
}
|
||||
|
||||
@@ -118,7 +121,7 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
try {
|
||||
await setMatrixAvatar(homeserverUrl, accessToken, profile.avatar_url);
|
||||
} catch (e) {
|
||||
console.warn('Failed to set Matrix avatar:', e);
|
||||
log.warn('Failed to set Matrix avatar', { error: e });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +141,7 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
);
|
||||
|
||||
if (upsertError) {
|
||||
console.error('Failed to store Matrix credentials:', upsertError);
|
||||
log.error('Failed to store Matrix credentials', { error: upsertError });
|
||||
return json({ error: 'Failed to store credentials' }, { status: 500 });
|
||||
}
|
||||
|
||||
@@ -152,7 +155,7 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
provisioned: true,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Matrix provisioning error:', e);
|
||||
log.error('Matrix provisioning error', { error: e });
|
||||
return json({ error: 'Matrix provisioning failed' }, { status: 500 });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { createLogger, getErrorMessage } from '$lib/utils/logger';
|
||||
|
||||
const log = createLogger('api:matrix-space');
|
||||
|
||||
/**
|
||||
* GET: Retrieve the Matrix Space ID for an org
|
||||
@@ -140,9 +143,9 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
||||
}
|
||||
|
||||
return json({ spaceId, created: true });
|
||||
} catch (e: any) {
|
||||
console.error('Failed to create Matrix Space:', e);
|
||||
return json({ error: e.message || 'Failed to create Matrix Space' }, { status: 500 });
|
||||
} catch (e: unknown) {
|
||||
log.error('Failed to create Matrix Space', { error: e });
|
||||
return json({ error: getErrorMessage(e, 'Failed to create Matrix Space') }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user