diff --git a/.env b/.env new file mode 100644 index 00000000..ca82edf5 --- /dev/null +++ b/.env @@ -0,0 +1,5 @@ +MAIN_VITE_API_URL=https://hydra-api-us-east-1.losbroxas.org +MAIN_VITE_AUTH_URL=https://auth.hydralauncher.gg +MAIN_VITE_CHECKOUT_URL=https://checkout.hydralauncher.gg +MAIN_VITE_EXTERNAL_RESOURCES_URL=https://assets.hydralauncher.gg +RENDERER_VITE_EXTERNAL_RESOURCES_URL=https://assets.hydralauncher.gg diff --git a/.env.example b/.env.example deleted file mode 100644 index 3ef399f7..00000000 --- a/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -MAIN_VITE_API_URL=API_URL -MAIN_VITE_AUTH_URL=AUTH_URL diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1 @@ + diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml new file mode 100644 index 00000000..11b2e355 --- /dev/null +++ b/.github/workflows/manual.yml @@ -0,0 +1,32 @@ +# This is a basic workflow that is manually triggered + +name: Manual workflow + +# Controls when the action will run. Workflow runs when manually triggered using the UI +# or API. +on: + workflow_dispatch: + # Inputs the workflow accepts. + inputs: + name: + # Friendly description to be shown in the UI instead of 'name' + description: 'Person to greet' + # Default value if no value is explicitly provided + default: 'World' + # Input has to be provided for the workflow to run + required: true + # The data type of the input + type: string + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "greet" + greet: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Runs a single command using the runners shell + - name: Send greeting + run: echo "Hello ${{ inputs.name }}" diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index f1e85019..ac59bc11 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -231,6 +231,7 @@ "options": "Manage" }, "settings": { + "username": "Username", "downloads_path": "Downloads path", "change": "Update", "notifications": "Notifications", diff --git a/src/locales/es/translation.json b/src/locales/es/translation.json index 27e18f34..c463a94a 100644 --- a/src/locales/es/translation.json +++ b/src/locales/es/translation.json @@ -225,6 +225,7 @@ "options": "Gestionar" }, "settings": { + "username": "Nombre de usuario", "downloads_path": "Ruta de descarga", "change": "Cambiar", "notifications": "Notificaciones", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index 0cefd188..3299b3f1 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -221,6 +221,7 @@ "options": "Gerenciar" }, "settings": { + "username": "Nome de usuário", "downloads_path": "Diretório dos downloads", "change": "Explorar...", "notifications": "Notificações", diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json index c2aa40ce..9123326f 100644 --- a/src/locales/ru/translation.json +++ b/src/locales/ru/translation.json @@ -229,6 +229,7 @@ "options": "Управлять" }, "settings": { + "username": "Имя пользователя", "downloads_path": "Путь загрузок", "change": "Изменить", "notifications": "Уведомления", diff --git a/src/renderer/src/pages/settings/settings-account.tsx b/src/renderer/src/pages/settings/settings-account.tsx index 9cf35541..9141c6ab 100644 --- a/src/renderer/src/pages/settings/settings-account.tsx +++ b/src/renderer/src/pages/settings/settings-account.tsx @@ -1,255 +1,255 @@ -import { Avatar, Button, SelectField } from "@renderer/components"; -import { Controller, useForm } from "react-hook-form"; -import { useTranslation } from "react-i18next"; -import { useDate, useToast, useUserDetails } from "@renderer/hooks"; -import { useCallback, useContext, useEffect, useState } from "react"; -import { - CloudIcon, - KeyIcon, - MailIcon, - XCircleFillIcon, -} from "@primer/octicons-react"; -import { settingsContext } from "@renderer/context"; -import { AuthPage } from "@shared"; -import "./settings-account.scss"; - -interface FormValues { - profileVisibility: "PUBLIC" | "FRIENDS" | "PRIVATE"; -} - -export function SettingsAccount() { - const { t } = useTranslation("settings"); - - const [isUnblocking, setIsUnblocking] = useState(false); - - const { showSuccessToast } = useToast(); - - const { blockedUsers, fetchBlockedUsers } = useContext(settingsContext); - - const { formatDate } = useDate(); - - const { - control, - formState: { isSubmitting }, - setValue, - handleSubmit, - } = useForm(); - - const { - userDetails, - hasActiveSubscription, - patchUser, - fetchUserDetails, - updateUserDetails, - unblockUser, - } = useUserDetails(); - - useEffect(() => { - if (userDetails?.profileVisibility) { - setValue("profileVisibility", userDetails.profileVisibility); - } - }, [userDetails, setValue]); - - useEffect(() => { - const unsubscribe = window.electron.onAccountUpdated(() => { - fetchUserDetails().then((response) => { - if (response) { - updateUserDetails(response); - } - }); - showSuccessToast(t("account_data_updated_successfully")); - }); - - return () => { - unsubscribe(); - }; - }, [fetchUserDetails, updateUserDetails, t, showSuccessToast]); - - const visibilityOptions = [ - { value: "PUBLIC", label: t("public") }, - { value: "FRIENDS", label: t("friends_only") }, - { value: "PRIVATE", label: t("private") }, - ]; - - const onSubmit = async (values: FormValues) => { - await patchUser(values); - showSuccessToast(t("changes_saved")); - }; - - const handleUnblockClick = useCallback( - (id: string) => { - setIsUnblocking(true); - - unblockUser(id) - .then(() => { - fetchBlockedUsers(); - showSuccessToast(t("user_unblocked")); - }) - .finally(() => { - setIsUnblocking(false); - }); - }, - [unblockUser, fetchBlockedUsers, t, showSuccessToast] - ); - - const getHydraCloudSectionContent = () => { - const hasSubscribedBefore = Boolean(userDetails?.subscription?.expiresAt); - const isRenewalActive = userDetails?.subscription?.status === "active"; - - if (!hasSubscribedBefore) { - return { - description: {t("no_subscription")}, - callToAction: t("become_subscriber"), - }; - } - - if (hasActiveSubscription) { - return { - description: isRenewalActive ? ( - <> - - {t("subscription_renews_on", { - date: formatDate(userDetails.subscription!.expiresAt!), - })} - - {t("bill_sent_until")} - - ) : ( - <> - {t("subscription_renew_cancelled")} - - {t("subscription_active_until", { - date: formatDate(userDetails!.subscription!.expiresAt!), - })} - - - ), - callToAction: t("manage_subscription"), - }; - } - - return { - description: ( - - {t("subscription_expired_at", { - date: formatDate(userDetails!.subscription!.expiresAt!), - })} - - ), - callToAction: t("renew_subscription"), - }; - }; - - if (!userDetails) return null; - - return ( -
- { - const handleChange = ( - event: React.ChangeEvent - ) => { - field.onChange(event); - handleSubmit(onSubmit)(); - }; - - return ( -
- ({ - key: visiblity.value, - value: visiblity.value, - label: visiblity.label, - }))} - disabled={isSubmitting} - /> - - {t("profile_visibility_description")} -
- ); - }} - /> - -
-

