forked from github/cinny
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a33e8db9a3 | ||
|
|
fb76e3ecb4 | ||
|
|
3d79293167 | ||
|
|
74745edcda | ||
|
|
0812131a97 | ||
|
|
1068bba5c7 | ||
|
|
1b5e58a3b4 | ||
|
|
acae043f31 | ||
|
|
b4299f8f37 | ||
|
|
b6adac6714 | ||
|
|
1c8f203164 | ||
|
|
0c30ece281 | ||
|
|
4e559e56d4 | ||
|
|
19f28b40ac | ||
|
|
bcaf43a540 | ||
|
|
9c7b635e7e | ||
|
|
65c87dff3a | ||
|
|
132a76df27 | ||
|
|
b0954eeddc | ||
|
|
8f1add6059 | ||
|
|
8a78c9699e | ||
|
|
0721b29a2c | ||
|
|
3d354909d6 | ||
|
|
7570a84dfd |
127
.github/DISCUSSION_TEMPLATE/issue-triage.yml
vendored
Normal file
127
.github/DISCUSSION_TEMPLATE/issue-triage.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
labels: ["needs-confirmation"]
|
||||||
|
body:
|
||||||
|
- type: markdown #add faqs in future
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Please read through [the Discussion rules](https://github.com/cinnyapp/cinny/discussions/2653) and check for both existing [Discussions](https://github.com/cinnyapp/cinny/discussions?discussions_q=) and [Issues](https://github.com/cinnyapp/cinny/issues?q=sort%3Areactions-desc) prior to opening a new Discussion.
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: "# Issue Details"
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Issue Description
|
||||||
|
description: |
|
||||||
|
Provide a detailed description of the issue. Include relevant information, such as:
|
||||||
|
- The feature or configuration option you encounter the issue with.
|
||||||
|
- Screenshots, screen recordings, or other supporting media (as needed).
|
||||||
|
- If this is a regression of an existing issue that was closed or resolved, please include the previous item reference (Discussion, Issue, PR, commit) in your description.
|
||||||
|
placeholder: |
|
||||||
|
When I try to send a message in a room, the message doesn't appear in the timeline.
|
||||||
|
OR
|
||||||
|
The application crashes when I click on the settings button.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected Behavior
|
||||||
|
description: |
|
||||||
|
Describe how you expect Cinny to behave in this situation.
|
||||||
|
placeholder: |
|
||||||
|
I expected the message to appear in the room timeline immediately after sending.
|
||||||
|
OR
|
||||||
|
The settings panel should open smoothly without any crashes.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Actual Behavior
|
||||||
|
description: |
|
||||||
|
Describe how Cinny actually behaves in this situation. If it is not immediately obvious how the actual behavior differs from the expected behavior described above, please be sure to mention the deviation specifically.
|
||||||
|
placeholder: |
|
||||||
|
The application freezes for 3 seconds and then shows a white screen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Reproduction Steps
|
||||||
|
description: |
|
||||||
|
Provide a detailed set of step-by-step instructions for reproducing this issue.
|
||||||
|
placeholder: |
|
||||||
|
1. Open Cinny and log in to my account
|
||||||
|
2. Navigate to the #general room
|
||||||
|
3. Type a message in the message box
|
||||||
|
4. Press Enter to send
|
||||||
|
5. Notice that the message doesn't appear in the timeline
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Environement
|
||||||
|
description: |
|
||||||
|
Please provide information about your environment. Include the following:
|
||||||
|
- OS:
|
||||||
|
- Browser:
|
||||||
|
- Cinny Web Version: (app.cinny.in or self hosted)
|
||||||
|
- Cinny desktop Version: (appimage or deb or flatpak)
|
||||||
|
- Matrix Homeserver:
|
||||||
|
placeholder: |
|
||||||
|
- OS: Windows 11
|
||||||
|
- Browser: Chrome 120.0.6099.109
|
||||||
|
- Cinny Web Version: 3.2.0 (app.cinny.in or self hosted)
|
||||||
|
- Cinny desktop Version: 3.2.0 (appimage or deb or flatpak)
|
||||||
|
- Matrix Homeserver: matrix.org (Synapse 1.97.0)
|
||||||
|
render: text
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant Logs
|
||||||
|
description: |
|
||||||
|
If applicable, add browser console logs to help explain your problem.
|
||||||
|
|
||||||
|
**To get browser console logs:**
|
||||||
|
- Chrome/Edge: Press F12 → Console tab
|
||||||
|
- Firefox: Press F12 → Console tab
|
||||||
|
- Safari: Develop → Show Web Inspector → Console
|
||||||
|
|
||||||
|
Please wrap large log outputs in code blocks with triple backticks (```).
|
||||||
|
placeholder: |
|
||||||
|
```
|
||||||
|
Error: Failed to send message
|
||||||
|
at MessageComposer.sendMessage (composer.js:245)
|
||||||
|
at HTMLButtonElement.onClick (composer.js:189)
|
||||||
|
TypeError: Cannot read property 'content' of undefined
|
||||||
|
at RoomTimeline.render (timeline.js:567)
|
||||||
|
```
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: |
|
||||||
|
Add any other context about the problem here (e.g., when did this start happening, does it happen on different homeservers, etc.)
|
||||||
|
placeholder: |
|
||||||
|
- This started happening after I updated to version 3.2.0
|
||||||
|
- It only happens in encrypted rooms, not in public rooms
|
||||||
|
- I've tried on both Firefox and Chrome with the same result
|
||||||
|
- It works fine on my phone using the same account
|
||||||
|
- This happens on all homeservers I've tested (matrix.org, mozilla.org)
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
# User Acknowledgements
|
||||||
|
> [!TIP]
|
||||||
|
> Use these links to review the existing Cinny [Discussions](https://github.com/cinnyapp/cinny/discussions?discussions_q=) and [Issues](https://github.com/cinnyapp/cinny/issues?q=sort%3Areactions-desc).
|
||||||
|
- type: checkboxes #add faqs in future
|
||||||
|
attributes:
|
||||||
|
label: "I acknowledge that:"
|
||||||
|
options:
|
||||||
|
- label: I have searched the Cinny repository (both open and closed Discussions and Issues) and confirm this is not a duplicate of an existing issue or discussion.
|
||||||
|
required: true
|
||||||
|
- label: I have checked the "Preview" tab on all text fields to ensure that everything looks right, and have wrapped all configuration and code in code blocks with a group of three backticks (` ``` `) on separate lines.
|
||||||
|
required: true
|
||||||
57
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
57
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,57 +0,0 @@
|
|||||||
name: 🐞 Bug Report
|
|
||||||
description: Report a bug
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## First of all
|
|
||||||
1. Please search for [existing issues](https://github.com/ajbura/cinny/issues?q=is%3Aissue) about this problem first.
|
|
||||||
2. Make sure Cinny is up to date.
|
|
||||||
3. Make sure it's an issue with Cinny and not something else you are using.
|
|
||||||
4. Remember to be friendly.
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Describe the bug
|
|
||||||
description: A clear description of what the bug is. Include screenshots if applicable.
|
|
||||||
placeholder: Bug description
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: reproduction
|
|
||||||
attributes:
|
|
||||||
label: Reproduction
|
|
||||||
description: Steps to reproduce the behavior.
|
|
||||||
placeholder: |
|
|
||||||
1. Go to ...
|
|
||||||
2. Click on ...
|
|
||||||
3. See error
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: expected-behavior
|
|
||||||
attributes:
|
|
||||||
label: Expected behavior
|
|
||||||
description: A clear description of what you expected to happen.
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: info
|
|
||||||
attributes:
|
|
||||||
label: Platform and versions
|
|
||||||
description: "Provide OS, browser and Cinny version with your Homeserver."
|
|
||||||
placeholder: |
|
|
||||||
1. OS: [e.g. Windows 10, MacOS]
|
|
||||||
2. Browser: [e.g. chrome 99.5, firefox 97.2]
|
|
||||||
3. Cinny version: [e.g. 1.8.1 (app.cinny.in)]
|
|
||||||
4. Matrix homeserver: [e.g. matrix.org]
|
|
||||||
render: shell
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: context
|
|
||||||
attributes:
|
|
||||||
label: Additional context
|
|
||||||
description: Add any other context about the problem here.
|
|
||||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,4 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: 💬 Matrix Chat
|
- name: Features, Bug Reports, Questions
|
||||||
url: https://matrix.to/#/#cinny:matrix.org
|
url: https://github.com/cinnyapp/cinny/discussions/new/choose
|
||||||
about: Ask questions and talk to other Cinny users and the maintainers
|
about: Our preferred starting point if you have any questions or suggestions about features or behavior.
|
||||||
|
|||||||
33
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
33
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,33 +0,0 @@
|
|||||||
name: 💡 Feature Request
|
|
||||||
description: Suggest an idea
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: problem
|
|
||||||
attributes:
|
|
||||||
label: Describe the problem
|
|
||||||
description: A clear description of the problem this feature would solve
|
|
||||||
placeholder: "I'm always frustrated when..."
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: solution
|
|
||||||
attributes:
|
|
||||||
label: "Describe the solution you'd like"
|
|
||||||
description: A clear description of what change you would like
|
|
||||||
placeholder: "I would like to..."
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: alternatives
|
|
||||||
attributes:
|
|
||||||
label: Alternatives considered
|
|
||||||
description: "Any alternative solutions you've considered"
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: context
|
|
||||||
attributes:
|
|
||||||
label: Additional context
|
|
||||||
description: Add any other context about the problem here.
|
|
||||||
9
.github/ISSUE_TEMPLATE/preapproved.md
vendored
Normal file
9
.github/ISSUE_TEMPLATE/preapproved.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
name: Pre-Discussed and Approved Topics
|
||||||
|
about: |-
|
||||||
|
Only for topics already discussed and approved in the GitHub Discussions section.
|
||||||
|
---
|
||||||
|
|
||||||
|
**DO NOT OPEN A NEW ISSUE. PLEASE USE THE DISCUSSIONS SECTION.**
|
||||||
|
|
||||||
|
**I DIDN'T READ THE ABOVE LINE. PLEASE CLOSE THIS ISSUE.**
|
||||||
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,22 +0,0 @@
|
|||||||
<!-- Please read https://github.com/ajbura/cinny/blob/dev/CONTRIBUTING.md before submitting your pull request -->
|
|
||||||
|
|
||||||
### Description
|
|
||||||
<!-- Please include a summary of the change. Please also include relevant motivation and context. List any dependencies that are required for this change. -->
|
|
||||||
|
|
||||||
|
|
||||||
Fixes #
|
|
||||||
|
|
||||||
#### Type of change
|
|
||||||
|
|
||||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
|
||||||
- [ ] New feature (non-breaking change which adds functionality)
|
|
||||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
|
||||||
- [ ] This change requires a documentation update
|
|
||||||
|
|
||||||
### Checklist:
|
|
||||||
|
|
||||||
- [ ] My code follows the style guidelines of this project
|
|
||||||
- [ ] I have performed a self-review of my own code
|
|
||||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
|
||||||
- [ ] I have made corresponding changes to the documentation
|
|
||||||
- [ ] My changes generate no new warnings
|
|
||||||
3
.github/SECURITY.md
vendored
3
.github/SECURITY.md
vendored
@@ -1,3 +0,0 @@
|
|||||||
# Reporting a Vulnerability
|
|
||||||
|
|
||||||
**If you've found a security vulnerability, please report it to cinnyapp@gmail.com**
|
|
||||||
16
.github/renovate.json
vendored
16
.github/renovate.json
vendored
@@ -3,12 +3,26 @@
|
|||||||
"extends": [
|
"extends": [
|
||||||
"config:recommended",
|
"config:recommended",
|
||||||
":dependencyDashboardApproval",
|
":dependencyDashboardApproval",
|
||||||
":semanticCommits"
|
":semanticCommits",
|
||||||
|
"group:monorepos"
|
||||||
],
|
],
|
||||||
"labels": ["Dependencies"],
|
"labels": ["Dependencies"],
|
||||||
|
"rebaseWhen": "conflicted",
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": ["lockFileMaintenance"]
|
"matchUpdateTypes": ["lockFileMaintenance"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"groupName": "Slatejs",
|
||||||
|
"matchPackageNames": ["slate", "slate-dom", "slate-history", "slate-react"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"groupName": "Call",
|
||||||
|
"matchPackageNames": ["@element-hq/element-call-embedded", "matrix-widget-api"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"groupName": "Linkify",
|
||||||
|
"matchPackageNames": ["linkifyjs", "linkify-react"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lockFileMaintenance": {
|
"lockFileMaintenance": {
|
||||||
|
|||||||
4
.github/workflows/build-pull-request.yml
vendored
4
.github/workflows/build-pull-request.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
NODE_OPTIONS: '--max_old_space_size=4096'
|
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||||
run: npm run build
|
run: npm run build
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
with:
|
with:
|
||||||
name: preview
|
name: preview
|
||||||
path: dist
|
path: dist
|
||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
- name: Save pr number
|
- name: Save pr number
|
||||||
run: echo ${PR_NUMBER} > ./pr.txt
|
run: echo ${PR_NUMBER} > ./pr.txt
|
||||||
- name: Upload pr number
|
- name: Upload pr number
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
with:
|
with:
|
||||||
name: pr
|
name: pr
|
||||||
path: ./pr.txt
|
path: ./pr.txt
|
||||||
|
|||||||
4
.github/workflows/deploy-pull-request.yml
vendored
4
.github/workflows/deploy-pull-request.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Download pr number
|
- name: Download pr number
|
||||||
uses: dawidd6/action-download-artifact@2536c51d3d126276eb39f74d6bc9c72ac6ef30d3 # v16
|
uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20
|
||||||
with:
|
with:
|
||||||
workflow: ${{ github.event.workflow.id }}
|
workflow: ${{ github.event.workflow.id }}
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
id: pr
|
id: pr
|
||||||
run: echo "id=$(<pr.txt)" >> $GITHUB_OUTPUT
|
run: echo "id=$(<pr.txt)" >> $GITHUB_OUTPUT
|
||||||
- name: Download artifact
|
- name: Download artifact
|
||||||
uses: dawidd6/action-download-artifact@2536c51d3d126276eb39f74d6bc9c72ac6ef30d3 # v16
|
uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20
|
||||||
with:
|
with:
|
||||||
workflow: ${{ github.event.workflow.id }}
|
workflow: ${{ github.event.workflow.id }}
|
||||||
run_id: ${{ github.event.workflow_run.id }}
|
run_id: ${{ github.event.workflow_run.id }}
|
||||||
|
|||||||
6
.github/workflows/docker-pr.yml
vendored
6
.github/workflows/docker-pr.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Login to Docker Hub #Do not update this action from a outside PR
|
- name: Login to Docker Hub #Do not update this action from a outside PR
|
||||||
if: github.event.pull_request.head.repo.fork == false
|
if: github.event.pull_request.head.repo.fork == false
|
||||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
@@ -34,7 +34,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Login to the Github Container registry #Do not update this action from a outside PR
|
- name: Login to the Github Container registry #Do not update this action from a outside PR
|
||||||
if: github.event.pull_request.head.repo.fork == false
|
if: github.event.pull_request.head.repo.fork == false
|
||||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -50,7 +50,7 @@ jobs:
|
|||||||
ghcr.io/${{ github.repository }}
|
ghcr.io/${{ github.repository }}
|
||||||
|
|
||||||
- name: Build Docker image (no push)
|
- name: Build Docker image (no push)
|
||||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|||||||
42
.github/workflows/prod-deploy.yml
vendored
42
.github/workflows/prod-deploy.yml
vendored
@@ -1,16 +1,19 @@
|
|||||||
name: Production deploy
|
name: Production deploy
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
workflow_dispatch:
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy-and-tarball:
|
deploy-and-tarball:
|
||||||
name: Netlify deploy and tarball
|
name: Netlify deploy and tarball
|
||||||
|
outputs:
|
||||||
|
version: ${{ steps.vars.outputs.tag }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
- name: Setup node
|
- name: Setup node
|
||||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||||
with:
|
with:
|
||||||
@@ -18,6 +21,19 @@ jobs:
|
|||||||
package-manager-cache: false
|
package-manager-cache: false
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
|
- name: Run semantic release
|
||||||
|
run: npm run semantic-release
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GIT_AUTHOR_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
|
||||||
|
GIT_AUTHOR_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||||
|
GIT_COMMITTER_NAME: ${{ secrets.GIT_AUTHOR_NAME }}
|
||||||
|
GIT_COMMITTER_EMAIL: ${{ secrets.GIT_AUTHOR_EMAIL }}
|
||||||
|
- name: Get version from tag
|
||||||
|
id: vars
|
||||||
|
run: |
|
||||||
|
TAG=$(git describe --tags --abbrev=0)
|
||||||
|
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||||
- name: Build app
|
- name: Build app
|
||||||
env:
|
env:
|
||||||
NODE_OPTIONS: '--max_old_space_size=4096'
|
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||||
@@ -26,7 +42,7 @@ jobs:
|
|||||||
uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0.0
|
uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0.0
|
||||||
with:
|
with:
|
||||||
publish-dir: dist
|
publish-dir: dist
|
||||||
deploy-message: 'Prod deploy ${{ github.ref_name }}'
|
deploy-message: 'Prod deploy ${{ steps.vars.outputs.tag }}'
|
||||||
enable-commit-comment: false
|
enable-commit-comment: false
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
production-deploy: true
|
production-deploy: true
|
||||||
@@ -36,9 +52,6 @@ jobs:
|
|||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID_APP }}
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID_APP }}
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
- name: Get version from tag
|
|
||||||
id: vars
|
|
||||||
run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
|
|
||||||
- name: Create tar.gz
|
- name: Create tar.gz
|
||||||
run: tar -czvf cinny-${{ steps.vars.outputs.tag }}.tar.gz dist
|
run: tar -czvf cinny-${{ steps.vars.outputs.tag }}.tar.gz dist
|
||||||
- name: Sign tar.gz
|
- name: Sign tar.gz
|
||||||
@@ -52,14 +65,18 @@ jobs:
|
|||||||
gpg --export | xxd -p
|
gpg --export | xxd -p
|
||||||
echo '${{ secrets.GNUPG_PASSPHRASE }}' | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --armor --detach-sign cinny-${{ steps.vars.outputs.tag }}.tar.gz
|
echo '${{ secrets.GNUPG_PASSPHRASE }}' | gpg --batch --yes --pinentry-mode loopback --passphrase-fd 0 --armor --detach-sign cinny-${{ steps.vars.outputs.tag }}.tar.gz
|
||||||
- name: Upload tagged release
|
- name: Upload tagged release
|
||||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
|
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||||
with:
|
with:
|
||||||
|
tag_name: ${{ steps.vars.outputs.tag }}
|
||||||
files: |
|
files: |
|
||||||
cinny-${{ steps.vars.outputs.tag }}.tar.gz
|
cinny-${{ steps.vars.outputs.tag }}.tar.gz
|
||||||
cinny-${{ steps.vars.outputs.tag }}.tar.gz.asc
|
cinny-${{ steps.vars.outputs.tag }}.tar.gz.asc
|
||||||
|
|
||||||
publish-image:
|
publish-image:
|
||||||
name: Push Docker image to Docker Hub, GHCR
|
name: Push Docker image to Docker Hub, GHCR
|
||||||
|
needs: deploy-and-tarball
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.deploy-and-tarball.outputs.version }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -67,17 +84,19 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||||
- name: Login to Docker Hub #Do not update this action from a outside PR
|
- name: Login to Docker Hub #Do not update this action from a outside PR
|
||||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
- name: Login to the Github Container registry #Do not update this action from a outside PR
|
- name: Login to the Github Container registry #Do not update this action from a outside PR
|
||||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -89,8 +108,11 @@ jobs:
|
|||||||
images: |
|
images: |
|
||||||
${{ secrets.DOCKER_USERNAME }}/cinny
|
${{ secrets.DOCKER_USERNAME }}/cinny
|
||||||
ghcr.io/${{ github.repository }}
|
ghcr.io/${{ github.repository }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=${{ env.VERSION }}
|
||||||
|
type=raw,value=latest
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
3
.husky/pre-commit
Normal file
3
.husky/pre-commit
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# These are commented until we enable lint and typecheck
|
||||||
|
# npx tsc -p tsconfig.json --noEmit
|
||||||
|
# npx lint-staged
|
||||||
@@ -18,7 +18,7 @@ Bug reports and feature suggestions must use descriptive and concise titles and
|
|||||||
## Pull requests
|
## Pull requests
|
||||||
|
|
||||||
> ### Legal Notice
|
> ### Legal Notice
|
||||||
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
|
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. You will also be asked to [sign the CLA](https://github.com/cinnyapp/cla) upon submiting your pull request.
|
||||||
|
|
||||||
**NOTE: If you want to add new features, please discuss with maintainers before coding or opening a pull request.** This is to ensure that we are on same track and following our roadmap.
|
**NOTE: If you want to add new features, please discuss with maintainers before coding or opening a pull request.** This is to ensure that we are on same track and following our roadmap.
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ RUN npm run build
|
|||||||
|
|
||||||
|
|
||||||
## App
|
## App
|
||||||
FROM nginx:1.29.5-alpine
|
FROM nginx:1.29.8-alpine
|
||||||
|
|
||||||
COPY --from=builder /src/dist /app
|
COPY --from=builder /src/dist /app
|
||||||
COPY --from=builder /src/docker-nginx.conf /etc/nginx/conf.d/default.conf
|
COPY --from=builder /src/docker-nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ A Matrix client focusing primarily on simple, elegant and secure interface. The
|
|||||||
- [Roadmap](https://github.com/orgs/cinnyapp/projects/1)
|
- [Roadmap](https://github.com/orgs/cinnyapp/projects/1)
|
||||||
- [Contributing](./CONTRIBUTING.md)
|
- [Contributing](./CONTRIBUTING.md)
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
We are currently in the [process of replacing the matrix-js-sdk](https://github.com/cinnyapp/cinny/issues/257#issuecomment-3714406704) with our own SDK. As a result, we will not be accepting any pull requests until further notice.
|
||||||
|
Thank you for your understanding.
|
||||||
|
|
||||||
<img align="center" src="https://raw.githubusercontent.com/cinnyapp/cinny-site/main/assets/preview2-light.png" height="380">
|
<img align="center" src="https://raw.githubusercontent.com/cinnyapp/cinny-site/main/assets/preview2-light.png" height="380">
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
"#space:unredacted.org",
|
"#space:unredacted.org",
|
||||||
"#science-space:matrix.org",
|
"#science-space:matrix.org",
|
||||||
"#libregaming-games:tchncs.de",
|
"#libregaming-games:tchncs.de",
|
||||||
"#mathematics-on:matrix.org"
|
"#mathematics-on:matrix.org",
|
||||||
|
"#stickers-and-emojis:tastytea.de"
|
||||||
],
|
],
|
||||||
"rooms": [
|
"rooms": [
|
||||||
"#cinny:matrix.org",
|
"#cinny:matrix.org",
|
||||||
@@ -21,7 +22,7 @@
|
|||||||
"#PrivSec.dev:arcticfoxes.net",
|
"#PrivSec.dev:arcticfoxes.net",
|
||||||
"#disroot:aria-net.org"
|
"#disroot:aria-net.org"
|
||||||
],
|
],
|
||||||
"servers": ["matrix.org", "mozilla.org", "unredacted.org"]
|
"servers": ["matrixrooms.info", "matrix.org", "mozilla.org", "unredacted.org"]
|
||||||
},
|
},
|
||||||
|
|
||||||
"hashRouter": {
|
"hashRouter": {
|
||||||
|
|||||||
7104
package-lock.json
generated
7104
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
51
package.json
51
package.json
@@ -11,11 +11,52 @@
|
|||||||
"start": "vite",
|
"start": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "yarn check:eslint && yarn check:prettier",
|
"lint": "npm run check:eslint && npm run check:prettier",
|
||||||
"check:eslint": "eslint src/*",
|
"check:eslint": "eslint src/*",
|
||||||
"check:prettier": "prettier --check .",
|
"check:prettier": "prettier --check .",
|
||||||
"fix:prettier": "prettier --write .",
|
"fix:prettier": "prettier --write .",
|
||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit",
|
||||||
|
"prepare": "husky install",
|
||||||
|
"commit": "git-cz",
|
||||||
|
"semantic-release": "semantic-release"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{ts,tsx,js,jsx}": "eslint",
|
||||||
|
"*": "prettier --ignore-unknown --write"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"commitizen": {
|
||||||
|
"path": "./node_modules/cz-conventional-changelog"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"release": {
|
||||||
|
"branches": [
|
||||||
|
"dev"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"@semantic-release/commit-analyzer",
|
||||||
|
"@semantic-release/release-notes-generator",
|
||||||
|
[
|
||||||
|
"@semantic-release/exec",
|
||||||
|
{
|
||||||
|
"prepareCmd": "node scripts/update-version.js ${nextRelease.version}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"@semantic-release/git",
|
||||||
|
{
|
||||||
|
"assets": [
|
||||||
|
"package.json",
|
||||||
|
"package-lock.json",
|
||||||
|
"src/app/features/settings/about/About.tsx",
|
||||||
|
"src/app/pages/auth/AuthFooter.tsx",
|
||||||
|
"src/app/pages/client/WelcomePage.tsx"
|
||||||
|
],
|
||||||
|
"message": "chore(release): ${nextRelease.version} [skip ci]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@semantic-release/github"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Ajay Bura",
|
"author": "Ajay Bura",
|
||||||
@@ -82,6 +123,8 @@
|
|||||||
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
|
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
|
||||||
"@rollup/plugin-inject": "5.0.3",
|
"@rollup/plugin-inject": "5.0.3",
|
||||||
"@rollup/plugin-wasm": "6.1.1",
|
"@rollup/plugin-wasm": "6.1.1",
|
||||||
|
"@semantic-release/exec": "7.1.0",
|
||||||
|
"@semantic-release/git": "10.0.1",
|
||||||
"@types/chroma-js": "3.1.1",
|
"@types/chroma-js": "3.1.1",
|
||||||
"@types/file-saver": "2.0.5",
|
"@types/file-saver": "2.0.5",
|
||||||
"@types/is-hotkey": "0.1.10",
|
"@types/is-hotkey": "0.1.10",
|
||||||
@@ -96,6 +139,7 @@
|
|||||||
"@typescript-eslint/parser": "5.46.1",
|
"@typescript-eslint/parser": "5.46.1",
|
||||||
"@vitejs/plugin-react": "4.2.0",
|
"@vitejs/plugin-react": "4.2.0",
|
||||||
"buffer": "6.0.3",
|
"buffer": "6.0.3",
|
||||||
|
"cz-conventional-changelog": "3.3.0",
|
||||||
"eslint": "8.29.0",
|
"eslint": "8.29.0",
|
||||||
"eslint-config-airbnb": "19.0.4",
|
"eslint-config-airbnb": "19.0.4",
|
||||||
"eslint-config-prettier": "8.5.0",
|
"eslint-config-prettier": "8.5.0",
|
||||||
@@ -103,7 +147,10 @@
|
|||||||
"eslint-plugin-jsx-a11y": "6.6.1",
|
"eslint-plugin-jsx-a11y": "6.6.1",
|
||||||
"eslint-plugin-react": "7.31.11",
|
"eslint-plugin-react": "7.31.11",
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
|
"husky": "9.1.7",
|
||||||
|
"lint-staged": "16.3.2",
|
||||||
"prettier": "2.8.1",
|
"prettier": "2.8.1",
|
||||||
|
"semantic-release": "25.0.3",
|
||||||
"typescript": "4.9.4",
|
"typescript": "4.9.4",
|
||||||
"vite": "5.4.19",
|
"vite": "5.4.19",
|
||||||
"vite-plugin-pwa": "0.20.5",
|
"vite-plugin-pwa": "0.20.5",
|
||||||
|
|||||||
48
scripts/update-version.js
Normal file
48
scripts/update-version.js
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import { execSync } from "child_process";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
const version = process.argv[2];
|
||||||
|
|
||||||
|
if (!version) {
|
||||||
|
console.error("Version argument missing");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = path.resolve(__dirname, "..");
|
||||||
|
const newVersionTag = `v${version}`;
|
||||||
|
|
||||||
|
// Update package.json + package-lock.json safely
|
||||||
|
execSync(`npm version ${version} --no-git-tag-version`, {
|
||||||
|
cwd: root,
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Updated package.json and package-lock.json → ${version}`);
|
||||||
|
|
||||||
|
// Update UI version references
|
||||||
|
const files = [
|
||||||
|
"src/app/features/settings/about/About.tsx",
|
||||||
|
"src/app/pages/auth/AuthFooter.tsx",
|
||||||
|
"src/app/pages/client/WelcomePage.tsx",
|
||||||
|
];
|
||||||
|
|
||||||
|
files.forEach((filePath) => {
|
||||||
|
const absPath = path.join(root, filePath);
|
||||||
|
|
||||||
|
if (!fs.existsSync(absPath)) {
|
||||||
|
console.warn(`File not found: ${filePath}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = fs.readFileSync(absPath, "utf8");
|
||||||
|
const updated = content.replace(/v\d+\.\d+\.\d+/g, newVersionTag);
|
||||||
|
|
||||||
|
fs.writeFileSync(absPath, updated);
|
||||||
|
|
||||||
|
console.log(`Updated ${filePath} → ${newVersionTag}`);
|
||||||
|
});
|
||||||
45
src/app/components/ImageOverlay.tsx
Normal file
45
src/app/components/ImageOverlay.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import FocusTrap from 'focus-trap-react';
|
||||||
|
import { as, Modal, Overlay, OverlayBackdrop, OverlayCenter } from 'folds';
|
||||||
|
import React, { ReactNode } from 'react';
|
||||||
|
import { ModalWide } from '../styles/Modal.css';
|
||||||
|
import { stopPropagation } from '../utils/keyboard';
|
||||||
|
|
||||||
|
export type RenderViewerProps = {
|
||||||
|
src: string;
|
||||||
|
alt: string;
|
||||||
|
requestClose: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ImageOverlayProps = RenderViewerProps & {
|
||||||
|
viewer: boolean;
|
||||||
|
renderViewer: (props: RenderViewerProps) => ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ImageOverlay = as<'div', ImageOverlayProps>(
|
||||||
|
({ src, alt, viewer, requestClose, renderViewer, ...props }, ref) => (
|
||||||
|
<Overlay {...props} ref={ref} open={viewer} backdrop={<OverlayBackdrop />}>
|
||||||
|
<OverlayCenter>
|
||||||
|
<FocusTrap
|
||||||
|
focusTrapOptions={{
|
||||||
|
initialFocus: false,
|
||||||
|
onDeactivate: () => requestClose(),
|
||||||
|
clickOutsideDeactivates: true,
|
||||||
|
escapeDeactivates: stopPropagation,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Modal
|
||||||
|
className={ModalWide}
|
||||||
|
size="500"
|
||||||
|
onContextMenu={(evt: any) => evt.stopPropagation()}
|
||||||
|
>
|
||||||
|
{renderViewer({
|
||||||
|
src,
|
||||||
|
alt,
|
||||||
|
requestClose,
|
||||||
|
})}
|
||||||
|
</Modal>
|
||||||
|
</FocusTrap>
|
||||||
|
</OverlayCenter>
|
||||||
|
</Overlay>
|
||||||
|
)
|
||||||
|
);
|
||||||
@@ -228,9 +228,13 @@ const parseCodeBlockNode = (node: Element): CodeBlockElement[] | ParagraphElemen
|
|||||||
children: [{ text }],
|
children: [{ text }],
|
||||||
}));
|
}));
|
||||||
const childCode = node.children[0];
|
const childCode = node.children[0];
|
||||||
const className =
|
const attribs =
|
||||||
isTag(childCode) && childCode.tagName === 'code' ? childCode.attribs.class ?? '' : '';
|
isTag(childCode) && childCode.tagName === 'code' ? childCode.attribs : undefined;
|
||||||
const prefix = { text: `${mdSequence}${className.replace('language-', '')}` };
|
const languageClass = attribs?.class;
|
||||||
|
const customLabel = attribs?.['data-label'];
|
||||||
|
const prefix = {
|
||||||
|
text: `${mdSequence}${customLabel ?? languageClass?.replace('language-', '') ?? ''}`,
|
||||||
|
};
|
||||||
const suffix = { text: mdSequence };
|
const suffix = { text: mdSequence };
|
||||||
return [
|
return [
|
||||||
{ type: BlockType.Paragraph, children: [prefix] },
|
{ type: BlockType.Paragraph, children: [prefix] },
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ export const UrlPreviewImg = style([
|
|||||||
objectPosition: 'center',
|
objectPosition: 'center',
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
':hover': {
|
||||||
|
filter: 'brightness(0.8)',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { IPreviewUrlResponse } from 'matrix-js-sdk';
|
import { IPreviewUrlResponse } from 'matrix-js-sdk';
|
||||||
import { Box, Icon, IconButton, Icons, Scroll, Spinner, Text, as, color, config } from 'folds';
|
import { Box, Icon, IconButton, Icons, Scroll, Spinner, Text, as, color, config } from 'folds';
|
||||||
|
import { ImageOverlay } from '../ImageOverlay';
|
||||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { UrlPreview, UrlPreviewContent, UrlPreviewDescription, UrlPreviewImg } from './UrlPreview';
|
import { UrlPreview, UrlPreviewContent, UrlPreviewDescription, UrlPreviewImg } from './UrlPreview';
|
||||||
@@ -12,6 +13,8 @@ import * as css from './UrlPreviewCard.css';
|
|||||||
import { tryDecodeURIComponent } from '../../utils/dom';
|
import { tryDecodeURIComponent } from '../../utils/dom';
|
||||||
import { mxcUrlToHttp } from '../../utils/matrix';
|
import { mxcUrlToHttp } from '../../utils/matrix';
|
||||||
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
|
||||||
|
import { ImageViewer } from '../image-viewer';
|
||||||
|
import { onEnterOrSpace } from '../../utils/keyboard';
|
||||||
|
|
||||||
const linkStyles = { color: color.Success.Main };
|
const linkStyles = { color: color.Success.Main };
|
||||||
|
|
||||||
@@ -19,6 +22,7 @@ export const UrlPreviewCard = as<'div', { url: string; ts: number }>(
|
|||||||
({ url, ts, ...props }, ref) => {
|
({ url, ts, ...props }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const useAuthentication = useMediaAuthentication();
|
const useAuthentication = useMediaAuthentication();
|
||||||
|
const [viewer, setViewer] = useState(false);
|
||||||
const [previewStatus, loadPreview] = useAsyncCallback(
|
const [previewStatus, loadPreview] = useAsyncCallback(
|
||||||
useCallback(() => mx.getUrlPreview(url, ts), [url, ts, mx])
|
useCallback(() => mx.getUrlPreview(url, ts), [url, ts, mx])
|
||||||
);
|
);
|
||||||
@@ -30,7 +34,7 @@ export const UrlPreviewCard = as<'div', { url: string; ts: number }>(
|
|||||||
if (previewStatus.status === AsyncStatus.Error) return null;
|
if (previewStatus.status === AsyncStatus.Error) return null;
|
||||||
|
|
||||||
const renderContent = (prev: IPreviewUrlResponse) => {
|
const renderContent = (prev: IPreviewUrlResponse) => {
|
||||||
const imgUrl = mxcUrlToHttp(
|
const thumbUrl = mxcUrlToHttp(
|
||||||
mx,
|
mx,
|
||||||
prev['og:image'] || '',
|
prev['og:image'] || '',
|
||||||
useAuthentication,
|
useAuthentication,
|
||||||
@@ -40,9 +44,31 @@ export const UrlPreviewCard = as<'div', { url: string; ts: number }>(
|
|||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const imgUrl = mxcUrlToHttp(mx, prev['og:image'] || '', useAuthentication);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{imgUrl && <UrlPreviewImg src={imgUrl} alt={prev['og:title']} title={prev['og:title']} />}
|
{thumbUrl && (
|
||||||
|
<UrlPreviewImg
|
||||||
|
src={thumbUrl}
|
||||||
|
alt={prev['og:title']}
|
||||||
|
title={prev['og:title']}
|
||||||
|
tabIndex={0}
|
||||||
|
onKeyDown={(evt) => onEnterOrSpace(() => setViewer(true))(evt)}
|
||||||
|
onClick={() => setViewer(true)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{imgUrl && (
|
||||||
|
<ImageOverlay
|
||||||
|
src={imgUrl}
|
||||||
|
alt={prev['og:title']}
|
||||||
|
viewer={viewer}
|
||||||
|
requestClose={() => {
|
||||||
|
setViewer(false);
|
||||||
|
}}
|
||||||
|
renderViewer={(p) => <ImageViewer {...p} />}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<UrlPreviewContent>
|
<UrlPreviewContent>
|
||||||
<Text
|
<Text
|
||||||
style={linkStyles}
|
style={linkStyles}
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ export function Search({ requestClose }: SearchProps) {
|
|||||||
gap="100"
|
gap="100"
|
||||||
>
|
>
|
||||||
<Text size="H6" align="Center">
|
<Text size="H6" align="Center">
|
||||||
{result ? 'No Match Found' : `No Rooms'}`}
|
{result ? 'No Match Found' : 'No Rooms'}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="T200" align="Center">
|
<Text size="T200" align="Center">
|
||||||
{result
|
{result
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ export const useDateFormatItems = (): DateFormatItem[] =>
|
|||||||
format: 'YYYY/MM/DD',
|
format: 'YYYY/MM/DD',
|
||||||
name: 'YYYY/MM/DD',
|
name: 'YYYY/MM/DD',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
name: 'YYYY-MM-DD',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
format: '',
|
format: '',
|
||||||
name: 'Custom',
|
name: 'Custom',
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export function SpecVersions({ baseUrl, children }: { baseUrl: string; children:
|
|||||||
<Dialog>
|
<Dialog>
|
||||||
<Box direction="Column" gap="400" style={{ padding: config.space.S400 }}>
|
<Box direction="Column" gap="400" style={{ padding: config.space.S400 }}>
|
||||||
<Text>
|
<Text>
|
||||||
Failed to connect to homeserver. Either homeserver is down or your internet.
|
Unable to connect to the homeserver. The homeserver or your internet connection may be down.
|
||||||
</Text>
|
</Text>
|
||||||
<Button variant="Critical" onClick={retry}>
|
<Button variant="Critical" onClick={retry}>
|
||||||
<Text as="span" size="B400">
|
<Text as="span" size="B400">
|
||||||
|
|||||||
@@ -16,8 +16,12 @@ export const CodeBlockRule: BlockMDRule = {
|
|||||||
match: (text) => text.match(CODEBLOCK_REG_1),
|
match: (text) => text.match(CODEBLOCK_REG_1),
|
||||||
html: (match) => {
|
html: (match) => {
|
||||||
const [, g1, g2] = match;
|
const [, g1, g2] = match;
|
||||||
const classNameAtt = g1 ? ` class="language-${g1}"` : '';
|
// use last identifier after dot, e.g. for "example.json" gets us "json" as language code.
|
||||||
return `<pre data-md="${CODEBLOCK_MD_1}"><code${classNameAtt}>${g2}</code></pre>`;
|
const langCode = g1 ? g1.substring(g1.lastIndexOf('.') + 1) : null;
|
||||||
|
const filename = g1 !== langCode ? g1 : null;
|
||||||
|
const classNameAtt = langCode ? ` class="language-${langCode}"` : '';
|
||||||
|
const filenameAtt = filename ? ` data-label="${filename}"` : '';
|
||||||
|
return `<pre data-md="${CODEBLOCK_MD_1}"><code${classNameAtt}${filenameAtt}>${g2}</code></pre>`;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -232,8 +232,9 @@ export function CodeBlock({
|
|||||||
opts: HTMLReactParserOptions;
|
opts: HTMLReactParserOptions;
|
||||||
}) {
|
}) {
|
||||||
const code = children[0];
|
const code = children[0];
|
||||||
const languageClass =
|
const attribs = code instanceof Element && code.name === 'code' ? code.attribs : undefined;
|
||||||
code instanceof Element && code.name === 'code' ? code.attribs.class : undefined;
|
const languageClass = attribs?.class;
|
||||||
|
const customLabel = attribs?.['data-label'];
|
||||||
const language =
|
const language =
|
||||||
languageClass && languageClass.startsWith('language-')
|
languageClass && languageClass.startsWith('language-')
|
||||||
? languageClass.replace('language-', '')
|
? languageClass.replace('language-', '')
|
||||||
@@ -262,7 +263,7 @@ export function CodeBlock({
|
|||||||
<Header variant="Surface" size="400" className={css.CodeBlockHeader}>
|
<Header variant="Surface" size="400" className={css.CodeBlockHeader}>
|
||||||
<Box grow="Yes">
|
<Box grow="Yes">
|
||||||
<Text size="L400" truncate>
|
<Text size="L400" truncate>
|
||||||
{language ?? 'Code'}
|
{customLabel ?? language ?? 'Code'}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box shrink="No" gap="200">
|
<Box shrink="No" gap="200">
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
import { atom } from 'jotai';
|
import { atom } from 'jotai';
|
||||||
|
|
||||||
const STORAGE_KEY = 'settings';
|
const STORAGE_KEY = 'settings';
|
||||||
export type DateFormat = 'D MMM YYYY' | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD' | '';
|
export type DateFormat =
|
||||||
|
| 'D MMM YYYY'
|
||||||
|
| 'DD/MM/YYYY'
|
||||||
|
| 'MM/DD/YYYY'
|
||||||
|
| 'YYYY/MM/DD'
|
||||||
|
| 'YYYY-MM-DD'
|
||||||
|
| '';
|
||||||
export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500';
|
export type MessageSpacing = '0' | '100' | '200' | '300' | '400' | '500';
|
||||||
export enum MessageLayout {
|
export enum MessageLayout {
|
||||||
Modern = 0,
|
Modern = 0,
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const permittedTagToAttributes = {
|
|||||||
ul: ['data-md'],
|
ul: ['data-md'],
|
||||||
a: ['name', 'target', 'href', 'rel', 'data-md'],
|
a: ['name', 'target', 'href', 'rel', 'data-md'],
|
||||||
img: ['width', 'height', 'alt', 'title', 'src', 'data-mx-emoticon'],
|
img: ['width', 'height', 'alt', 'title', 'src', 'data-mx-emoticon'],
|
||||||
code: ['class', 'data-md'],
|
code: ['class', 'data-md', 'data-label'],
|
||||||
strong: ['data-md'],
|
strong: ['data-md'],
|
||||||
i: ['data-md'],
|
i: ['data-md'],
|
||||||
em: ['data-md'],
|
em: ['data-md'],
|
||||||
|
|||||||
Reference in New Issue
Block a user