diff --git a/CLAUDE.md b/CLAUDE.md index 968e0b12f..ba401963d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -69,16 +69,20 @@ You are an expert in TypeScript, JavaScript, HTML, SCSS and Teact with deep expe - Add new translations to `src/assets/localization/fallback.strings`. - **After your solution:** - 1. Critique it—identify any shortcomings. - 2. Fix those issues, do more planning. + 1. Think like on a code review and identify any shortcomings. + 2. Fix those issues. Repeat review-fix cycle until you are sure about code quality. 3. Present the improved result. - **When deeper debugging is needed:** - 1. Outline clear, step-by-step debugging instructions for the operator. + 1. Outline clear, step-by-step debugging instructions in your output. 2. Remove any temporary debug code once the issue is resolved. +- **Linter commands** + After finishing your changes, run `npm run check:ts` if you touched TypeScript files and/or `npm run check:css` for SCSS. + If linter reports incorrect import order, try fixing it using command. If it fails, make ONE try to fix it manually and leave it as is. + - **Lint errors you can't fix manually:** - Suggest running `eslint --fix `. + Suggest running `npx eslint --fix `. # Telegram Web API Guide @@ -178,6 +182,7 @@ addActionHandler('loadUser', async (global, actions, { userId }) => { * Only use **useCallback** when you really need to memoize a render function. * Prefer **useFlag()** over `useState()` for simple boolean toggles. * Check the `hooks/` folders for additional utilities. +* Avoid adding new `useEffect` where possible. ### 4. Component Signature > **Migrate** any old `FC` syntax to the new form. @@ -200,6 +205,8 @@ const NewComp = (props: OwnProps & StateProps) => { … } * Call `const lang = useLang()` at the top of your component. * Look up the localization guide for how to add new language keys. +### 7. Icons +* Use `` component for icons. Available icons are listed in `src/types/icons/index.ts` --- ### Example @@ -305,15 +312,15 @@ Global State is our single, app-wide store, similar to Redux or Zustand. All its ### 1. Accessing Global in Components -* **Use** `withGlobal` (a `mapStateToProps` helper) to pull in state. -* There is an experimental `useSelector` API available. -* **Use** `getGlobal` **only** inside hooks for one-off reads (it's non-reactive). +* Prefer existing `withGlobal` (a `mapStateToProps` helper) to pull in state. +* There is an experimental `useSelector` API available. If your value can be retrieved using simple selector and `withGlobal` is not present, use it. +* **Use** `getGlobal` **only** inside callbacks for one-off reads (it's non-reactive). ### 2. Performance * Wrap `withGlobal` in `memo` so the component re-renders only on real data changes. * **Don't** return new arrays or objects inside `withGlobal`; that defeats memoization. -* If you need to filter or map a list, **pass IDs as props** and do the heavy work in a `useMemo` hook. +* If you need to filter or map a list, use `useShallowSelector` to retrieve reactive array and perform computation in `useMemo`. * Force `Complete` return type for `withGlobal` parameter, as it ensures that all defined properties are passed. ### 3. Example Component @@ -381,6 +388,7 @@ lang('MarkdownKey', undefined, { withNodes: true, withMarkdown: true }); **3. Adding a New Key** +0. Make sure key does not exist already. 1. Search Translation Platform for similar strings to get the correct wording. 2. Add it to `fallback.strings`. 3. If it's plural, include `_one` and `_other`. diff --git a/README.md b/README.md index 11d428d13..a42d1d11b 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ npm run dev ### Invoking API from console -Start your dev server and locate GramJS worker in console context. +Start your dev server and locate GramJS worker in the console context. All constructors and functions available in global `GramJs` variable. -Run `npm run gramjs:tl full` to get access to all available Telegram requests. +Run `npm run gramjs:tl full` to get access to all available Telegram methods. Example usage: ``` javascript @@ -42,16 +42,14 @@ await invoke(new GramJs.help.GetAppConfig()) * [fflate](https://github.com/101arrowz/fflate) ([MIT License](https://github.com/101arrowz/fflate/blob/master/LICENSE)) * [cryptography](https://github.com/spalt08/cryptography) ([Apache License 2.0](https://github.com/spalt08/cryptography/blob/master/LICENSE)) * [emoji-data](https://github.com/iamcal/emoji-data) ([MIT License](https://github.com/iamcal/emoji-data/blob/master/LICENSE)) -* [twemoji-parser](https://github.com/twitter/twemoji-parser) ([MIT License](https://github.com/twitter/twemoji-parser/blob/master/LICENSE.md)) +* [twemoji-parser](https://github.com/jdecked/twemoji-parser) ([MIT License](https://github.com/jdecked/twemoji-parser/blob/master/LICENSE.md)) * [rlottie](https://github.com/Samsung/rlottie) ([MIT License](https://github.com/Samsung/rlottie/blob/master/COPYING)) * [opus-recorder](https://github.com/chris-rudmin/opus-recorder) ([Various Licenses](https://github.com/chris-rudmin/opus-recorder/blob/master/LICENSE.md)) * [qr-code-styling](https://github.com/kozakdenys/qr-code-styling) ([MIT License](https://github.com/kozakdenys/qr-code-styling/blob/master/LICENSE)) -* [mp4box](https://github.com/gpac/mp4box.js) ([BSD-3-Clause license](https://github.com/gpac/mp4box.js/blob/master/LICENSE)) -* [music-metadata-browser](https://github.com/Borewit/music-metadata-browser) ([MIT License](https://github.com/Borewit/music-metadata-browser/blob/master/LICENSE.txt)) +* [music-metadata](https://github.com/Borewit/music-metadata) ([MIT License](https://github.com/Borewit/music-metadata/blob/master/LICENSE.txt)) * [lowlight](https://github.com/wooorm/lowlight) ([MIT License](https://github.com/wooorm/lowlight/blob/main/license)) * [idb-keyval](https://github.com/jakearchibald/idb-keyval) ([Apache License 2.0](https://github.com/jakearchibald/idb-keyval/blob/main/LICENCE)) * [fasttextweb](https://github.com/karmdesai/fastTextWeb) -* webp-wasm * fastblur ## Bug reports and Suggestions diff --git a/package.json b/package.json index 362660133..1bfb8dab5 100644 --- a/package.json +++ b/package.json @@ -9,25 +9,39 @@ "scripts": { "dev": "cross-env APP_ENV=development webpack serve --mode development", "dev:mocked": "cross-env APP_ENV=test APP_MOCKED_CLIENT=1 webpack serve --mode development --port 1235", + "build:dev": "webpack --mode development && bash ./deploy/copy_to_dist.sh", "build:staging": "cross-env APP_ENV=staging npm run build:dev", "build:mocked": "cross-env APP_ENV=test APP_MOCKED_CLIENT=1 npm run build:dev", "build:production": "webpack && bash ./deploy/copy_to_dist.sh", + "web:release:production": "npm i && npm run build:production && git add -A && git commit -a -m '[Build]' --no-verify && git push", + "tauri": "tauri", "tauri:dev": "tauri dev", "tauri:build": "tauri build", + "telegraph:update_changelog": "node ./dev/telegraphChangelog.js", - "check": "tsc && stylelint \"**/*.{css,scss}\" --cache --cache-location .cache/.stylelintcache && eslint --cache --cache-location .cache/.eslintcache", - "check:fix": "stylelint \"**/*.{css,scss}\" --fix --cache --cache-location .cache/.stylelintcache && eslint --fix --cache --cache-location .cache/.eslintcache", + + "check:ts": "tsc && eslint --cache --cache-location .cache/.eslintcache", + "check:css": "stylelint \"**/*.{css,scss}\" --cache --cache-location .cache/.stylelintcache", + "fix:ts": "tsc && eslint --cache --cache-location .cache/.eslintcache --fix", + "fix:css": "stylelint \"**/*.{css,scss}\" --cache --cache-location .cache/.stylelintcache --fix", + "check": "npm run check:ts && npm run check:css", + "fix": "npm run fix:ts && npm run fix:css", + "tl:rehash": "node ./dev/tlHash.js", "gramjs:tl": "tsx ./src/lib/gramjs/tl/generateModules.ts", + "lang:ts": "tsx ./dev/generateLangTypes.js", "lang:initial": "tsx ./dev/generateInitialLangFallback.js", + "icons:build": "fantasticon -c .fantasticonrc.cjs", + "test": "cross-env APP_ENV=test jest --verbose --silent --forceExit", "test:playwright": "playwright test", "test:record": "playwright codegen localhost:1235", + "statoscope:validate-diff": "statoscope validate --input input.json --reference reference.json", "postinstall": "node -e \"require('fs').rmSync('.cache', { recursive: true, force: true })\"", "postversion": "echo $(node -p \"require('./package.json').version\") > public/version.txt && git commit --amend --no-verify --no-edit public/version.txt"