mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-04 06:02:08 +08:00
fix(service): explain core security failures and link repair guidance
This commit is contained in:
@@ -3,6 +3,7 @@ import {
|
||||
Snackbar,
|
||||
Alert,
|
||||
IconButton,
|
||||
Link,
|
||||
Box,
|
||||
Stack,
|
||||
type SnackbarOrigin,
|
||||
@@ -18,6 +19,12 @@ import {
|
||||
showNotice,
|
||||
} from '@/services/notice-service'
|
||||
import type { TranslationKey } from '@/types/generated/i18n-keys'
|
||||
import { openExternalUrl } from '@/utils/open-external-url'
|
||||
|
||||
const SERVICE_PERMISSION_NOTICE =
|
||||
'settings.feedback.notifications.clashService.permissionFallback'
|
||||
const SERVICE_PERMISSION_GUIDE =
|
||||
'https://clash-verge-rev.github.io/faq/windows.html#service-core-permissions'
|
||||
|
||||
type NoticePosition = NonNullable<IVergeConfig['notice_position']>
|
||||
type NoticeItem = ReturnType<typeof getSnapshotNotices>[number]
|
||||
@@ -59,6 +66,38 @@ const resolveNoticeMessage = (
|
||||
const i18n = notice.i18n
|
||||
if (!i18n) return bound(notice.message)
|
||||
|
||||
if (i18n.key === SERVICE_PERMISSION_NOTICE) {
|
||||
const reason = i18n.params?.reason
|
||||
return (
|
||||
<>
|
||||
{t(SERVICE_PERMISSION_NOTICE, {
|
||||
reason: t(
|
||||
typeof reason === 'string' && reason.includes('is writable by')
|
||||
? 'settings.feedback.notifications.clashService.permissionWritableReason'
|
||||
: 'settings.feedback.notifications.clashService.permissionRejectedReason',
|
||||
),
|
||||
})}
|
||||
<Box sx={{ mt: 1 }}>
|
||||
<Link
|
||||
href={SERVICE_PERMISSION_GUIDE}
|
||||
color="inherit"
|
||||
underline="always"
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
void openExternalUrl(SERVICE_PERMISSION_GUIDE).catch(
|
||||
showNotice.error,
|
||||
)
|
||||
}}
|
||||
>
|
||||
{t(
|
||||
'settings.feedback.notifications.clashService.permissionRepairGuide',
|
||||
)}
|
||||
</Link>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const source = (i18n.params ?? {}) as Record<string, unknown>
|
||||
// Bound both parameters and their final interpolation.
|
||||
const params =
|
||||
@@ -132,6 +171,9 @@ const resolveNoticeCopyText = (
|
||||
notice: NoticeItem,
|
||||
t: TranslationFn,
|
||||
): string | undefined => {
|
||||
if (notice.i18n?.key === SERVICE_PERMISSION_NOTICE) {
|
||||
return extractNoticeCopyText(notice.i18n.params?.reason)
|
||||
}
|
||||
if (
|
||||
notice.i18n?.key === 'shared.feedback.notices.prefixedRaw' ||
|
||||
notice.i18n?.key === 'shared.feedback.notices.raw'
|
||||
|
||||
@@ -78,6 +78,7 @@ it('reports the permission refusal and finishes after installation falls back to
|
||||
expect(showNotice.warning).toHaveBeenCalledWith(
|
||||
'settings.feedback.notifications.clashService.permissionFallback',
|
||||
{ reason },
|
||||
0,
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ export const ServiceMigrationDialog = () => {
|
||||
showNotice.warning(
|
||||
'settings.feedback.notifications.clashService.permissionFallback',
|
||||
{ reason: outcome.reason },
|
||||
0,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ export const SysproxyPrivilegeDialog = () => {
|
||||
showNotice.warning(
|
||||
'settings.feedback.notifications.clashService.permissionFallback',
|
||||
{ reason: outcome.reason },
|
||||
0,
|
||||
)
|
||||
close()
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user