{t("current_email")}

-

{userDetails?.email ?? t("no_email_account")}

- -
- - - -
-
- -
-

Hydra Cloud

-
- {getHydraCloudSectionContent().description} -
- - -
- -
-

{t("blocked_users")}

- - {blockedUsers.length > 0 ? ( -
    - {blockedUsers.map((user) => { - return ( -
  • -
    - - {user.displayName} -
    - - -
  • - ); - })} -
- ) : ( - {t("no_users_blocked")} - )} -
- - ); -} +import { Avatar, Button, SelectField } from "@renderer/components"; +import { Controller, useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; +import { useDate, useToast, useUserDetails } from "@renderer/hooks"; +import { useCallback, useContext, useEffect, useState } from "react"; +import { + CloudIcon, + KeyIcon, + MailIcon, + XCircleFillIcon, +} from "@primer/octicons-react"; +import { settingsContext } from "@renderer/context"; +import { AuthPage } from "@shared"; +import "./settings-account.scss"; + +interface FormValues { + profileVisibility: "PUBLIC" | "FRIENDS" | "PRIVATE"; +} + +export function SettingsAccount() { + const { t } = useTranslation("settings"); + + const [isUnblocking, setIsUnblocking] = useState(false); + + const { showSuccessToast } = useToast(); + + const { blockedUsers, fetchBlockedUsers } = useContext(settingsContext); + + const { formatDate } = useDate(); + + const { + control, + formState: { isSubmitting }, + setValue, + handleSubmit, + } = useForm(); + + const { + userDetails, + hasActiveSubscription, + patchUser, + fetchUserDetails, + updateUserDetails, + unblockUser, + } = useUserDetails(); + + useEffect(() => { + if (userDetails?.profileVisibility) { + setValue("profileVisibility", userDetails.profileVisibility); + } + }, [userDetails, setValue]); + + useEffect(() => { + const unsubscribe = window.electron.onAccountUpdated(() => { + fetchUserDetails().then((response) => { + if (response) { + updateUserDetails(response); + } + }); + showSuccessToast(t("account_data_updated_successfully")); + }); + + return () => { + unsubscribe(); + }; + }, [fetchUserDetails, updateUserDetails, t, showSuccessToast]); + + const visibilityOptions = [ + { value: "PUBLIC", label: t("public") }, + { value: "FRIENDS", label: t("friends_only") }, + { value: "PRIVATE", label: t("private") }, + ]; + + const onSubmit = async (values: FormValues) => { + await patchUser(values); + showSuccessToast(t("changes_saved")); + }; + + const handleUnblockClick = useCallback( + (id: string) => { + setIsUnblocking(true); + + unblockUser(id) + .then(() => { + fetchBlockedUsers(); + showSuccessToast(t("user_unblocked")); + }) + .finally(() => { + setIsUnblocking(false); + }); + }, + [unblockUser, fetchBlockedUsers, t, showSuccessToast] + ); + + const getHydraCloudSectionContent = () => { + const hasSubscribedBefore = Boolean(userDetails?.subscription?.expiresAt); + const isRenewalActive = userDetails?.subscription?.status === "active"; + + if (!hasSubscribedBefore) { + return { + description: {t("no_subscription")}, + callToAction: t("become_subscriber"), + }; + } + + if (hasActiveSubscription) { + return { + description: isRenewalActive ? ( + <> + + {t("subscription_renews_on", { + date: formatDate(userDetails.subscription!.expiresAt!), + })} + + {t("bill_sent_until")} + + ) : ( + <> + {t("subscription_renew_cancelled")} + + {t("subscription_active_until", { + date: formatDate(userDetails!.subscription!.expiresAt!), + })} + + + ), + callToAction: t("manage_subscription"), + }; + } + + return { + description: ( + + {t("subscription_expired_at", { + date: formatDate(userDetails!.subscription!.expiresAt!), + })} + + ), + callToAction: t("renew_subscription"), + }; + }; + + if (!userDetails) return null; + + return ( +
+ { + const handleChange = ( + event: React.ChangeEvent + ) => { + field.onChange(event); + handleSubmit(onSubmit)(); + }; + + return ( +
+ ({ + key: visibility.value, + value: visibility.value, + label: visibility.label, + }))} + disabled={isSubmitting} + /> + + {t("profile_visibility_description")} +
+ ); + }} + /> + +
+

{t("current_email")}

+

{userDetails?.email ?? t("no_email_account")}

+

{t("username")}:

+

{userDetails?.username}

+
+ + + +
+
+
+

Hydra Cloud

+
+ {getHydraCloudSectionContent().description} +
+ + +
+ +
+

{t("blocked_users")}

+ + {blockedUsers.length > 0 ? ( +
    + {blockedUsers.map((user) => { + return ( +
  • +
    + + {user.displayName} +
    + + +
  • + ); + })} +
+ ) : ( + {t("no_users_blocked")} + )} +
+ + ); +}