diff --git a/.github/DISCUSSION_TEMPLATE/issue-triage.yml b/.github/DISCUSSION_TEMPLATE/issue-triage.yml index 6d154d323..064553259 100644 --- a/.github/DISCUSSION_TEMPLATE/issue-triage.yml +++ b/.github/DISCUSSION_TEMPLATE/issue-triage.yml @@ -57,7 +57,7 @@ body: required: true - type: textarea attributes: - label: Environement + label: Environment description: | Please provide information about your environment. Include the following: - OS: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..331e0a7c3 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +### Description + + + +Fixes # + +### Checklist: + +- [ ] I have read and understood the [Contribution policy](https://github.com/ajbura/cinny/blob/dev/CONTRIBUTING.md). diff --git a/.prettierignore b/.prettierignore index bc876b6c9..e0aa18a15 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,5 +2,4 @@ dist node_modules package.json package-lock.json -LICENSE -README.md \ No newline at end of file +LICENSE \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 5772e56dd..c09f78614 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,7 @@ RUN npm run build ## App -FROM nginx:1.29.8-alpine +FROM nginx:1.31.5-alpine COPY --from=builder /src/dist /app COPY --from=builder /src/docker-nginx.conf /etc/nginx/conf.d/default.conf diff --git a/HACKING.md b/HACKING.md new file mode 100644 index 000000000..30c4960f9 --- /dev/null +++ b/HACKING.md @@ -0,0 +1,60 @@ +# Developing Cinny + +> [!TIP] +> We recommend using a version manager as versions change very quickly. +> You will likely need to switch between multiple Node.js versions based +> on the needs of different projects you're working on. [NVM-windows] +> on Windows and [nvm] on Linux/macOS are pretty good choices. Recommended +> nodejs version is Krypton LTS (v24.13.1). + +[nvm-windows]: https://github.com/coreybutler/nvm-windows#installation--upgrades +[nvm]: https://github.com/nvm-sh/nvm + +Execute the following commands to start a development server: + +```sh +npm ci # Installs all dependencies +npm start # Serve a development version +``` + +To build the app: + +```sh +npm run build # Compiles the app into the dist/ directory +``` + +To commit changes: + +```sh +npm run commit +``` + +## Running with Docker + +This repository includes a Dockerfile, which builds the application from +source and serves it with Nginx on port 80. To use this locally, you can +build the container like so: + +``` +docker build -t cinny:latest . +``` + +You can then run the container you've built with a command similar to this: + +``` +docker run -p 8080:80 cinny:latest +``` + +This will forward your `localhost` port 8080 to the container's port 80. +You can visit the app in your browser by navigating to `http://localhost:8080`. + +## Code formatting + +We use [ESLint](https://eslint.org/) for clean and stylistically +consistent code syntax, so make sure your pull request follow it. + +## Helpful links + +- [BEM methodology](http://getbem.com/introduction/) +- [Atomic design](https://bradfrost.com/blog/post/atomic-web-design/) +- [Matrix JavaScript SDK documentation](https://matrix-org.github.io/matrix-js-sdk/index.html) diff --git a/README.md b/README.md index 4223daedb..0c1a9764a 100644 --- a/README.md +++ b/README.md @@ -129,12 +129,12 @@ Lotus Chat has a desktop app for Windows, macOS, and Linux. It wraps the same we ### Download -Operating System | Download ----|--- -Windows | [Get the installer (.exe)](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64-setup.exe) -Linux (AppImage, any distro) | [Get the AppImage](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.AppImage) -Linux (Debian/Ubuntu) | [Get the .deb](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.deb) -Linux (Arch/CachyOS/EndeavourOS) | [Get the .pkg.tar.zst](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.pkg.tar.zst) — install with `pacman -U LotusChat-x86_64.pkg.tar.zst` +| Operating System | Download | +| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Windows | [Get the installer (.exe)](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64-setup.exe) | +| Linux (AppImage, any distro) | [Get the AppImage](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.AppImage) | +| Linux (Debian/Ubuntu) | [Get the .deb](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.deb) | +| Linux (Arch/CachyOS/EndeavourOS) | [Get the .pkg.tar.zst](https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest/LotusChat-x86_64.pkg.tar.zst) — install with `pacman -U LotusChat-x86_64.pkg.tar.zst` | All Linux builds need `webkit2gtk-4.1` and, for calls to work, GStreamer's `good`/`bad`/`ugly`/`libav` plugin sets (the pacman package pulls these in automatically; on the AppImage/.deb, install them via your package manager if joining a call shows "browser does not support WebRTC"). diff --git a/contrib/nginx/README.md b/contrib/nginx/README.md index d90225010..fc7a74027 100644 --- a/contrib/nginx/README.md +++ b/contrib/nginx/README.md @@ -3,6 +3,7 @@ ## Insert wasm type into nginx mime.types file so they load correctly. `/etc/nginx/mime.types`: + ``` types { .. diff --git a/dev/oidc-test/README.md b/dev/oidc-test/README.md index 68dbd3b9c..aa1c7cf68 100644 --- a/dev/oidc-test/README.md +++ b/dev/oidc-test/README.md @@ -39,6 +39,7 @@ services: ``` ### 1a. MAS `config.yaml` — the parts that matter + After `config generate` (which fills in `secrets.keys` + `encryption`), set: ```yaml @@ -48,18 +49,19 @@ http: database: uri: postgresql://synapse:pw@postgres/synapse matrix: - homeserver: localhost # the server_name + homeserver: localhost # the server_name endpoint: http://synapse:8008/ - secret: "REPLACE_WITH_A_LONG_SHARED_ADMIN_TOKEN" + secret: 'REPLACE_WITH_A_LONG_SHARED_ADMIN_TOKEN' clients: - - client_id: "0000000000000000000SYNAPSE" + - client_id: '0000000000000000000SYNAPSE' client_auth_method: client_secret_basic - client_secret: "REPLACE_WITH_A_SHARED_CLIENT_SECRET" -passwords: # so you can create a local test account in the MAS UI + client_secret: 'REPLACE_WITH_A_SHARED_CLIENT_SECRET' +passwords: # so you can create a local test account in the MAS UI enabled: true ``` ### 1b. Synapse `homeserver.yaml` — delegate auth to MAS + See `synapse-msc3861.yaml` in this folder; the key block is: ```yaml @@ -67,17 +69,18 @@ experimental_features: msc3861: enabled: true issuer: http://localhost:8090/ - client_id: "0000000000000000000SYNAPSE" + client_id: '0000000000000000000SYNAPSE' client_auth_method: client_secret_basic - client_secret: "REPLACE_WITH_A_SHARED_CLIENT_SECRET" # == MAS clients[].client_secret - admin_token: "REPLACE_WITH_A_LONG_SHARED_ADMIN_TOKEN" # == MAS matrix.secret - account_management_url: "http://localhost:8090/account" + client_secret: 'REPLACE_WITH_A_SHARED_CLIENT_SECRET' # == MAS clients[].client_secret + admin_token: 'REPLACE_WITH_A_LONG_SHARED_ADMIN_TOKEN' # == MAS matrix.secret + account_management_url: 'http://localhost:8090/account' ``` Create a test user via the MAS UI (`http://localhost:8090/`) or `docker compose exec mas mas-cli manage register-user`. Sanity check discovery (the client relies on this): + ```bash curl -s http://localhost:8008/.well-known/matrix/client | jq '."m.authentication"' # -> { "issuer": "http://localhost:8090/", "account": "http://localhost:8090/account" } @@ -108,5 +111,6 @@ See **section N** of `../../LOTUS_TESTING.md` for the actual pass/fail steps revocation, account-management link, and the non-OIDC-regression check). ## Files here + - `synapse-msc3861.yaml` — the Synapse experimental-features delta. - `config.local.json` — the Lotus `public/config.json` override. diff --git a/package-lock.json b/package-lock.json index 507644f91..7fa26506d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lotus-chat", - "version": "4.12.3-lotus", + "version": "4.12.7-lotus", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lotus-chat", - "version": "4.12.3-lotus", + "version": "4.12.7-lotus", "hasInstallScript": true, "license": "AGPL-3.0-only", "dependencies": { diff --git a/package.json b/package.json index 1dcdfe318..0fe6bfd92 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lotus-chat", - "version": "4.12.3-lotus", + "version": "4.12.7-lotus", "description": "Lotus Chat — Matrix client for Lotus Guild", "main": "index.js", "type": "module", diff --git a/src/app/components/editor/utils.ts b/src/app/components/editor/utils.ts index 15122cb8e..e4006c059 100644 --- a/src/app/components/editor/utils.ts +++ b/src/app/components/editor/utils.ts @@ -268,15 +268,15 @@ export const getPointUntilChar = ( return targetPoint; }; -export const getPrevWorldRange = (editor: Editor): BaseRange | undefined => { +export const getPrevWordRange = (editor: Editor): BaseRange | undefined => { const { selection } = editor; if (!selection || !Range.isCollapsed(selection)) return undefined; const [cursorPoint] = Range.edges(selection); - const worldStartPoint = getPointUntilChar(editor, cursorPoint, { + const wordStartPoint = getPointUntilChar(editor, cursorPoint, { reverse: true, - match: (char) => char === ' ', + match: (char) => char === ' ' || char === '', }); - return worldStartPoint && Editor.range(editor, worldStartPoint, cursorPoint); + return wordStartPoint && Editor.range(editor, wordStartPoint, cursorPoint); }; export const isEmptyEditor = (editor: Editor): boolean => { diff --git a/src/app/features/room/RoomInput.tsx b/src/app/features/room/RoomInput.tsx index 6dcdd03ec..bfa21ce61 100644 --- a/src/app/features/room/RoomInput.tsx +++ b/src/app/features/room/RoomInput.tsx @@ -44,7 +44,7 @@ import { AutocompletePrefix, AutocompleteQuery, getAutocompleteQuery, - getPrevWorldRange, + getPrevWordRange, resetEditor, RoomMentionAutocomplete, UserMentionAutocomplete, @@ -806,7 +806,7 @@ export const RoomInput = forwardRef( sendTypingStatus(!isEmptyEditor(editor)); } - const prevWordRange = getPrevWorldRange(editor); + const prevWordRange = getPrevWordRange(editor); const query = prevWordRange ? getAutocompleteQuery(editor, prevWordRange, AUTOCOMPLETE_PREFIXES) : undefined; diff --git a/src/app/features/room/message/MessageEditor.tsx b/src/app/features/room/message/MessageEditor.tsx index 45177867e..3281cab95 100644 --- a/src/app/features/room/message/MessageEditor.tsx +++ b/src/app/features/room/message/MessageEditor.tsx @@ -35,7 +35,7 @@ import { createEmoticonElement, customHtmlEqualsPlainText, getAutocompleteQuery, - getPrevWorldRange, + getPrevWordRange, htmlToEditorInput, moveCursor, plainToEditorInput, @@ -281,7 +281,7 @@ export const MessageEditor = as<'div', MessageEditorProps>( return; } - const prevWordRange = getPrevWorldRange(editor); + const prevWordRange = getPrevWordRange(editor); const query = prevWordRange ? getAutocompleteQuery(editor, prevWordRange, AUTOCOMPLETE_PREFIXES) : undefined; diff --git a/src/app/hooks/useAccountManagement.ts b/src/app/hooks/useAccountManagement.ts index b5f0f4ee8..e3aeb469f 100644 --- a/src/app/hooks/useAccountManagement.ts +++ b/src/app/hooks/useAccountManagement.ts @@ -4,9 +4,9 @@ export const useAccountManagementActions = () => { const actions = useMemo( () => ({ profile: 'org.matrix.profile', - sessionsList: 'org.matrix.sessions_list', - sessionView: 'org.matrix.session_view', - sessionEnd: 'org.matrix.session_end', + sessionsList: 'org.matrix.devices_list', + sessionView: 'org.matrix.device_view', + sessionEnd: 'org.matrix.device_delete', accountDeactivate: 'org.matrix.account_deactivate', crossSigningReset: 'org.matrix.cross_signing_reset', }),