/* This file is part of the Notesnook project (https://notesnook.com/) Copyright (C) 2023 Streetwriters (Private) Limited This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ import { Flex, Text } from "@theme-ui/components"; import { appVersion } from "../utils/version"; import Field from "../components/field"; import Dialog from "../components/dialog"; import platform from "platform"; import { useState } from "react"; import { confirm, Perform } from "../common/dialog-controller"; import { isUserPremium } from "../hooks/use-is-user-premium"; import * as clipboard from "clipboard-polyfill/text"; import { store as userstore } from "../stores/user-store"; import { db } from "../common/db"; import { ErrorText } from "../components/error-text"; const PLACEHOLDERS = { title: "Briefly describe what happened", body: `Tell us more about the issue you are facing. For example things like: 1. Steps to reproduce the issue 2. Things you have tried so far 3. etc. This is all optional, of course.` }; type IssueDialogProps = { onClose: Perform; }; function IssueDialog(props: IssueDialogProps) { const [isSubmitting, setIsSubmitting] = useState(false); const [error, setError] = useState(); return ( props.onClose(false)} positiveButton={{ text: "Submit", form: "issueForm", loading: isSubmitting, disabled: isSubmitting }} negativeButton={{ text: "Cancel", onClick: () => props.onClose(false) }} > { e.preventDefault(); try { setIsSubmitting(true); setError(undefined); const formData = new FormData(e.target as HTMLFormElement); const requestData = Object.fromEntries( formData.entries() as IterableIterator<[string, string]> ); if (!requestData.title.trim() || !requestData.body.trim()) return; requestData.body = BODY_TEMPLATE(requestData.body); const url = await db.debug?.report({ title: requestData.title, body: requestData.body, userId: userstore.get().user?.id }); if (!url) throw new Error("Could not submit bug report."); props.onClose(true); await showIssueReportedDialog({ url }); } catch (e) { if (e instanceof Error) setError(e.message); } finally { setIsSubmitting(false); } }} sx={{ flexDirection: "column" }} > Your bug report is public. Do NOT include sensitive information (email, passwords etc) in the issue title or description. {getDeviceInfo() .split("\n") .map((t) => ( <> {t}
))}
); } export default IssueDialog; function showIssueReportedDialog({ url }: { url: string }) { return confirm({ title: "Thank you for reporting!", positiveButtonText: "Copy link", message: `You can track your bug report at [${url}](${url}). Please note that we will respond to your bug report on the link above. **We recommended that you save the above link for later reference.** If your issue is critical (e.g. notes not syncing, crashes etc.), please [join our Discord community](https://discord.com/invite/zQBK97EE22) for one-to-one support.` }).then((result) => { result && clipboard.writeText(url); }); } function getDeviceInfo() { const version = appVersion.formatted; const os = platform.os; const browser = `${platform.name} ${platform.version}`; return `App version: ${version} OS: ${os} Browser: ${browser} Pro: ${isUserPremium()}`; } const BODY_TEMPLATE = (body: string) => { const info = `**Device information:**\n${getDeviceInfo()}`; if (!body) return info; return `${body}\n\n${info}`; };