Skip to content

Commit 50e049f

Browse files
committed
resolved errors and corrected the code while showing the service messages and removing the unsupported media
2 parents 828e5db + 26540ca commit 50e049f

File tree

15 files changed

+1510
-79
lines changed

15 files changed

+1510
-79
lines changed

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# Changelog
22

3+
## [2.4.0](https://github.com/storacha/tg-miniapp/compare/v2.3.1...v2.4.0) (2025-07-01)
4+
5+
6+
### Features
7+
8+
* highlight myself in the leaderboard ([25f5186](https://github.com/storacha/tg-miniapp/commit/25f51861e70bb793ad772d16a54080ba9cdad59c))
9+
* improve sign in flow ([ca22cb8](https://github.com/storacha/tg-miniapp/commit/ca22cb8287ea2d0109924f2a2a933605995d7370))
10+
* install sentry, for real ([7b9750a](https://github.com/storacha/tg-miniapp/commit/7b9750a545bfa1034b865b5164b5ac25d8cdbbc8))
11+
12+
13+
### Bug Fixes
14+
15+
* add error message for expired email verification link ([3c85278](https://github.com/storacha/tg-miniapp/commit/3c85278a09181694c0c83da57b9f1d16788980e0))
16+
* add error message for expired email verification link ([402ab9a](https://github.com/storacha/tg-miniapp/commit/402ab9ac983c266ea4acb2c5b2bfca3a8b415a19))
17+
* add telegram to `serverExternalPackages` ([6eaf4e3](https://github.com/storacha/tg-miniapp/commit/6eaf4e339b9df3a6d7241b35e31908a0e593fcd3))
18+
* format date-time in current user locale ([9e3869a](https://github.com/storacha/tg-miniapp/commit/9e3869a47d4a2e282ed1ab42f582421fda8608e2))
19+
* format date-time in current user locale ([3ee0a71](https://github.com/storacha/tg-miniapp/commit/3ee0a7142cdc247f75bb416ddaff67fe7e561b5b))
20+
* improve view for unsupported media ([455087a](https://github.com/storacha/tg-miniapp/commit/455087ae83eb222ca426160e1c69883e0439c8d7))
21+
* improve visualization to unsupported media ([01abab4](https://github.com/storacha/tg-miniapp/commit/01abab40aaeb47bd9b184ba0b6fe3032b36db8ab))
22+
* skip unsupported media and fix missing user info header ([437c185](https://github.com/storacha/tg-miniapp/commit/437c18500896450a03d37e083116a88261808dd9))
23+
* skip unsupported media and fix missing user info header ([1de435c](https://github.com/storacha/tg-miniapp/commit/1de435c20adef1c1db73624f59bbf21e35b6cc85))
24+
325
## [2.3.1](https://github.com/storacha/tg-miniapp/compare/v2.3.0...v2.3.1) (2025-06-27)
426

527

app/app/dialog/[id]/backup/[cid]/page.tsx

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ const formatDate = (timestamp: number) =>
4444
year: 'numeric',
4545
})
4646

47+
const INITIAL_MESSAGE_BATCH_SIZE = 20
48+
4749
const Message: React.FC<{
4850
isOutgoing: boolean
4951
date: number
@@ -386,7 +388,6 @@ const formatServiceMessage = (
386388
}
387389
}
388390

389-
390391
const UserInfo: React.FC<{ thumbSrc: string; userName: string }> = ({
391392
thumbSrc,
392393
userName,
@@ -425,6 +426,26 @@ function BackupDialog({
425426
let lastRenderedDate: string | null = null
426427
let lastSenderId: string | null = null
427428

429+
// const filteredMessages: MessageData[] = useMemo(
430+
// () =>
431+
// messages.filter((msg): msg is MessageData => {
432+
// // Skip all service messages for now, this should be handled later
433+
// if (msg.type === 'service') {
434+
// return false
435+
// }
436+
437+
// /**
438+
// * Skip unsupported media types, there's no point in showing them.
439+
// */
440+
// if (msg.media?.metadata?.type === 'unsupported') {
441+
// return false
442+
// }
443+
444+
// return true
445+
// }),
446+
// [messages]
447+
// )
448+
428449
let dialogThumbSrc = ''
429450
if (dialog.photo?.strippedThumb) {
430451
dialogThumbSrc = toJPGDataURL(
@@ -489,8 +510,9 @@ function BackupDialog({
489510
if (chatContainer) {
490511
chatContainer.addEventListener('scroll', handleScroll, { passive: true })
491512

492-
// Also check scroll position on mount and when messages change
493-
handleScroll()
513+
if (messages.length >= INITIAL_MESSAGE_BATCH_SIZE) {
514+
handleScroll()
515+
}
494516
}
495517

496518
return () => {
@@ -507,31 +529,37 @@ function BackupDialog({
507529
name={dialog.name}
508530
type={dialog.type}
509531
/>
510-
511-
{isLoading ? (
532+
533+
{isLoading ? (
512534
<div className="flex flex-col items-center justify-center flex-1">
513535
<Loading text="Loading messages..." />
514536
</div>
515537
) : (
516-
<div
517-
ref={chatContainerRef}
518-
className="flex-1 overflow-y-auto px-4 py-6 space-y-4"
519-
style={{ height: 'calc(100vh - 64px)' }} // Ensure proper height
520-
>
521-
{messages.map((msg) => {
538+
<div
539+
ref={chatContainerRef}
540+
className="flex-1 overflow-y-auto px-4 py-6 space-y-4"
541+
style={{ height: 'calc(100vh - 64px)' }} // Ensure proper height
542+
>
543+
{messages.map((msg) => {
544+
if (
545+
msg.type === 'message' &&
546+
msg.media?.metadata?.type === 'unsupported'
547+
) {
548+
return null
549+
}
522550
const date = formatDate(msg.date)
523551
const showDate = lastRenderedDate !== date
524552
if (showDate) lastRenderedDate = date
525553

526-
const isOutgoing = msg.from === userId
527-
const sender = msg.from
528-
? (participants[msg.from]?.name ?? 'Unknown')
529-
: 'Anonymous'
554+
const isOutgoing = msg.from === userId
555+
const sender = msg.from
556+
? (participants[msg.from]?.name ?? 'Unknown')
557+
: 'Anonymous'
530558

531-
const showSenderHeader = !isOutgoing && lastSenderId !== msg.from
532-
lastSenderId = msg.from ?? null
559+
const showSenderHeader = !isOutgoing && lastSenderId !== msg.from
560+
lastSenderId = msg.from ?? null
533561

534-
let thumbSrc = ''
562+
let thumbSrc = ''
535563
if (msg.from && participants[msg.from]?.photo?.strippedThumb) {
536564
thumbSrc = toJPGDataURL(
537565
decodeStrippedThumb(
@@ -559,12 +587,12 @@ function BackupDialog({
559587
{showDate && <ServiceMessage text={date} />}
560588
{/* { msg.type === 'service' && <ServiceMessage text={msg.action.description} /> } // TODO: would be nice to have a description for each action */}
561589
{msg.type === 'service' ? (
562-
<div className="flex flex-col items-center space-y-1">
563-
<ServiceMessage
564-
text={formatServiceMessage(msg, participants)}
565-
/>
566-
</div>
567-
) : (
590+
<div className="flex flex-col items-center space-y-1">
591+
<ServiceMessage
592+
text={formatServiceMessage(msg, participants)}
593+
/>
594+
</div>
595+
) : (
568596
<div
569597
className={`flex ${
570598
isOutgoing ? 'justify-end' : 'justify-start'
@@ -595,12 +623,12 @@ function BackupDialog({
595623
</Fragment>
596624
)
597625
})}
598-
{isLoadingMore && (
599-
<div className="text-center py-4">
600-
<Loading text="Loading more messages..." />
601-
</div>
602-
)}
603-
</div>
626+
{isLoadingMore && (
627+
<div className="text-center py-4">
628+
<Loading text="Loading more messages..." />
629+
</div>
630+
)}
631+
</div>
604632
)}
605633
</div>
606634
)
@@ -649,7 +677,7 @@ export default function Page() {
649677
(restoredBackup.item && restoredBackup.item.backupCid === backupCid)
650678
)
651679
return
652-
await restoreBackup(backupCid!, normalizedId, 20)
680+
await restoreBackup(backupCid!, normalizedId, INITIAL_MESSAGE_BATCH_SIZE)
653681
}
654682

655683
fetchBackup()

app/app/global-error.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use client'
2+
3+
import * as Sentry from '@sentry/nextjs'
4+
import NextError from 'next/error'
5+
import { useEffect } from 'react'
6+
7+
export default function GlobalError({
8+
error,
9+
}: {
10+
error: Error & { digest?: string }
11+
}) {
12+
useEffect(() => {
13+
Sentry.captureException(error)
14+
}, [error])
15+
16+
return (
17+
<html>
18+
<body>
19+
{/* `NextError` is the default Next.js error page component. Its type
20+
definition requires a `statusCode` prop. However, since the App Router
21+
does not expose status codes for errors, we simply pass 0 to render a
22+
generic error message. */}
23+
<NextError statusCode={0} />
24+
</body>
25+
</html>
26+
)
27+
}

app/components/backup/dialog-item.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ export const DialogItem = ({ dialog, latestBackup }: DialogItemProps) => {
1212
const { name, initials, photo } = dialog
1313
const thumbSrc = getThumbSrc(photo?.strippedThumb)
1414
const { formatDateTime } = useUserLocale()
15-
const latestBackupDate = formatDateTime(Number(latestBackup?.[1]))
15+
const latestBackupDate = latestBackup
16+
? formatDateTime(Number(latestBackup[1]))
17+
: undefined
1618

1719
return (
1820
<div className="flex gap-4 items-center w-full">

app/components/ui/media.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ export const Media: React.FC<MediaProps> = ({ mediaUrl, metadata, time }) => {
123123
}
124124
break
125125
}
126+
case 'unsupported': {
127+
// skipping unsupported media types visualization
128+
break
129+
}
126130
default: {
127131
console.log(JSON.stringify(metadata))
128132
mediaContent = (

app/instrumentation-client.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// This file configures the initialization of Sentry on the client.
2+
// The added config here will be used whenever a users loads a page in their browser.
3+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
4+
5+
import * as Sentry from '@sentry/nextjs'
6+
7+
Sentry.init({
8+
dsn: 'https://[email protected]/4509561976455168',
9+
10+
// Setting this option to true will print useful information to the console while you're setting up Sentry.
11+
debug: false,
12+
})
13+
14+
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart

app/instrumentation.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import * as Sentry from '@sentry/nextjs'
2+
3+
export async function register() {
4+
if (process.env.NEXT_RUNTIME === 'nodejs') {
5+
await import('./sentry.server.config')
6+
}
7+
8+
if (process.env.NEXT_RUNTIME === 'edge') {
9+
await import('./sentry.edge.config')
10+
}
11+
}
12+
13+
export const onRequestError = Sentry.captureRequestError

app/lib/sentry.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { captureException } from '@sentry/nextjs'
2+
3+
/**
4+
* Log to the error console and capture the error in Sentry.
5+
*
6+
* @param err the error - typed as unknown to match catch(err)
7+
*/
8+
export function logAndCaptureError(err: unknown) {
9+
console.error(err)
10+
captureException(err)
11+
}

app/lib/server/runner.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ export const run = async (
291291
if (!mediaRoot) throw new Error('missing media root')
292292
}
293293

294-
messages.push(toMessageData(message, mediaRoot))
294+
messages.push(toMessageData(message, fromID, mediaRoot))
295295
if (messages.length === maxMessages) {
296296
break
297297
}
@@ -354,10 +354,9 @@ const callWithDialogsSync = async <T>(
354354

355355
const toMessageData = (
356356
message: Api.Message | Api.MessageService,
357+
from: ToString<bigint>,
357358
mediaRoot?: Link<EncryptedTaggedByteView<Uint8Array>>
358359
): MessageData | ServiceMessageData => {
359-
const from = message.fromId && toPeerID(message.fromId)
360-
361360
if (message.className === 'MessageService') {
362361
const action = toActionData(message.action)
363362
if (!action) throw new Error('missing service message action')

app/next.config.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pkg from './package.json'
2+
import { withSentryConfig } from '@sentry/nextjs'
23
import type { NextConfig } from 'next'
34

45
const nextConfig: NextConfig = {
@@ -9,6 +10,37 @@ const nextConfig: NextConfig = {
910
experimental: {
1011
nodeMiddleware: true, // TODO: remove this
1112
},
13+
serverExternalPackages: ['telegram'],
1214
}
1315

14-
export default nextConfig
16+
export default withSentryConfig(nextConfig, {
17+
// For all available options, see:
18+
// https://www.npmjs.com/package/@sentry/webpack-plugin#options
19+
20+
org: 'storacha-it',
21+
project: 'tg-miniapp',
22+
23+
// Only print logs for uploading source maps in CI
24+
silent: !process.env.CI,
25+
26+
// For all available options, see:
27+
// https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/
28+
29+
// Upload a larger set of source maps for prettier stack traces (increases build time)
30+
widenClientFileUpload: true,
31+
32+
// Uncomment to route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
33+
// This can increase your server load as well as your hosting bill.
34+
// Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
35+
// side errors will fail.
36+
// tunnelRoute: "/monitoring",
37+
38+
// Automatically tree-shake Sentry logger statements to reduce bundle size
39+
disableLogger: true,
40+
41+
// Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
42+
// See the following for more information:
43+
// https://docs.sentry.io/product/crons/
44+
// https://vercel.com/docs/cron-jobs
45+
automaticVercelMonitors: true,
46+
})

0 commit comments

Comments
 (0)