From f520e30858b9d646040218675d3dcddf3330540d Mon Sep 17 00:00:00 2001 From: Lim Chee Aun Date: Mon, 25 Dec 2023 19:25:48 +0800 Subject: [PATCH] Extend self-hosting variables --- .env | 7 ++-- README.md | 62 ++++++++++++++++++++++++++-- compose/index.html | 2 +- index.html | 12 +++--- scripts/fetch-lingva-languages.js | 5 +-- src/components/translation-block.jsx | 15 +++---- src/pages/login.jsx | 21 +++++++--- src/pages/settings.jsx | 15 ++++++- src/pages/welcome.css | 12 ++++++ src/pages/welcome.jsx | 57 ++++++++++++++++++++----- src/utils/auth.js | 2 +- src/utils/useTitle.js | 2 +- vite.config.js | 17 +++++--- 13 files changed, 179 insertions(+), 50 deletions(-) diff --git a/.env b/.env index 787c8d7e..23232209 100644 --- a/.env +++ b/.env @@ -1,3 +1,4 @@ -VITE_CLIENT_NAME=Phanpy -VITE_CLIENT_ID=social.phanpy -VITE_WEBSITE=https://phanpy.social \ No newline at end of file +PHANPY_CLIENT_NAME=Phanpy +PHANPY_WEBSITE=https://phanpy.social +PHANPY_LINGVA_INSTANCES="lingva.phanpy.social lingva.lunar.icu lingva.garudalinux.org translate.plausibility.cloud" +PHANPY_PRIVACY_POLICY_URL="https://github.com/cheeaun/phanpy/blob/main/PRIVACY.MD" \ No newline at end of file diff --git a/README.md b/README.md index cc438a65..acb243ee 100644 --- a/README.md +++ b/README.md @@ -126,10 +126,66 @@ This is a **pure static web app**. You can host it anywhere you want. Two ways (choose one): -1. (Recommended) Go to [Releases](https://github.com/cheeaun/phanpy/releases) and download the latest `phanpy-dist.zip`. It's pre-built so don't need to run any install/build commands. Extract it. Serve the folder of extracted files. -2. Download or `git clone` this repository. Build it by running `npm run build` (after `npm install`). Serve the `dist` folder. +### Easy way -Try search for "how to self-host static sites" as there are many ways to do it. +Go to [Releases](https://github.com/cheeaun/phanpy/releases) and download the latest `phanpy-dist.zip` or `phanpy-dist.tar.gz`. It's pre-built so don't need to run any install/build commands. Extract it. Serve the folder of extracted files. + +### Custom-build way + +Download or `git clone` this repository. Build it by running `npm run build` (after `npm install`). Serve the `dist` folder. + +Customization can be done by passing environment variables to the build command. Examples: + +```bash +PHANPY_APP_TITLE="Phanpy Dev" \ + PHANPY_WEBSITE="https://dev.phanpy.social" \ + npm run build +``` + +```bash +PHANPY_DEFAULT_INSTANCE=hachyderm.io \ + PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL=https://hachyderm.io/auth/sign_up \ + PHANPY_PRIVACY_POLICY_URL=https://hachyderm.io/privacy-policy \ + npm run build +``` + +It's also possible to set them in the `.env` file. + +Available variables: + +- `PHANPY_APP_TITLE` (optional, default: `Phanpy`) affects: + - Web page title, shown in the browser window or tab title + - App title, when installed as PWA, shown in the Home screen, macOS dock, Windows taskbar, etc + - OpenGraph card title, when shared on social networks + - Client name, when [registering the app for authentication](https://docs.joinmastodon.org/client/token/#app) and shown as client used on posts in some apps/clients +- `PHANPY_WEBSITE` (optional but recommended, default: `https://phanpy.social`) affects: + - Canonical URL of the website + - OpenGraph card URL, when shared on social networks + - Root path for the OpenGraph card image + - Client URL, when [registering the app for authentication](https://docs.joinmastodon.org/client/token/#app) and shown as client used on posts in some apps/clients +- `PHANPY_DEFAULT_INSTANCE` (optional, no defaults): + - e.g. 'mastodon.social', without `https://` + - Default instance for log-in + - When logging in, the user will be redirected instantly to the instance's authentication page instead of having to manually type the instance URL and submit +- `PHANPY_DEFAULT_INSTANCE_REGISTRATION_URL` (optional, no defaults): + - URL of the instance registration page + - E.g. `https://mastodon.social/auth/sign_up` +- `PHANPY_PRIVACY_POLICY_URL` (optional, default to official instance's privacy policy): + - URL of the privacy policy page + - May specify the instance's own privacy policy +- `PHANPY_LINGVA_INSTANCES` (optional, space-separated list, default: `lingva.phanpy.social [...hard-coded list of fallback instances]`): + - Specify a space-separated list of instances. First will be used as default before falling back to the subsequent instances. If there's only 1 instance, means no fallback. + - May specify a self-hosted Lingva instance, powered by either [lingva-translate](https://github.com/thedaviddelta/lingva-translate) or [lingva-api](https://github.com/cheeaun/lingva-api) + - List of fallback instances hard-coded in `/.env` + - [↗️ List of lingva-translate instances](https://github.com/thedaviddelta/lingva-translate?tab=readme-ov-file#instances) + +### Static site hosting + +Try online search for "how to self-host static sites" as there are many ways to do it. + +#### Lingva-translate or lingva-api hosting + +See documentation for [lingva-translate](https://github.com/thedaviddelta/lingva-translate) or [lingva-api](https://github.com/cheeaun/lingva-api). ## Community deployments diff --git a/compose/index.html b/compose/index.html index c4b3d5a1..53fdf971 100644 --- a/compose/index.html +++ b/compose/index.html @@ -4,7 +4,7 @@ - Compose / %VITE_CLIENT_NAME% + Compose / %PHANPY_CLIENT_NAME% diff --git a/index.html b/index.html index 44108ff5..35bb3e02 100644 --- a/index.html +++ b/index.html @@ -6,7 +6,7 @@ name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> - %VITE_CLIENT_NAME% + %PHANPY_CLIENT_NAME% - + - + - - + + - +
diff --git a/scripts/fetch-lingva-languages.js b/scripts/fetch-lingva-languages.js index f270cabe..e4bed3f1 100644 --- a/scripts/fetch-lingva-languages.js +++ b/scripts/fetch-lingva-languages.js @@ -1,7 +1,6 @@ -// Fetch https://lingva.ml/api/v1/languages/{source|target} import fs from 'fs'; -fetch('https://lingva.ml/api/v1/languages/source') +fetch('https://lingva.phanpy.social/api/v1/languages/source') .then((response) => response.json()) .then((json) => { const file = './src/data/lingva-source-languages.json'; @@ -9,7 +8,7 @@ fetch('https://lingva.ml/api/v1/languages/source') fs.writeFileSync(file, JSON.stringify(json.languages, null, '\t'), 'utf8'); }); -fetch('https://lingva.ml/api/v1/languages/target') +fetch('https://lingva.phanpy.social/api/v1/languages/target') .then((response) => response.json()) .then((json) => { const file = './src/data/lingva-target-languages.json'; diff --git a/src/components/translation-block.jsx b/src/components/translation-block.jsx index 62cb7a56..588ee1f9 100644 --- a/src/components/translation-block.jsx +++ b/src/components/translation-block.jsx @@ -12,19 +12,16 @@ import pmem from '../utils/pmem'; import Icon from './icon'; import Loader from './loader'; +const { PHANPY_LINGVA_INSTANCES } = import.meta.env; +const LINGVA_INSTANCES = PHANPY_LINGVA_INSTANCES + ? PHANPY_LINGVA_INSTANCES.split(/\s+/) + : []; + const throttle = pThrottle({ limit: 1, interval: 2000, }); -// Using other API instances instead of lingva.ml because of this bug (slashes don't work): -// https://github.com/thedaviddelta/lingva-translate/issues/68 -const LINGVA_INSTANCES = [ - 'lingva.phanpy.social', - 'lingva.lunar.icu', - 'lingva.garudalinux.org', - 'translate.plausibility.cloud', -]; let currentLingvaInstance = 0; function _lingvaTranslate(text, source, target) { @@ -243,4 +240,4 @@ function TranslationBlock({ ); } -export default TranslationBlock; +export default LINGVA_INSTANCES?.length ? TranslationBlock : () => null; diff --git a/src/pages/login.jsx b/src/pages/login.jsx index 307fb112..a7981510 100644 --- a/src/pages/login.jsx +++ b/src/pages/login.jsx @@ -12,6 +12,8 @@ import { getAuthorizationURL, registerApplication } from '../utils/auth'; import store from '../utils/store'; import useTitle from '../utils/useTitle'; +const { PHANPY_DEFAULT_INSTANCE: DEFAULT_INSTANCE } = import.meta.env; + function Login() { useTitle('Log in'); const instanceURLRef = useRef(); @@ -19,6 +21,7 @@ function Login() { const [uiState, setUIState] = useState('default'); const [searchParams] = useSearchParams(); const instance = searchParams.get('instance'); + const submit = searchParams.get('submit'); const [instanceText, setInstanceText] = useState( instance || cachedInstanceURL?.toLowerCase() || '', ); @@ -129,6 +132,12 @@ function Login() { submitInstance(selectedInstanceText); }; + if (submit) { + useEffect(() => { + submitInstance(instance || selectedInstanceText); + }, []); + } + return (
@@ -200,11 +209,13 @@ function Login() {