···11+---
22+name: Feature request
33+about: Suggest an idea for this project
44+title: ''
55+labels: 'enhancement'
66+assignees: ''
77+88+---
99+1010+**Is your feature request related to a problem? Please describe.**
1111+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
1212+1313+**Describe the solution you'd like**
1414+A clear and concise description of what you want to happen.
1515+1616+**Describe alternatives you've considered**
1717+A clear and concise description of any alternative solutions or features you've considered.
1818+1919+**Additional context**
2020+Add any other context or screenshots about the feature request here.
+25-7
README.md
···107107 - requires `.env.dev` file with `INSTANCES_SOCIAL_SECRET_TOKEN` variable set
108108- `npm run sourcemap` - Run `source-map-explorer` on the production build
109109110110-## Self-hosting
111111-112112-This is a **pure static web app**. You can host it anywhere you want. Build it by running `npm run build` (after `npm install`) and serve the `dist` folder.
113113-114114-Try search for "how to self-host static sites" as there are many ways to do it.
115115-116110## Tech stack
117111118112- [Vite](https://vitejs.dev/) - Build tool
···122116- [masto.js](https://github.com/neet/masto.js/) - Mastodon API client
123117- [Iconify](https://iconify.design/) - Icon library
124118 - [MingCute icons](https://www.mingcute.com/)
125125-- Vanilla CSS - *Yes, I'm old school.*
119119+- Vanilla CSS - _Yes, I'm old school._
126120127121Some of these may change in the future. The front-end world is ever-changing.
122122+123123+## Self-hosting
124124+125125+This is a **pure static web app**. You can host it anywhere you want.
126126+127127+Two ways (choose one):
128128+129129+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.
130130+2. Download or `git clone` this repository. Build it by running `npm run build` (after `npm install`). Serve the `dist` folder.
131131+132132+Try search for "how to self-host static sites" as there are many ways to do it.
133133+134134+## Community deployments
135135+136136+These are self-hosted by other wonderful folks.
137137+138138+- [ferengi.one](https://ferengi.one/) by [@david@collantes.social](https://collantes.social/@david)
139139+- [phanpy.blaede.family](https://phanpy.blaede.family/) by [@cassidy@blaede.family](https://mastodon.blaede.family/@cassidy)
140140+- [phanpy.mstdn.mx](https://phanpy.mstdn.mx/) by [@maop@mstdn.mx](https://mstdn.mx/@maop)
141141+- [phanpy.vmst.io](https://phanpy.vmst.io/) by [@vmstan@vmst.io](https://vmst.io/@vmstan)
142142+- [phanpy.gotosocial.social](https://phanpy.gotosocial.social/) by [@admin@gotosocial.social](https://gotosocial.social/@admin)
143143+- [phanpy.bauxite.tech](https://phanpy.bauxite.tech) by [@b4ux1t3@hachyderm.io](https://hachyderm.io/@b4ux1t3)
144144+145145+> Note: Add yours by creating a pull request.
128146129147## Costs
130148
···99import Mentions from '../pages/mentions';
1010import Notifications from '../pages/notifications';
1111import Public from '../pages/public';
1212+import Search from '../pages/search';
1213import Trending from '../pages/trending';
1314import states from '../utils/states';
1415import useTitle from '../utils/useTitle';
···3334 hashtag: Hashtag,
3435 mentions: Mentions,
3536 trending: Trending,
3737+ search: Search,
3638 }[type];
3739 if (!Component) return null;
4040+ // Don't show Search column with no query, for now
4141+ if (type === 'search' && !params.query) return null;
3842 return (
3943 <Component key={type + JSON.stringify(params)} {...params} columnMode />
4044 );
+10-1
src/components/compose.jsx
···2828 getCurrentInstanceConfiguration,
2929} from '../utils/store-utils';
3030import supports from '../utils/supports';
3131+import useCloseWatcher from '../utils/useCloseWatcher';
3132import useInterval from '../utils/useInterval';
3233import visibilityIconsMap from '../utils/visibility-icons-map';
3334···108109// https://github.com/mastodon/mastodon/blob/c03bd2a238741a012aa4b98dc4902d6cf948ab63/app/models/account.rb#L69
109110const USERNAME_RE = /[a-z0-9_]+([a-z0-9_.-]+[a-z0-9_]+)?/i;
110111const MENTION_RE = new RegExp(
111111- `(^|[^=\\/\\w.])(@${USERNAME_RE.source}(?:@[\\p{L}\\w.-]+[\\w]+)?)`,
112112+ `(^|[^=\\/\\w])(@${USERNAME_RE.source}(?:@[\\p{L}\\w.-]+[\\w]+)?)`,
112113 'uig',
113114);
114115···416417 };
417418 useEffect(updateCharCount, []);
418419420420+ const supportsCloseWatcher = window.CloseWatcher;
419421 const escDownRef = useRef(false);
420422 useHotkeys(
421423 'esc',
···424426 // This won't be true if this event is already handled and not propagated 🤞
425427 },
426428 {
429429+ enabled: !supportsCloseWatcher,
427430 enableOnFormTags: true,
428431 },
429432 );
···436439 escDownRef.current = false;
437440 },
438441 {
442442+ enabled: !supportsCloseWatcher,
439443 enableOnFormTags: true,
440444 // Use keyup because Esc keydown will close the confirm dialog on Safari
441445 keyup: true,
···448452 },
449453 },
450454 );
455455+ useCloseWatcher(() => {
456456+ if (!standalone && confirmClose()) {
457457+ onClose();
458458+ }
459459+ }, [standalone, confirmClose, onClose]);
451460452461 const prevBackgroundDraft = useRef({});
453462 const draftKey = () => {