| 1 | /** |
| 2 | * What a person hears of from one repository: subscribing to one of its |
| 3 | * issues or pull requests (`intent` subscribe, unsubscribe, ignore or |
| 4 | * default, with its `number`), and watching it (`intent` watch, with |
| 5 | * `level` and, for custom, the `event` kinds). Posted by the sidebar's |
| 6 | * Notifications box and the header's Watch menu (components/notifications.tsx). |
| 7 | * Only someone who can read the repository may choose. |
| 8 | */ |
| 9 | import { data } from "react-router"; |
| 10 | |
| 11 | import type { Route } from "./+types/notifications"; |
| 12 | import { subscriptionFromForm, watchFromForm } from "../../lib/inbox"; |
| 13 | import { inbox, repos } from "../../lib/services.server"; |
| 14 | import { assertSameOrigin, requireUser } from "../../lib/session.server"; |
| 15 | |
| 16 | export async function action({ request, params, context }: Route.ActionArgs) { |
| 17 | assertSameOrigin(request); |
| 18 | const user = requireUser(context, request); |
| 19 | const form = await request.formData(); |
| 20 | const repo = await repos.get({ namespace: params.owner, name: params.repo }, user); |
| 21 | if (!repo.ok) return data({ error: "That repository could not be found." }, { status: 404 }); |
| 22 | const path = `${repo.value.namespace}/${repo.value.name}`; |
| 23 | try { |
| 24 | if (form.get("intent") === "watch") { |
| 25 | const watch = watchFromForm(form); |
| 26 | if (!watch) return data({ error: "Choose how to watch it." }, { status: 400 }); |
| 27 | // Participating is the default: no choice to keep. |
| 28 | const level = watch.level === "participating" ? null : watch.level; |
| 29 | return { error: null, watching: await inbox.watch(user.username, repo.value.id, path, level, watch.events) }; |
| 30 | } |
| 31 | const choice = subscriptionFromForm(form); |
| 32 | const number = Number(form.get("number")); |
| 33 | if (!choice || !Number.isInteger(number) || number < 1) return data({ error: "Nothing to do." }, { status: 400 }); |
| 34 | const subscription = await inbox.subscribe(user, { repoId: repo.value.id, number }, choice.subscribed, choice.ignored); |
| 35 | if (!subscription) return data({ error: "That issue or pull request could not be found." }, { status: 404 }); |
| 36 | return { error: null, subscription }; |
| 37 | } catch { |
| 38 | return data({ error: "That did not save. Try again in a moment." }, { status: 503 }); |
| 39 | } |
| 40 | } |