import { createSignal, onMount, onCleanup, Show } from "solid-js"; import { useSearchParams } from "@solidjs/router"; import { Title, Meta } from "@solidjs/meta"; import { A } from "@solidjs/router"; import { api } from "~/lib/api"; import GitHub from "~/components/icons/GitHub"; import LinkedIn from "~/components/icons/LinkedIn"; import { getClientCookie, setClientCookie } from "~/lib/cookies.client"; import CountdownCircleTimer from "~/components/CountdownCircleTimer"; import LoadingSpinner from "~/components/LoadingSpinner"; import RevealDropDown from "~/components/RevealDropDown"; import type { UserProfile } from "~/types/user"; export default function ContactPage() { const [searchParams] = useSearchParams(); const viewer = () => searchParams.viewer ?? "default"; const [countDown, setCountDown] = createSignal(0); const [emailSent, setEmailSent] = createSignal(false); const [error, setError] = createSignal(""); const [loading, setLoading] = createSignal(false); const [user, setUser] = createSignal(null); let timerIdRef: ReturnType | null = null; const calcRemainder = (timer: string) => { const expires = new Date(timer); const remaining = expires.getTime() - Date.now(); const remainingInSeconds = remaining / 1000; if (remainingInSeconds <= 0) { setCountDown(0); if (timerIdRef !== null) { clearInterval(timerIdRef); } } else { setCountDown(remainingInSeconds); } }; onMount(() => { // Check for existing timer const timer = getClientCookie("contactRequestSent"); if (timer) { timerIdRef = setInterval(() => calcRemainder(timer), 1000); } // Fetch user data if authenticated api.user.getProfile .query() .then((userData) => { if (userData) { setUser(userData); } }) .catch(() => { // User not authenticated, no problem }); onCleanup(() => { if (timerIdRef !== null) { clearInterval(timerIdRef); } }); }); const sendEmailTrigger = async (e: Event) => { e.preventDefault(); const formData = new FormData(e.target as HTMLFormElement); const name = formData.get("name") as string; const email = formData.get("email") as string; const message = formData.get("message") as string; if (name && email && message) { setLoading(true); try { const res = await api.misc.sendContactRequest.mutate({ name, email, message }); if (res.message === "email sent") { setEmailSent(true); setError(""); const timer = getClientCookie("contactRequestSent"); if (timer) { if (timerIdRef !== null) { clearInterval(timerIdRef); } timerIdRef = setInterval(() => calcRemainder(timer), 1000); } } } catch (err: any) { setError(err.message || "An error occurred"); setEmailSent(false); } setLoading(false); } }; const LineageQuestionsDropDown = () => { return (
Feel free to use the form{" "} {viewer() === "lineage" ? "below" : "above"}, I will respond as quickly as possible, however, you may find an answer to your question in the following.
    1. Personal Information
    You can find the entire privacy policy{" "} here .
    2. Remote Backups
    Life and Lineage uses a per-user database approach for its remote storage, this provides better separation of users and therefore privacy, and it makes requesting the removal of your data simpler, you can even request the database dump if you so choose. This isn't particularly expensive, but not free for n users, so use of this feature requires a purchase of an IAP(in-app purchase) - this can be the specific IAP for the remote save feature, and any other IAP will also unlock this feature.
    3. Cross Device Play
    You can use the above mentioned remote-backups to save progress between devices/platforms.
    4. Online Requirements
    Currently, the only time you need to be online is for remote save access. There are plans for pvp, which will require an internet connection, but this is not implemented at time of writing.
    5. Microtransactions
    Microtransactions are not required to play or complete the game, the game can be fully completed without spending any money, however 2 of the classes(necromancer and ranger) are pay-walled. Microtransactions are supported cross-platform, so no need to pay for each device, you simply need to login to your gmail/apple/email account. This would require first creating a character, signing in under options{">"}remote backups first.
); }; const renderTime = (time: number) => { return (
{time.toFixed(0)}
); }; return ( <> Contact | Michael Freno
Contact
(for this website or any of my apps...)