diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index b042205cf4d..e4fe9e7c4ed 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -15,7 +15,6 @@ import { Link } from "@/components/link" import { useLanguage } from "@/context/language" import { useGlobalSDK } from "@/context/global-sdk" import { useGlobalSync } from "@/context/global-sync" -import { usePlatform } from "@/context/platform" import { DialogSelectModel } from "./dialog-select-model" import { DialogSelectProvider } from "./dialog-select-provider" @@ -23,7 +22,6 @@ export function DialogConnectProvider(props: { provider: string }) { const dialog = useDialog() const globalSync = useGlobalSync() const globalSDK = useGlobalSDK() - const platform = usePlatform() const language = useLanguage() const alive = { value: true } @@ -49,13 +47,14 @@ export function DialogConnectProvider(props: { provider: string }) { const [store, setStore] = createStore({ methodIndex: undefined as undefined | number, authorization: undefined as undefined | ProviderAuthAuthorization, - state: "pending" as undefined | "pending" | "complete" | "error", + state: "pending" as undefined | "pending" | "complete" | "error" | "prompt", error: undefined as string | undefined, }) type Action = | { type: "method.select"; index: number } | { type: "method.reset" } + | { type: "auth.prompt" } | { type: "auth.pending" } | { type: "auth.complete"; authorization: ProviderAuthAuthorization } | { type: "auth.error"; error: string } @@ -77,6 +76,11 @@ export function DialogConnectProvider(props: { provider: string }) { draft.error = undefined return } + if (action.type === "auth.prompt") { + draft.state = "prompt" + draft.error = undefined + return + } if (action.type === "auth.pending") { draft.state = "pending" draft.error = undefined @@ -120,7 +124,7 @@ export function DialogConnectProvider(props: { provider: string }) { return fallback } - async function selectMethod(index: number) { + async function selectMethod(index: number, inputs?: Record) { if (timer.current !== undefined) { clearTimeout(timer.current) timer.current = undefined @@ -130,6 +134,10 @@ export function DialogConnectProvider(props: { provider: string }) { dispatch({ type: "method.select", index }) if (method.type === "oauth") { + if (method.prompts?.length && !inputs) { + dispatch({ type: "auth.prompt" }) + return + } dispatch({ type: "auth.pending" }) const start = Date.now() await globalSDK.client.provider.oauth @@ -137,6 +145,7 @@ export function DialogConnectProvider(props: { provider: string }) { { providerID: props.provider, method: index, + inputs, }, { throwOnError: true }, ) @@ -163,6 +172,122 @@ export function DialogConnectProvider(props: { provider: string }) { } } + function OAuthPromptsView() { + const [formStore, setFormStore] = createStore({ + value: {} as Record, + index: 0, + }) + + const prompts = createMemo(() => method()?.prompts ?? []) + const matches = (prompt: NonNullable[number]>, value: Record) => { + if (!prompt.when) return true + const actual = value[prompt.when.key] + if (actual === undefined) return false + return prompt.when.op === "eq" ? actual === prompt.when.value : actual !== prompt.when.value + } + const current = createMemo(() => { + const all = prompts() + const index = all.findIndex((prompt, index) => index >= formStore.index && matches(prompt, formStore.value)) + if (index === -1) return + return { + index, + prompt: all[index], + } + }) + const valid = createMemo(() => { + const item = current() + if (!item || item.prompt.type !== "text") return false + const value = formStore.value[item.prompt.key] ?? "" + return value.trim().length > 0 + }) + + async function next(index: number, value: Record) { + if (store.methodIndex === undefined) return + const next = prompts().findIndex((prompt, i) => i > index && matches(prompt, value)) + if (next !== -1) { + setFormStore("index", next) + return + } + await selectMethod(store.methodIndex, value) + } + + async function handleSubmit(e: SubmitEvent) { + e.preventDefault() + const item = current() + if (!item || item.prompt.type !== "text") return + if (!valid()) return + await next(item.index, formStore.value) + } + + const item = () => current() + const text = createMemo(() => { + const prompt = item()?.prompt + if (!prompt || prompt.type !== "text") return + return prompt + }) + const select = createMemo(() => { + const prompt = item()?.prompt + if (!prompt || prompt.type !== "select") return + return prompt + }) + + return ( +
+ + + { + const prompt = text() + if (!prompt) return + setFormStore("value", prompt.key, value) + }} + /> + + + +
+
{select()?.message}
+
+ x.value} + current={select()?.options.find((x) => x.value === formStore.value[select()!.key])} + onSelect={(value) => { + if (!value) return + const prompt = select() + if (!prompt) return + const nextValue = { + ...formStore.value, + [prompt.key]: value.value, + } + setFormStore("value", prompt.key, value.value) + void next(item()!.index, nextValue) + }} + > + {(option) => ( +
+
+ + {option.label} + {option.hint} +
+ )} + +
+
+ + + + ) + } + let listRef: ListRef | undefined function handleKey(e: KeyboardEvent) { if (e.key === "Enter" && e.target instanceof HTMLInputElement) { @@ -301,7 +426,7 @@ export function DialogConnectProvider(props: { provider: string }) { error={formStore.error} />
@@ -314,12 +439,6 @@ export function DialogConnectProvider(props: { provider: string }) { error: undefined as string | undefined, }) - onMount(() => { - if (store.authorization?.method === "code" && store.authorization?.url) { - platform.openLink(store.authorization.url) - } - }) - async function handleSubmit(e: SubmitEvent) { e.preventDefault() @@ -368,7 +487,7 @@ export function DialogConnectProvider(props: { provider: string }) { error={formStore.error} /> @@ -386,10 +505,6 @@ export function DialogConnectProvider(props: { provider: string }) { onMount(() => { void (async () => { - if (store.authorization?.url) { - platform.openLink(store.authorization.url) - } - const result = await globalSDK.client.provider.oauth .callback({ providerID: props.provider, @@ -470,6 +585,9 @@ export function DialogConnectProvider(props: { provider: string }) {
+ + +
diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts index 720045a4d1c..c8f58c796e6 100644 --- a/packages/app/src/i18n/ar.ts +++ b/packages/app/src/i18n/ar.ts @@ -204,6 +204,7 @@ export const dict = { "common.cancel": "إلغاء", "common.connect": "اتصال", "common.disconnect": "قطع الاتصال", + "common.continue": "إرسال", "common.submit": "إرسال", "common.save": "حفظ", "common.saving": "جارٍ الحفظ...", diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts index a7d7433b02c..3112e91bbea 100644 --- a/packages/app/src/i18n/br.ts +++ b/packages/app/src/i18n/br.ts @@ -204,6 +204,7 @@ export const dict = { "common.cancel": "Cancelar", "common.connect": "Conectar", "common.disconnect": "Desconectar", + "common.continue": "Enviar", "common.submit": "Enviar", "common.save": "Salvar", "common.saving": "Salvando...", diff --git a/packages/app/src/i18n/bs.ts b/packages/app/src/i18n/bs.ts index ccdf2b6044d..f2dbd8493c6 100644 --- a/packages/app/src/i18n/bs.ts +++ b/packages/app/src/i18n/bs.ts @@ -221,6 +221,7 @@ export const dict = { "common.cancel": "Otkaži", "common.connect": "Poveži", "common.disconnect": "Prekini vezu", + "common.continue": "Pošalji", "common.submit": "Pošalji", "common.save": "Sačuvaj", "common.saving": "Čuvanje...", diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts index f1701094b56..e90e1071ad5 100644 --- a/packages/app/src/i18n/da.ts +++ b/packages/app/src/i18n/da.ts @@ -219,6 +219,7 @@ export const dict = { "common.cancel": "Annuller", "common.connect": "Forbind", "common.disconnect": "Frakobl", + "common.continue": "Indsend", "common.submit": "Indsend", "common.save": "Gem", "common.saving": "Gemmer...", diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts index 2dfeed72032..69658b29e9a 100644 --- a/packages/app/src/i18n/de.ts +++ b/packages/app/src/i18n/de.ts @@ -209,6 +209,7 @@ export const dict = { "common.cancel": "Abbrechen", "common.connect": "Verbinden", "common.disconnect": "Trennen", + "common.continue": "Absenden", "common.submit": "Absenden", "common.save": "Speichern", "common.saving": "Speichert...", diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index 7f6816de9e3..72caed40ad9 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -221,6 +221,7 @@ export const dict = { "common.open": "Open", "common.connect": "Connect", "common.disconnect": "Disconnect", + "common.continue": "Continue", "common.submit": "Submit", "common.save": "Save", "common.saving": "Saving...", diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts index 1cd47dfc796..9e36e4de6db 100644 --- a/packages/app/src/i18n/es.ts +++ b/packages/app/src/i18n/es.ts @@ -220,6 +220,7 @@ export const dict = { "common.cancel": "Cancelar", "common.connect": "Conectar", "common.disconnect": "Desconectar", + "common.continue": "Enviar", "common.submit": "Enviar", "common.save": "Guardar", "common.saving": "Guardando...", diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts index c7d89c3251b..f53b3882c6d 100644 --- a/packages/app/src/i18n/fr.ts +++ b/packages/app/src/i18n/fr.ts @@ -204,6 +204,7 @@ export const dict = { "common.cancel": "Annuler", "common.connect": "Connecter", "common.disconnect": "Déconnecter", + "common.continue": "Soumettre", "common.submit": "Soumettre", "common.save": "Enregistrer", "common.saving": "Enregistrement...", diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts index 267411083f4..d66a7341d5a 100644 --- a/packages/app/src/i18n/ja.ts +++ b/packages/app/src/i18n/ja.ts @@ -203,6 +203,7 @@ export const dict = { "common.cancel": "キャンセル", "common.connect": "接続", "common.disconnect": "切断", + "common.continue": "送信", "common.submit": "送信", "common.save": "保存", "common.saving": "保存中...", diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts index bb57f99396b..d534c27e8fb 100644 --- a/packages/app/src/i18n/ko.ts +++ b/packages/app/src/i18n/ko.ts @@ -207,6 +207,7 @@ export const dict = { "common.cancel": "취소", "common.connect": "연결", "common.disconnect": "연결 해제", + "common.continue": "제출", "common.submit": "제출", "common.save": "저장", "common.saving": "저장 중...", diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts index 83d6a9903b6..c23d0a27927 100644 --- a/packages/app/src/i18n/no.ts +++ b/packages/app/src/i18n/no.ts @@ -223,6 +223,7 @@ export const dict = { "common.cancel": "Avbryt", "common.connect": "Koble til", "common.disconnect": "Koble fra", + "common.continue": "Send inn", "common.submit": "Send inn", "common.save": "Lagre", "common.saving": "Lagrer...", diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts index db9ef18003e..dac847b217f 100644 --- a/packages/app/src/i18n/pl.ts +++ b/packages/app/src/i18n/pl.ts @@ -205,6 +205,7 @@ export const dict = { "common.cancel": "Anuluj", "common.connect": "Połącz", "common.disconnect": "Rozłącz", + "common.continue": "Prześlij", "common.submit": "Prześlij", "common.save": "Zapisz", "common.saving": "Zapisywanie...", diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts index e1abb6e6cf6..684d5deecd0 100644 --- a/packages/app/src/i18n/ru.ts +++ b/packages/app/src/i18n/ru.ts @@ -220,6 +220,7 @@ export const dict = { "common.cancel": "Отмена", "common.connect": "Подключить", "common.disconnect": "Отключить", + "common.continue": "Отправить", "common.submit": "Отправить", "common.save": "Сохранить", "common.saving": "Сохранение...", diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts index b522e4631b9..80f0da94ec6 100644 --- a/packages/app/src/i18n/th.ts +++ b/packages/app/src/i18n/th.ts @@ -220,6 +220,7 @@ export const dict = { "common.cancel": "ยกเลิก", "common.connect": "เชื่อมต่อ", "common.disconnect": "ยกเลิกการเชื่อมต่อ", + "common.continue": "ส่ง", "common.submit": "ส่ง", "common.save": "บันทึก", "common.saving": "กำลังบันทึก...", diff --git a/packages/app/src/i18n/tr.ts b/packages/app/src/i18n/tr.ts index 8542dff799b..9041e0dd07f 100644 --- a/packages/app/src/i18n/tr.ts +++ b/packages/app/src/i18n/tr.ts @@ -225,6 +225,7 @@ export const dict = { "common.cancel": "İptal", "common.connect": "Bağlan", "common.disconnect": "Bağlantı Kes", + "common.continue": "Gönder", "common.submit": "Gönder", "common.save": "Kaydet", "common.saving": "Kaydediliyor...", diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index e762ba78d9c..cf64ca9b2c5 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -242,6 +242,7 @@ export const dict = { "common.cancel": "取消", "common.connect": "连接", "common.disconnect": "断开连接", + "common.continue": "提交", "common.submit": "提交", "common.save": "保存", "common.saving": "保存中...", diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts index 184c789ce36..02c00d17a22 100644 --- a/packages/app/src/i18n/zht.ts +++ b/packages/app/src/i18n/zht.ts @@ -220,6 +220,7 @@ export const dict = { "common.cancel": "取消", "common.connect": "連線", "common.disconnect": "中斷連線", + "common.continue": "提交", "common.submit": "提交", "common.save": "儲存", "common.saving": "儲存中...",