diff --git a/src/common/locales.ts b/src/common/locales.ts index 2197423f7..637342fc8 100644 --- a/src/common/locales.ts +++ b/src/common/locales.ts @@ -73,6 +73,7 @@ export type MessageName = | 'options_syncFeatureDescription' | 'options_turnOnSync' | 'options_turnOnSyncDialog_title' + | 'options_turnOnSyncDialog_useAltFlow' | 'options_turnOnSyncDialog_altFlowDescription' | 'options_turnOnSyncDialog_altFlowAuthCodeLabel' | 'options_turnOnSyncDialog_turnOnSyncButton' diff --git a/src/locales/en.json.ts b/src/locales/en.json.ts index cc4dddf3e..579d31d16 100644 --- a/src/locales/en.json.ts +++ b/src/locales/en.json.ts @@ -233,8 +233,11 @@ exportAsMessages('_locales/en/messages.json', { // The text of the button to turn on sync. options_turnOnSyncDialog_turnOnSyncButton: 'Turn on', + // The label of the check box whether to use the 'alternative' web auth flow. + // In this flow, the authentication page will be opened not in a new window, but in a new tab. + options_turnOnSyncDialog_useAltFlow: 'Open the authentication page in a new tab', + // The text to explain permission requests in the 'alternative' web auth flow. - // Currently it is used only in Safari. // '$1' is expanded to 'iorate.github.io'. options_turnOnSyncDialog_altFlowDescription: 'You may be asked for permission to access $1 before authentication, but your personal information will NOT be stored in that domain.', diff --git a/src/locales/ja.json.ts b/src/locales/ja.json.ts index dd88108bb..f62a8121a 100644 --- a/src/locales/ja.json.ts +++ b/src/locales/ja.json.ts @@ -83,6 +83,7 @@ exportAsMessages('_locales/ja/messages.json', { options_turnOnSync: '同期を有効にする', options_turnOnSyncDialog_title: '同期を有効にする', options_turnOnSyncDialog_turnOnSyncButton: '有効にする', + options_turnOnSyncDialog_useAltFlow: '新しいタブで認証ページを開く', options_turnOnSyncDialog_altFlowDescription: '認証中に $1 へのアクセス権限が求められることがありますが、個人情報がこのドメインに保存されることはありません。', options_turnOnSyncDialog_altFlowAuthCodeLabel: '認証コード', diff --git a/src/scripts/options/sync-section.tsx b/src/scripts/options/sync-section.tsx index 4f7f47c03..d53d72118 100644 --- a/src/scripts/options/sync-section.tsx +++ b/src/scripts/options/sync-section.tsx @@ -3,6 +3,7 @@ import dayjsDuration from 'dayjs/plugin/duration'; import React, { useEffect, useState } from 'react'; import { apis } from '../apis'; import { Button, LinkButton } from '../components/button'; +import { CheckBox } from '../components/checkbox'; import { FOCUS_END_CLASS, FOCUS_START_CLASS } from '../components/constants'; import { Dialog, @@ -50,16 +51,19 @@ const TurnOnSyncDialog: React.VFC< } = useOptionsContext(); const [state, setState] = useState({ - selectedCloudId: 'googleDrive' as CloudId, phase: 'none' as 'none' | 'auth' | 'auth-alt' | 'conn' | 'conn-alt', + selectedCloudId: 'googleDrive' as CloudId, + useAltFlow: false, authCode: '', }); const prevOpen = usePrevious(open); if (open && !prevOpen) { - state.selectedCloudId = 'googleDrive'; state.phase = 'none'; + state.selectedCloudId = 'googleDrive'; + state.useAltFlow = false; state.authCode = ''; } + const forceAltFlow = supportedClouds[state.selectedCloudId].shouldUseAltFlow(os); return ( @@ -94,7 +98,26 @@ const TurnOnSyncDialog: React.VFC< - {supportedClouds[state.selectedCloudId].shouldUseAltFlow(os) ? ( + + + + setState(s => ({ ...s, useAltFlow: e.currentTarget.checked }))} + /> + + + + + + {translate('options_turnOnSyncDialog_useAltFlow')} + + + + + {(forceAltFlow || state.useAltFlow) && ( @@ -105,7 +128,7 @@ const TurnOnSyncDialog: React.VFC< - ) : null} + )} {state.phase === 'auth-alt' || state.phase === 'conn-alt' ? ( @@ -163,7 +186,7 @@ const TurnOnSyncDialog: React.VFC< authCode = state.authCode; } else { const cloud = supportedClouds[state.selectedCloudId]; - useAltFlow = cloud.shouldUseAltFlow(os); + useAltFlow = forceAltFlow || state.useAltFlow; setState(s => ({ ...s, phase: useAltFlow ? 'auth-alt' : 'auth' })); try { const granted = await apis.permissions.request({