@meith/web 0.21.2 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/(board)/notifications/preferences/page.tsx +15 -1
- package/app/(board)/unsubscribe/page.tsx +5 -3
- package/app/admin/api/marketplace/screenshot/route.ts +0 -8
- package/app/admin/users/mail/page.tsx +1 -1
- package/app/layout.tsx +1 -3
- package/app/manifest.ts +1 -3
- package/bin/forum-web.mjs +1 -182
- package/bin/forum-web.test.ts +0 -22
- package/next.config.mjs +14 -29
- package/package.json +47 -47
- package/proxy.ts +0 -14
- package/src/components/account/notification-forms.tsx +45 -0
- package/src/components/admin/admin-nav.tsx +0 -4
- package/src/components/admin/marketplace-listing.tsx +0 -9
- package/src/components/auth/passkey-client.ts +0 -5
- package/src/components/auth/register-form.tsx +18 -0
- package/src/components/content/composer-ids.ts +0 -1
- package/src/components/content/markdown-editor.tsx +0 -7
- package/src/components/shell/demo-banner.tsx +0 -8
- package/src/config.ts +0 -11
- package/src/server/admin-actions.ts +0 -5
- package/src/server/antispam.ts +27 -14
- package/src/server/auth-actions.ts +12 -1
- package/src/server/auth-config.ts +0 -11
- package/src/server/auth-events.ts +0 -5
- package/src/server/brand-assets.ts +2 -6
- package/src/server/container.ts +0 -8
- package/src/server/cookies.ts +0 -24
- package/src/server/demo-uploads.ts +0 -11
- package/src/server/demo.ts +0 -21
- package/src/server/federation-actions.ts +0 -6
- package/src/server/federation.ts +0 -7
- package/src/server/feed-routes.ts +0 -5
- package/src/server/i18n.ts +1 -3
- package/src/server/location-header.ts +0 -30
- package/src/server/mail-send.ts +0 -6
- package/src/server/marketplace-actions.ts +0 -6
- package/src/server/marketplace-admin.ts +0 -33
- package/src/server/navigation.ts +0 -5
- package/src/server/notification-actions.ts +25 -0
- package/src/server/onboarding.ts +0 -5
- package/src/server/plugin-admin-actions.ts +0 -11
- package/src/server/plugin-admin.ts +0 -3
- package/src/server/plugin-host.ts +15 -6
- package/src/server/plugin-pages.ts +3 -68
- package/src/server/plugin-routes.ts +1 -1
- package/src/server/plugin-runtime.ts +78 -0
- package/src/server/presence.ts +3 -34
- package/src/server/relations.ts +1 -3
- package/src/server/reply-core.ts +1 -0
- package/src/server/request-fingerprint.ts +0 -1
- package/src/server/search-page.ts +0 -4
- package/src/server/session-actions.ts +0 -1
- package/src/server/settings.ts +0 -11
- package/src/server/subscription-actions.ts +12 -4
- package/src/server/syndication.ts +0 -4
- package/src/server/theme-admin.ts +2 -6
- package/src/server/thread-core.ts +6 -1
- package/src/server/two-factor-actions.ts +0 -5
- package/src/server/two-factor.ts +0 -6
- package/src/server/upgrade-notice.ts +1 -1
- package/src/view/account-copy.ts +5 -0
- package/src/view/auth-copy.ts +2 -0
- package/src/view/editor-toolbar.ts +0 -1
- package/src/view/navigation.ts +0 -4
- package/src/view/notification-menu.ts +0 -2
- package/src/view/notifications.ts +1 -0
- package/src/view/pager.ts +0 -6
- package/src/view/panel-nav.ts +0 -1
- package/src/view/security-activity.ts +0 -5
- package/src/view/subscriptions.ts +1 -0
- package/src/view/two-factor.ts +0 -5
- package/src/view/usercp.ts +1 -3
package/src/server/two-factor.ts
CHANGED
|
@@ -32,11 +32,6 @@ export function twoFactorService(): TwoFactorService | null {
|
|
|
32
32
|
})
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
/**
|
|
36
|
-
* Offered when the board says so and the board has a key to seal a secret
|
|
37
|
-
* with. Without AUTH_SECRET there is nowhere safe to put the secret, so the
|
|
38
|
-
* surface is hidden rather than half-built.
|
|
39
|
-
*/
|
|
40
35
|
export async function twoFactorOffered(): Promise<boolean> {
|
|
41
36
|
if (getContainer().dataSource !== 'postgres') return false
|
|
42
37
|
if (twoFactorService() === null) return false
|
|
@@ -49,7 +44,6 @@ export async function twoFactorRequiredForStaff(): Promise<boolean> {
|
|
|
49
44
|
return (await getSettingsUncached()).get('security.two_factor_required_for_staff')
|
|
50
45
|
}
|
|
51
46
|
|
|
52
|
-
/** Whether this member must hold a second factor, and may not drop it. */
|
|
53
47
|
export async function secondFactorPosture(userId: number | null): Promise<SecondFactorPosture> {
|
|
54
48
|
const offered = await twoFactorOffered()
|
|
55
49
|
if (!offered || userId === null) return { offered, required: false }
|
|
@@ -6,7 +6,7 @@ import { planUpgrade, type UpgradeState, upgradeNotice } from '@meith/upgrade'
|
|
|
6
6
|
|
|
7
7
|
import { activeDefinitions } from './plugin-host'
|
|
8
8
|
|
|
9
|
-
export const CODE_VERSION = '0.
|
|
9
|
+
export const CODE_VERSION = '0.22.0'
|
|
10
10
|
|
|
11
11
|
export async function pendingUpgradeNotice(): Promise<string | null> {
|
|
12
12
|
if (env.DATA_SOURCE !== 'postgres') return null
|
package/src/view/account-copy.ts
CHANGED
|
@@ -297,6 +297,11 @@ export function notificationFormsCopy(
|
|
|
297
297
|
'accountForm.notifications.push',
|
|
298
298
|
'accountForm.notifications.blurb',
|
|
299
299
|
'accountForm.notifications.submit',
|
|
300
|
+
'accountForm.announcements.legend',
|
|
301
|
+
'accountForm.announcements.title',
|
|
302
|
+
'accountForm.announcements.description',
|
|
303
|
+
'accountForm.announcements.blurb',
|
|
304
|
+
'accountForm.announcements.submit',
|
|
300
305
|
'accountForm.push.heading',
|
|
301
306
|
'accountForm.push.subscribe',
|
|
302
307
|
'accountForm.push.unsubscribe',
|
package/src/view/auth-copy.ts
CHANGED
|
@@ -34,6 +34,8 @@ export function registerFormCopy(
|
|
|
34
34
|
'authForm.register.password',
|
|
35
35
|
'authForm.register.honeypot',
|
|
36
36
|
'authForm.register.challengeHint',
|
|
37
|
+
'authForm.register.announcements',
|
|
38
|
+
'authForm.register.announcementsHint',
|
|
37
39
|
'authForm.register.submit',
|
|
38
40
|
],
|
|
39
41
|
t,
|
|
@@ -62,7 +62,6 @@ function button(spec: ToolSpec, t: Translator): EditorToolbarButtonModel {
|
|
|
62
62
|
|
|
63
63
|
export interface EditorToolbarInput {
|
|
64
64
|
readonly textareaId?: string
|
|
65
|
-
/** Whether this composer takes attachments. Defaults to `false`. */
|
|
66
65
|
readonly attachments?: boolean
|
|
67
66
|
readonly t?: Translator
|
|
68
67
|
}
|
package/src/view/navigation.ts
CHANGED
|
@@ -67,10 +67,6 @@ export function defaultNavigationItems(): readonly NavigationItemRow[] {
|
|
|
67
67
|
}))
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
/**
|
|
71
|
-
* What a plugin called an item, for the rows the board holds on its behalf.
|
|
72
|
-
* Keyed by the same `plugin.<plugin>.<item>` the row carries.
|
|
73
|
-
*/
|
|
74
70
|
export interface NavigationName {
|
|
75
71
|
readonly label: string
|
|
76
72
|
readonly labelKey: string | null
|
|
@@ -13,14 +13,12 @@ export type NotificationMenuTabKind = 'notifications' | 'messages' | 'mod'
|
|
|
13
13
|
|
|
14
14
|
export interface NotificationMenuRow {
|
|
15
15
|
readonly key: string
|
|
16
|
-
/** The id a mark-seen form submits, or `null` for a row that is acted on elsewhere. */
|
|
17
16
|
readonly seenId: number | null
|
|
18
17
|
readonly subject: string
|
|
19
18
|
readonly meta: string | null
|
|
20
19
|
readonly href: string | null
|
|
21
20
|
readonly at: TimeModel
|
|
22
21
|
readonly isUnread: boolean
|
|
23
|
-
/** A short category label shown before the subject, or `null`. */
|
|
24
22
|
readonly tag: string | null
|
|
25
23
|
}
|
|
26
24
|
|
|
@@ -77,6 +77,7 @@ export function notificationNotice(
|
|
|
77
77
|
},
|
|
78
78
|
t: Translator = untranslated(),
|
|
79
79
|
): string | null {
|
|
80
|
+
if (query.saved === 'announcements') return t.t('notice.announcementsSaved')
|
|
80
81
|
if (query.saved !== undefined) return t.t('notice.preferencesSaved')
|
|
81
82
|
if (query.read === 'all') return t.t('notice.allRead')
|
|
82
83
|
if (query.read === 'one') return t.t('notice.markedRead')
|
package/src/view/pager.ts
CHANGED
|
@@ -15,12 +15,6 @@ export type Cursor = Readonly<Record<string, string>>
|
|
|
15
15
|
export interface PagerInput {
|
|
16
16
|
readonly path: string
|
|
17
17
|
readonly params: QueryParams
|
|
18
|
-
/**
|
|
19
|
-
* The query parameters the cursor owns. They are rewritten on every step and
|
|
20
|
-
* never carried forward from the current address, which is what keeps a
|
|
21
|
-
* two-part cursor — a rank and an id — from being half of one page and half
|
|
22
|
-
* of the next.
|
|
23
|
-
*/
|
|
24
18
|
readonly cursorParams: readonly string[]
|
|
25
19
|
readonly nextCursor: Cursor | null
|
|
26
20
|
readonly pageSize?: number
|
package/src/view/panel-nav.ts
CHANGED
|
@@ -12,7 +12,6 @@ import { untranslated } from './time'
|
|
|
12
12
|
export interface PanelSubsection {
|
|
13
13
|
readonly href: string
|
|
14
14
|
readonly titleKey?: string
|
|
15
|
-
/** Set instead of `titleKey` where the name is data, such as a plugin's. */
|
|
16
15
|
readonly titleText?: string
|
|
17
16
|
readonly record?: boolean
|
|
18
17
|
}
|
|
@@ -30,11 +30,6 @@ export function authEventLabel(kind: string, t: Translator = untranslated()): st
|
|
|
30
30
|
return key === undefined ? kind.replace(/_/g, ' ') : t.t(key)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
* Enough of a user-agent string for a member to tell one of their own devices
|
|
35
|
-
* from another, and no more: the full string is a fingerprint, and this is a
|
|
36
|
-
* page whose job is recognition, not identification.
|
|
37
|
-
*/
|
|
38
33
|
export function describeDevice(userAgent: string | null, t: Translator = untranslated()): string {
|
|
39
34
|
const unknown = t.t('device.unknown')
|
|
40
35
|
if (userAgent === null || userAgent.trim() === '') return unknown
|
|
@@ -70,6 +70,7 @@ export function unsubscribeNotice(
|
|
|
70
70
|
done: string | undefined,
|
|
71
71
|
t: Translator = untranslated(),
|
|
72
72
|
): string | null {
|
|
73
|
+
if (done === 'announcements') return t.t('subscription.announcementsOff')
|
|
73
74
|
if (done === 'email') return t.t('subscription.emailsOff')
|
|
74
75
|
if (done === 'one') return t.t('subscription.doneOne')
|
|
75
76
|
return null
|
package/src/view/two-factor.ts
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The form-state key the fresh recovery codes travel back under. It lives here
|
|
3
|
-
* rather than beside the action because a `'use server'` module may export
|
|
4
|
-
* nothing but async functions, and the client component needs to read it.
|
|
5
|
-
*/
|
|
6
1
|
export const RECOVERY_CODES_FIELD = 'recoveryCodes'
|
package/src/view/usercp.ts
CHANGED