Compare commits
No commits in common. "main" and "bwindels/rewrite" have entirely different histories.
main
...
bwindels/r
3
.gitignore
vendored
|
@ -1,5 +1,2 @@
|
||||||
node_modules
|
node_modules
|
||||||
build
|
build
|
||||||
*.tar.gz
|
|
||||||
/.idea
|
|
||||||
.DS_Store
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
# Contributing to Matrix.to
|
|
||||||
|
|
||||||
Thank you for taking the time to contribute to Matrix!
|
|
||||||
|
|
||||||
This is the repository for Matrix.to, a simple url redirection service for the Matrix.org ecosystem which lets users share links to matrix entities without being tied to a specific app.
|
|
||||||
|
|
||||||
## Sign off
|
|
||||||
|
|
||||||
We ask that everybody who contributes to this project signs off their contributions, as explained below.
|
|
||||||
|
|
||||||
We follow a simple 'inbound=outbound' model for contributions: the act of submitting an 'inbound' contribution means that the contributor agrees to license their contribution under the same terms as the project's overall 'outbound' license - in our case, this is Apache Software License v2 (see [LICENSE](./LICENSE)).
|
|
||||||
|
|
||||||
In order to have a concrete record that your contribution is intentional and you agree to license it under the same terms as the project's license, we've adopted the same lightweight approach used by the [Linux Kernel](https://www.kernel.org/doc/html/latest/process/submitting-patches.html), [Docker](https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other projects: the [Developer Certificate of Origin](https://developercertificate.org/) (DCO). This is a simple declaration that you wrote the contribution or otherwise have the right to contribute it to Matrix:
|
|
||||||
|
|
||||||
```
|
|
||||||
Developer Certificate of Origin
|
|
||||||
Version 1.1
|
|
||||||
|
|
||||||
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
|
||||||
660 York Street, Suite 102,
|
|
||||||
San Francisco, CA 94110 USA
|
|
||||||
|
|
||||||
Everyone is permitted to copy and distribute verbatim copies of this
|
|
||||||
license document, but changing it is not allowed.
|
|
||||||
|
|
||||||
Developer's Certificate of Origin 1.1
|
|
||||||
|
|
||||||
By making a contribution to this project, I certify that:
|
|
||||||
|
|
||||||
(a) The contribution was created in whole or in part by me and I
|
|
||||||
have the right to submit it under the open source license
|
|
||||||
indicated in the file; or
|
|
||||||
|
|
||||||
(b) The contribution is based upon previous work that, to the best
|
|
||||||
of my knowledge, is covered under an appropriate open source
|
|
||||||
license and I have the right under that license to submit that
|
|
||||||
work with modifications, whether created in whole or in part
|
|
||||||
by me, under the same open source license (unless I am
|
|
||||||
permitted to submit under a different license), as indicated
|
|
||||||
in the file; or
|
|
||||||
|
|
||||||
(c) The contribution was provided directly to me by some other
|
|
||||||
person who certified (a), (b) or (c) and I have not modified
|
|
||||||
it.
|
|
||||||
|
|
||||||
(d) I understand and agree that this project and the contribution
|
|
||||||
are public and that a record of the contribution (including all
|
|
||||||
personal information I submit with it, including my sign-off) is
|
|
||||||
maintained indefinitely and may be redistributed consistent with
|
|
||||||
this project or the open source license(s) involved.
|
|
||||||
```
|
|
||||||
|
|
||||||
If you agree to this for your contribution, then all that's needed is to include the line in your commit or pull request comment:
|
|
||||||
|
|
||||||
```
|
|
||||||
Signed-off-by: Your Name <your@email.example.org>
|
|
||||||
```
|
|
||||||
|
|
||||||
Git allows you to add this signoff automatically when using the `-s` flag to `git commit`, which uses the name and email set in your `user.name` and `user.email` git configs.
|
|
19
Dockerfile
|
@ -1,19 +0,0 @@
|
||||||
FROM node:latest
|
|
||||||
|
|
||||||
# Set working directory
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copy package files first to leverage Docker cache
|
|
||||||
COPY package.json yarn.lock ./
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
RUN yarn install
|
|
||||||
|
|
||||||
# Copy the rest of the application
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Expose port 5000
|
|
||||||
EXPOSE 5000
|
|
||||||
|
|
||||||
# Start the application
|
|
||||||
CMD ["yarn", "start"]
|
|
177
LICENSE
|
@ -1,177 +0,0 @@
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
108
README.md
|
@ -1,108 +0,0 @@
|
||||||
# dm.sij.law
|
|
||||||
This repo is cloned from the official Matrix.to repo on Github. I've added a Dockerfile and will make modifications in the future. The current version is live at [dm.sij.law](https://dm.sij.law)
|
|
||||||
|
|
||||||
## First clone the repo
|
|
||||||
```bash
|
|
||||||
git clone https://sij.ai/sij/env.esq.git
|
|
||||||
```
|
|
||||||
|
|
||||||
## Next build the image
|
|
||||||
```bash
|
|
||||||
docker build -t matrix-to .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Then run it
|
|
||||||
```bash
|
|
||||||
docker run -d \
|
|
||||||
--name matrix-to \
|
|
||||||
-p 3636:5000 \
|
|
||||||
matrix-to
|
|
||||||
```
|
|
||||||
|
|
||||||
# EVERYTHING BELOW HERE IS ORIGINAL DOCUMENTATION
|
|
||||||
|
|
||||||
## Matrix.to
|
|
||||||
|
|
||||||
Matrix.to is a simple url redirection service for the Matrix.org ecosystem
|
|
||||||
which lets users share links to matrix entities without being tied to a
|
|
||||||
specific app.
|
|
||||||
Stylistically it serves as a landing page for rooms and communities.
|
|
||||||
|
|
||||||
## How can I put a badge on my website linking to my matrix room?
|
|
||||||
|
|
||||||
You can use the badge image we've put up at https://matrix.to/img/matrix-badge.svg, and use it in a link like this:
|
|
||||||
|
|
||||||
[![Chat on Matrix](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#matrix.to:matrix.org)
|
|
||||||
|
|
||||||
You can use this Markdown:
|
|
||||||
```md
|
|
||||||
[![Chat on Matrix](https://matrix.to/img/matrix-badge.svg)](https://matrix.to/#/#matrix.to:matrix.org)
|
|
||||||
```
|
|
||||||
|
|
||||||
Or this HTML:
|
|
||||||
|
|
||||||
```html
|
|
||||||
<a href="https://matrix.to/#/#matrix.to:matrix.org" rel="noopener" target="_blank"><img src="https://matrix.to/img/matrix-badge.svg" alt="Chat on Matrix"></a>
|
|
||||||
```
|
|
||||||
|
|
||||||
to show the badge.
|
|
||||||
|
|
||||||
## How does matrix.to work?
|
|
||||||
|
|
||||||
Matrix.to preserves user privacy by not sharing any information about the links
|
|
||||||
being followed with the Matrix.to server - the redirection is calculated
|
|
||||||
entirely clientside using JavaScript, and the link details is hidden behind a
|
|
||||||
fragment to avoid web clients leaking it to the server. However, acting as a
|
|
||||||
landing page it may leak your ip to any number of homeservers involved with the
|
|
||||||
entity linked to while fetching previews. There is an opt out under which no
|
|
||||||
previews will be loaded.
|
|
||||||
|
|
||||||
Anyone is welcome to host their own version of the Matrix.to app - Matrix.to is
|
|
||||||
**not** a single point of failure on the Matrix ecosystem; if the matrix.to
|
|
||||||
deployment ever failed, users could trivially copy the room/user/message
|
|
||||||
details out of the URLs and follow them manually, or change the hostname to
|
|
||||||
point at an alternative deployment of the service. The Matrix.to service could
|
|
||||||
also be hosted in an immutable/signed environment such as IPFS to further
|
|
||||||
increase its availability and avoid tampering.
|
|
||||||
|
|
||||||
## URL Scheme
|
|
||||||
|
|
||||||
The matrix.to URL scheme is
|
|
||||||
|
|
||||||
| Entity type: | Example URL |
|
|
||||||
|--------------|-------------------------------------------------------------------|
|
|
||||||
| Rooms: | https://matrix.to/#/#matrix:matrix.org |
|
|
||||||
| Rooms by ID: | https://matrix.to/#/!cURbafjkfsMDVwdRDQ:matrix.org |
|
|
||||||
| Users: | https://matrix.to/#/@matthew:matrix.org |
|
|
||||||
| Messages: | https://matrix.to/#/#matrix:matrix.org/$1448831580433WbpiJ:jki.re |
|
|
||||||
|
|
||||||
The #/ component is mandatory and exists to avoid leaking the target URL to the
|
|
||||||
server hosting matrix.to.
|
|
||||||
|
|
||||||
Note that linking to rooms by ID should only be used for rooms to which the
|
|
||||||
target user has been invited: these links cannot be assumed to work for all
|
|
||||||
visitors.
|
|
||||||
|
|
||||||
(Technically the # and @ in the URL fragment should probably be escaped, but in
|
|
||||||
practice for legibility we bend the rules and include it verbatim)
|
|
||||||
|
|
||||||
### Optional parameters
|
|
||||||
|
|
||||||
https://matrix.to/#/#matrix:matrix.org?web-instance[element.io]=chat.mozilla.org
|
|
||||||
|
|
||||||
- `client`, e.g. `client=im.fluffychat`, `client=element.io`
|
|
||||||
- `web-instance[]`, e.g. `web-instance[element.io]=chat.mozilla.org`.
|
|
||||||
- For [matrix.to](https://matrix.to/), we have a list of [trusted web instances configured](src/open/clients/Element.js) (see `trustedWebInstances`).
|
|
||||||
- `via`, e.g. `via=mozilla.org`
|
|
||||||
|
|
||||||
You can discuss matrix.to in
|
|
||||||
[`#matrix.to:matrix.org`](https://matrix.to/#/#matrix.to:matrix.org)
|
|
||||||
|
|
||||||
## Build Instructions
|
|
||||||
|
|
||||||
1. Install [yarn](https://classic.yarnpkg.com/en/docs/install)
|
|
||||||
1. `git clone https://github.com/matrix-org/matrix.to`
|
|
||||||
1. `cd matrix.to`
|
|
||||||
1. `yarn`
|
|
||||||
1. `yarn start`
|
|
||||||
1. Go to http://localhost:5000 in your browser
|
|
|
@ -16,22 +16,6 @@
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ClientView.isPreferred {
|
|
||||||
border: 3px solid var(--link);
|
|
||||||
box-shadow: 0px 8px 4px rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ClientView .hostedBanner {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 29px;
|
|
||||||
padding: 4px 0;
|
|
||||||
line-height: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 16px;
|
|
||||||
background-color: var(--lightgrey);
|
|
||||||
}
|
|
||||||
|
|
||||||
.ClientView .header {
|
.ClientView .header {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +36,7 @@
|
||||||
height: 60px;
|
height: 60px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: block;
|
display: block;
|
||||||
margin-left: 16px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ClientView .platforms {
|
.ClientView .platforms {
|
||||||
|
|
66
css/main.css
|
@ -21,31 +21,31 @@ limitations under the License.
|
||||||
@import url('open.css');
|
@import url('open.css');
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--app-background: #f4f4f4;
|
--app-background: #f4f4f4;
|
||||||
--background: #ffffff;
|
--background: #ffffff;
|
||||||
--foreground: #000000;
|
--foreground: #000000;
|
||||||
--font: #333333;
|
--font: #333333;
|
||||||
--grey: #666666;
|
--grey: #666666;
|
||||||
--accent: #0098d4;
|
--accent: #0098d4;
|
||||||
--error: #d6001c;
|
--error: #d6001c;
|
||||||
--link: #0098d4;
|
--link: #0098d4;
|
||||||
--borders: #f4f4f4;
|
--borders: #f4f4f4;
|
||||||
--lightgrey: #E6E6E6;
|
--lightgrey: #E6E6E6;
|
||||||
--spinner-stroke-size: 2px;
|
--spinner-stroke-size: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: var(--app-background);
|
background-color: var(--app-background);
|
||||||
background-image: url('../images/background.svg');
|
background-image: url('../images/background.svg');
|
||||||
background-attachment: fixed;
|
background-attachment: fixed;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: auto;
|
background-size: auto;
|
||||||
background-position: center -50px;
|
background-position: center -50px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -54,17 +54,13 @@ body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
noscript {
|
p {
|
||||||
display: block;
|
line-height: 150%;
|
||||||
padding: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p { line-height: 150%; }
|
a {
|
||||||
a { text-decoration: none; }
|
text-decoration: none;
|
||||||
|
}
|
||||||
h1 { font-size: 24px; }
|
|
||||||
h2 { font-size: 21px; }
|
|
||||||
h3 { font-size: 16px; }
|
|
||||||
|
|
||||||
body,
|
body,
|
||||||
button,
|
button,
|
||||||
|
@ -89,12 +85,12 @@ input[type="checkbox"], input[type="radio"] {
|
||||||
|
|
||||||
.RootView {
|
.RootView {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 480px;
|
max-width: 480px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
box-shadow: 0px 18px 24px rgba(0, 0, 0, 0.06);
|
box-shadow: 0px 18px 24px rgba(0, 0, 0, 0.06);
|
||||||
}
|
}
|
||||||
|
@ -104,20 +100,20 @@ input[type="checkbox"], input[type="radio"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media screen and (max-width: 480px) {
|
@media screen and (max-width: 480px) {
|
||||||
body {
|
body {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
border-radius: unset;
|
border-radius: unset;
|
||||||
box-shadow: unset;
|
box-shadow: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +137,7 @@ input[type="checkbox"], input[type="radio"] {
|
||||||
}
|
}
|
||||||
|
|
||||||
a, button.text {
|
a, button.text {
|
||||||
color: var(--link);
|
color: var(--link);
|
||||||
}
|
}
|
||||||
|
|
||||||
button.text {
|
button.text {
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
word-wrap: anywhere;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .avatarContainer {
|
.PreviewView .avatarContainer {
|
||||||
|
@ -22,10 +21,6 @@
|
||||||
height: 64px;
|
height: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.PreviewView .mxSpace .avatar {
|
|
||||||
border-radius: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.PreviewView .defaultAvatar {
|
.PreviewView .defaultAvatar {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
version: '3'
|
|
||||||
services:
|
|
||||||
matrix-to:
|
|
||||||
build: .
|
|
||||||
ports:
|
|
||||||
- "3636:5000"
|
|
|
@ -1,13 +0,0 @@
|
||||||
# Developing
|
|
||||||
Clone the repo and
|
|
||||||
|
|
||||||
```
|
|
||||||
yarn start
|
|
||||||
```
|
|
||||||
|
|
||||||
## Storybook
|
|
||||||
Storybook lets you view components individually.
|
|
||||||
|
|
||||||
```
|
|
||||||
yarn storybook
|
|
||||||
```
|
|
|
@ -1,20 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="99" height="20">
|
|
||||||
<linearGradient id="b" x2="0" y2="100%">
|
|
||||||
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
|
|
||||||
<stop offset="1" stop-opacity=".1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<mask id="a">
|
|
||||||
<rect width="99" height="20" rx="3" fill="#fff"/>
|
|
||||||
</mask>
|
|
||||||
<g mask="url(#a)">
|
|
||||||
<path fill="#555" d="M0 0h42v20H0z"/>
|
|
||||||
<path fill="#46BC99" d="M42 0h59v20H42z"/>
|
|
||||||
<path fill="url(#b)" d="M0 0h99v20H0z"/>
|
|
||||||
</g>
|
|
||||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
|
||||||
<text x="21" y="15" fill="#010101" fill-opacity=".3">matrix</text>
|
|
||||||
<text x="21" y="14">matrix</text>
|
|
||||||
<text x="68.5" y="15" fill="#010101" fill-opacity=".3">join chat</text>
|
|
||||||
<text x="68.5" y="14">join chat</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 781 B |
|
@ -1,19 +0,0 @@
|
||||||
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In -->
|
|
||||||
<svg version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
|
||||||
x="0px" y="0px" width="18px" height="18px" viewBox="0 0 18 18" enable-background="new 0 0 18 18" xml:space="preserve">
|
|
||||||
<defs>
|
|
||||||
</defs>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<circle fill="#FFFFFF" cx="9" cy="9" r="8.5"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path d="M9,0C4,0,0,4,0,9c0,5,4,9,9,9c5,0,9-4,9-9C18,4,14,0,9,0z M1.2,10.8l3.5-2.3c0-0.1,0-0.2,0-0.3c0-1.8,1.3-3.2,3.1-3.4
|
|
||||||
c0.1,0,0.2,0,0.4,0c1.2,0,2.3,0.6,2.9,1.6c0.3-0.1,0.6-0.1,0.9-0.1c0.4,0,0.8,0,1.2,0.1c0.7,0.2,1.4,0.5,2,0.9
|
|
||||||
C14.6,7.1,14,7,13.3,7c-1.2,0-2.2,0.4-2.9,1.4c-0.7,0.9-1.1,2-1.1,3.2c0,1.5-0.4,2.9-1.3,4.2c-0.3,0.4-0.5,0.7-0.8,1
|
|
||||||
C4.2,16.1,1.9,13.8,1.2,10.8z"/>
|
|
||||||
<circle cx="9.5" cy="6.4" r="0.5"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 871 B |
|
@ -1,43 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 181.4 181.9" style="enable-background:new 0 0 181.4 181.9;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:url(#SVGID_1_);}
|
|
||||||
.st1{fill:#F094BE;}
|
|
||||||
.st2{fill:#4D3F92;}
|
|
||||||
.st3{fill:#FFFFFF;}
|
|
||||||
</style>
|
|
||||||
<g id="Capa_1">
|
|
||||||
<rect x="0" y="0" style="color:#FFFFFF" width="181.4" height="181.9" class="st3"/>
|
|
||||||
</g>
|
|
||||||
<g id="Capa_2">
|
|
||||||
<g>
|
|
||||||
<path class="st2" d="M151.6,95.1c1.5-0.3,2.8-1,3.8-2c4-5.3,0.8-11.8-4.5-12.6c-0.8,0-1.5-0.8-1.5-1.5c0-0.3,0-0.5,0-0.5
|
|
||||||
c0.8-0.8,1.5-1.8,2.5-3.3c8.1-10.8,11.8-50.6,3.8-53.7c-9.8-3.3-29.7,6.3-38.3,17.4c-0.5-0.3-1-1-1-1.8c0.3-3-1.3-5.5-3.5-6.8
|
|
||||||
c-4.5-2.3-8.8,0-10.6,3.3c-0.5,0.8-1.3,1.3-2,1c-0.8,0-1.5-0.8-1.5-1.5c-0.5-2.5-2-4.5-4.3-5.5c-4.8-2-9.8,0.8-10.6,5.3
|
|
||||||
c-0.3,0.8-0.8,1.5-1.5,1.5c-0.8,0.3-1.5-0.3-2-1c-1.5-2.3-4-3.8-6.5-3.8c-4,0-7.6,3.3-7.8,7.3v0.3v0.3c0,0.8-0.5,1.5-1,1.8h-0.3
|
|
||||||
c-8.3-10.8-28.5-20.7-38.5-17.4c-8.1,2.8-4.3,42.6,4,53.4c1.5,2,2.8,3.5,3.8,4.5c-0.3,0.8-1,1.5-1.8,1.5c-1.3,0-2.5,0.5-3.5,1.3
|
|
||||||
c-5.3,5-2.3,12.1,3,13.4c0.8,0.3,1.5,1,1.5,1.8c0,0.8-0.5,1.8-1.3,2c-1,0.5-2,1-2.8,2c-4,5.8,0,12.3,5.5,12.3
|
|
||||||
c0.8,0,1.5,0.5,1.8,1.3c0.3,0.8,0.3,1.5-0.5,2c-1.5,1.5-2.3,3.5-2,5.5c0.3,2.8,2,5.3,4.8,6.5c1.5,0.8,3,0.8,4.5,0.5
|
|
||||||
c0.8-0.3,1.5,0,2,0.8c0.5,0.5,0.5,1.5,0.3,2c-0.8,1.5-1,3.3-0.5,5c0.8,2.8,2.8,4.8,5.5,5.5c2.5,0.5,4.3-0.3,5.5-0.8
|
|
||||||
c0.5-0.3-3.3,9.1-6,15.4c-0.8,2,1.3,4.3,3.5,3.3c8.3-3.8,22.2-10.3,22.2-9.8c0.5,5.3,6.5,9.1,12.3,5.3c1.3-0.8,2-2.3,2.3-3.5
|
|
||||||
c0.3-0.8,1-1.5,2-1.5c1,0,1.8,0.5,2,1.5c0.3,1.3,0.8,2.3,1.8,3c5.8,4.5,12.3,0.8,12.8-4.8c0-0.8,0.5-1.5,1.3-1.8
|
|
||||||
c0.8-0.3,1.5,0,2,0.5c1.5,1.5,3.3,2.5,5.3,2.5l0,0c2.5,0,5-1.3,6.5-3.8c1-1.5,1.3-3,1-5c0-0.8,0.3-1.5,0.8-2c0.5-0.5,1.5-0.5,2,0
|
|
||||||
c1.5,0.8,3.3,1.3,5,0.8c2.8-0.5,5-2.8,5.8-5.3c0.5-1.8,0.3-3.5-0.5-5.3c-0.3-0.8-0.3-1.5,0.3-2s1.3-0.8,2-0.8
|
|
||||||
c1.8,0.3,3.3,0.3,4.8-0.5c2.3-1,3.8-3,4.3-5.5c0.5-2.5-0.3-4.8-2-6.5c-0.5-0.5-0.8-1.3-0.5-2s1-1.3,1.8-1.3c1.8,0,3.8-0.5,5-2
|
|
||||||
c4.3-4.5,2.3-10.6-2.5-12.6c-0.8-0.3-1.3-1-1.3-2C150.1,95.8,150.8,95.1,151.6,95.1z"/>
|
|
||||||
<path class="st3" d="M131.4,42.2c0.5,1.5,0.5,3,0,4.5c-0.3,0.8,0,1.5,0.5,2s1.3,0.8,2,0.5c1-0.5,2-0.5,3-0.5c2.3,0,4.3,1,5.8,3
|
|
||||||
c1,1.3,1.8,3,1.5,4.8c0,1.5-0.5,2.8-1.3,4c-0.5,0.5-0.5,1.5,0,2c0.3,0.3,0.5,0.8,1,0.8c1-0.3,2-1,2.8-2c4.5-6.3,5.3-26.2,0.8-27.7
|
|
||||||
c-4.5-1.5-12.3,1.5-17.9,6C130.7,40.1,131.2,40.9,131.4,42.2z"/>
|
|
||||||
<path class="st3" d="M39,63.6c0.3-0.3,0.5-0.5,0.8-0.8c0.5-0.8,0.3-1.5,0-2C38.5,59,38.2,57,38.5,55c0.5-2.8,2.8-5,5.5-5.8
|
|
||||||
c1.5-0.5,3-0.3,4.5,0.3c0.8,0.3,1.5,0,2-0.5c0.5-0.5,0.8-1.3,0.5-2c-0.5-1.5-0.5-3,0-4.5c0.3-1,0.8-2,1.5-2.8
|
|
||||||
c-5.5-4.5-13.9-7.8-18.4-6.3S30.4,54.8,35,61.1C36,62.6,37.2,63.3,39,63.6z"/>
|
|
||||||
<g>
|
|
||||||
<circle class="st3" cx="60.9" cy="94.6" r="9.3"/>
|
|
||||||
<path class="st3" d="M100.7,94.6c0,5.3-4.3,9.3-9.3,9.3c-5.3,0-9.3-4.3-9.3-9.3S100.7,89.3,100.7,94.6z"/>
|
|
||||||
<circle class="st3" cx="121.6" cy="94.6" r="9.3"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.3 KiB |
BIN
images/client-icons/fractal.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
|
@ -1,55 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg height="128px" viewBox="0 0 128 128" width="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="8" x2="58" y1="69.999985" y2="69.999985">
|
|
||||||
<stop offset="0" stop-color="#4aaac9"/>
|
|
||||||
<stop offset="0.16" stop-color="#8bddf7"/>
|
|
||||||
<stop offset="0.32" stop-color="#4aaac9"/>
|
|
||||||
<stop offset="1" stop-color="#4aaac9"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="b" gradientUnits="userSpaceOnUse" x1="31.462524" x2="39" y1="113.997253" y2="113.997253">
|
|
||||||
<stop offset="0" stop-color="#4aaac9"/>
|
|
||||||
<stop offset="0.469318" stop-color="#74d7f7"/>
|
|
||||||
<stop offset="1" stop-color="#4aaac9"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="104" x2="120" y1="84" y2="84">
|
|
||||||
<stop offset="0" stop-color="#1a5fb4"/>
|
|
||||||
<stop offset="0.5" stop-color="#4296ff"/>
|
|
||||||
<stop offset="1" stop-color="#1a5fb4"/>
|
|
||||||
</linearGradient>
|
|
||||||
<clipPath id="d">
|
|
||||||
<path d="m 8 24 h 97 v 84 h -97 z m 0 0"/>
|
|
||||||
</clipPath>
|
|
||||||
<clipPath id="e">
|
|
||||||
<path d="m 24 24 h 80 c 8.835938 0 16 7.164062 16 16 v 52 c 0 8.835938 -7.164062 16 -16 16 h -80 c -8.835938 0 -16 -7.164062 -16 -16 v -52 c 0 -8.835938 7.164062 -16 16 -16 z m 0 0"/>
|
|
||||||
</clipPath>
|
|
||||||
<linearGradient id="f" gradientUnits="userSpaceOnUse" x1="55.608135" x2="71.783539" y1="100" y2="48.532928">
|
|
||||||
<stop offset="0" stop-color="#81dffe"/>
|
|
||||||
<stop offset="1" stop-color="#9bf8fe"/>
|
|
||||||
</linearGradient>
|
|
||||||
<filter id="g" height="100%" width="100%" x="0%" y="0%">
|
|
||||||
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
|
||||||
</filter>
|
|
||||||
<mask id="h">
|
|
||||||
<g filter="url(#g)">
|
|
||||||
<rect fill-opacity="0.35" height="128" width="128"/>
|
|
||||||
</g>
|
|
||||||
</mask>
|
|
||||||
<clipPath id="i">
|
|
||||||
<rect height="152" width="192"/>
|
|
||||||
</clipPath>
|
|
||||||
<path d="m 24 28 h 72 c 8.835938 0 16 7.164062 16 16 v 52 c 0 8.835938 -7.164062 16 -16 16 h -72 c -8.835938 0 -16 -7.164062 -16 -16 v -52 c 0 -8.835938 7.164062 -16 16 -16 z m 0 0" fill="url(#a)"/>
|
|
||||||
<path d="m 24 28 h 80 c 8.835938 0 16 7.164062 16 16 v 48 c 0 8.835938 -7.164062 16 -16 16 h -80 c -8.835938 0 -16 -7.164062 -16 -16 v -48 c 0 -8.835938 7.164062 -16 16 -16 z m 0 0" fill="#53bde0"/>
|
|
||||||
<path d="m 24 100 v 12 h 4 c 2.210938 0 4 1.789062 4 4 v 7 c 0 1.992188 1.183594 3.792969 3.011719 4.585938 c 1.828125 0.789062 3.953125 0.417968 5.40625 -0.945313 l 13.523437 -12.707031 c 1.324219 -1.242188 3.070313 -1.933594 4.882813 -1.933594 h 9.175781 v -12 z m 0 0" fill="url(#b)" fill-rule="evenodd"/>
|
|
||||||
<path d="m 102 58.566406 h 2 c 8.835938 0 16 7.164063 16 16 v 21.433594 c 0 8.835938 -7.164062 16 -16 16 h -2 c -8.835938 0 -16 -7.164062 -16 -16 v -21.433594 c 0 -8.835937 7.164062 -16 16 -16 z m 0 0" fill="url(#c)"/>
|
|
||||||
<path d="m 86 87 h 18 v 25 h -18 z m 0 0" fill="#1a5fb4"/>
|
|
||||||
<path d="m 48 24 h 56 c 8.835938 0 16 7.164062 16 16 v 52 c 0 8.835938 -7.164062 16 -16 16 h -56 c -8.835938 0 -16 -7.164062 -16 -16 v -52 c 0 -8.835938 7.164062 -16 16 -16 z m 0 0" fill="#3584e4"/>
|
|
||||||
<g clip-path="url(#d)">
|
|
||||||
<g clip-path="url(#e)">
|
|
||||||
<path d="m 78.804688 16.023438 l 0.527343 2.460937 c -1.207031 -0.082031 -2.417969 4.964844 -3.621093 4.988281 c -19.335938 0.371094 -38.003907 14.230469 -39.148438 34.546875 c -0.835938 14.761719 9.570312 29.839844 25.15625 30.488281 c 10.371094 0.433594 20.96875 -6.957031 21.242188 -17.925781 c 0.179687 -7.078125 -4.953126 -14.3125 -12.488282 -14.355469 c -4.683594 -0.027343 -9.484375 3.425782 -9.398437 8.429688 c 0.074219 2.980469 2.300781 6.042969 5.511719 5.902344 c 1.8125 -0.082032 3.691406 -1.488282 3.539062 -3.453125 c -0.078125 -1.042969 -0.921875 -2.128907 -2.0625 -1.996094 c -0.5625 0.066406 -1.148438 0.539063 -1.046875 1.15625 c 0.070313 0.273437 0.285156 0.570313 0.597656 0.5 c 0.121094 -0.03125 0.25 -0.144531 0.214844 -0.28125 c 0 -0.042969 -0.070313 -0.09375 -0.113281 -0.074219 c 0 0.003906 -0.070313 0.023438 0 0.035156 v 0.007813 v -0.003906 v 0.035156 c 0 0.050781 -0.09375 0.050781 -0.136719 0.03125 c -0.121094 -0.066406 -0.113281 -0.242187 -0.070313 -0.347656 c 0.164063 -0.265625 0.542969 -0.230469 0.777344 -0.074219 c 0.519532 0.367188 0.429688 1.117188 0.070313 1.558594 c -0.710938 0.898437 -2.074219 0.726562 -2.867188 0.042968 c -1.5 -1.28125 -1.167969 -3.601562 0.070313 -4.941406 c 2.167968 -2.367187 5.929687 -1.792968 8.074218 0.28125 c 3.601563 3.476563 2.652344 9.308594 -0.675781 12.597656 c -5.359375 5.292969 -14.109375 3.800782 -18.992187 -1.324218 c -7.570313 -7.953125 -5.304688 -20.664063 2.335937 -27.6875 c 11.480469 -10.550782 29.507813 -7.242188 39.363281 3.785156 c 14.414063 16.121094 9.6875 41.066406 -5.855468 54.582031 c -11.121094 9.226563 -22.246094 15.429688 -32.949219 19.4375 c -13.058594 75.445313 -75.230469 6.835938 -81.039063 -4.195312 l 0.285157 -105.054688 z m 0 0" fill="url(#f)"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path d="m 24 106 v 2 h 4 c 2.210938 0 4 1.789062 4 4 v 7 c 0 1.992188 1.183594 3.792969 3.011719 4.585938 c 1.828125 0.789062 3.953125 0.417968 5.40625 -0.945313 l 13.523437 -12.707031 c 1.324219 -1.242188 3.070313 -1.933594 4.882813 -1.933594 h 9.175781 v -2 z m 0 0" fill="#81dffe" fill-rule="evenodd"/>
|
|
||||||
<g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -8 -16)">
|
|
||||||
<path d="m 173 17 h 8 c 1.65625 0 3 1.34375 3 3 v 7 c 0 1.65625 -1.34375 3 -3 3 h -8 c -1.65625 0 -3 -1.34375 -3 -3 v -7 c 0 -1.65625 1.34375 -3 3 -3 z m 0 0" fill="#241f31"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 5.5 KiB |
|
@ -1,34 +0,0 @@
|
||||||
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M51 12C51 10.8954 50.1046 10 49 10H13C11.8954 10 11 10.8954 11 12V38C11 39.1046 11.8954 40 13 40H30.5858C30.851 40 31.1054 40.1054 31.2929 40.2929L39.2929 48.2929C39.9229 48.9229 41 48.4767 41 47.5858V41C41 40.4477 41.4477 40 42 40H49C50.1046 40 51 39.1046 51 38V12Z" fill="url(#paint0_linear)"/>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M11 37V38C11 39.1046 11.8954 40 13 40H30.5858C30.851 40 31.1054 40.1054 31.2929 40.2929L39.2929 48.2929C39.9229 48.9229 41 48.4767 41 47.5858V46.5858C41 47.4767 39.9229 47.9229 39.2929 47.2929L31.2929 39.2929C31.1054 39.1054 30.851 39 30.5858 39H13C11.8954 39 11 38.1046 11 37ZM41 41C41 40.4477 41.4477 40 42 40H49C50.1046 40 51 39.1046 51 38V37C51 38.1046 50.1046 39 49 39H42C41.4477 39 41 39.4477 41 40V41Z" fill="#000405" fill-opacity="0.1"/>
|
|
||||||
<path d="M8 10C8 8.89543 8.89543 8 10 8H46C47.1046 8 48 8.89543 48 10V36C48 37.1046 47.1046 38 46 38H28.4142C28.149 38 27.8946 38.1054 27.7071 38.2929L19.7071 46.2929C19.0771 46.9229 18 46.4767 18 45.5858V39C18 38.4477 17.5523 38 17 38H10C8.89543 38 8 37.1046 8 36V10Z" fill="url(#paint1_linear)"/>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 35V36C8 37.1046 8.89543 38 10 38H17C17.5523 38 18 38.4477 18 39V38C18 37.4477 17.5523 37 17 37H10C8.89543 37 8 36.1046 8 35ZM18 44.5858V45.5858C18 46.4767 19.0771 46.9229 19.7071 46.2929L27.7071 38.2929C27.8946 38.1054 28.149 38 28.4142 38H46C47.1046 38 48 37.1046 48 36V35C48 36.1046 47.1046 37 46 37H28.4142C28.149 37 27.8946 37.1054 27.7071 37.2929L19.7071 45.2929C19.0771 45.9229 18 45.4767 18 44.5858Z" fill="#031C5A" fill-opacity="0.1"/>
|
|
||||||
<rect x="13" y="14" width="30" height="4" rx="2" fill="url(#paint2_linear)"/>
|
|
||||||
<rect x="12.5" y="13.5" width="31" height="5" rx="2.5" stroke="#004E6E" stroke-opacity="0.1"/>
|
|
||||||
<rect x="13" y="21" width="25" height="4" rx="2" fill="url(#paint3_linear)"/>
|
|
||||||
<rect x="12.5" y="20.5" width="26" height="5" rx="2.5" stroke="#004E6E" stroke-opacity="0.1"/>
|
|
||||||
<rect x="13" y="28" width="20" height="4" rx="2" fill="url(#paint4_linear)"/>
|
|
||||||
<rect x="12.5" y="27.5" width="21" height="5" rx="2.5" stroke="#004E6E" stroke-opacity="0.1"/>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="paint0_linear" x1="51" y1="10" x2="11" y2="50" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#6EB4D9"/>
|
|
||||||
<stop offset="1" stop-color="#004E6E"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint1_linear" x1="8" y1="8" x2="48" y2="48" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#44F0D3"/>
|
|
||||||
<stop offset="1" stop-color="#3DAEE9"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint2_linear" x1="43" y1="18" x2="19.5854" y2="-11.2683" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#D1D5D9"/>
|
|
||||||
<stop offset="1" stop-color="#FCFFFF"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint3_linear" x1="38" y1="25" x2="14.02" y2="0.0208158" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#D1D5D9"/>
|
|
||||||
<stop offset="1" stop-color="#FCFFFF"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint4_linear" x1="33" y1="32" x2="9.39344" y2="12.3279" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#D1D5D9"/>
|
|
||||||
<stop offset="1" stop-color="#FCFFFF"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 118 KiB |
|
@ -1,65 +0,0 @@
|
||||||
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M452.1 306.5H452.16C474.2 229.45 570.24 191.84 668.11 191.84C735.74 191.84 796.45 213.25 838.07 247.24C813.232 248.411 788.708 253.285 765.31 261.7C798.94 274.2 827.83 293.43 849.24 317.22C833.087 314.439 816.707 313.201 800.32 313.52C840.596 371.863 862.114 441.105 862 512C862 705.3 705.3 862 512 862C321.68 862 162 702.65 162 512C162 481.89 166 450.8 173.77 421.64C175.81 415.52 178.65 409.65 182.42 407.5C187.14 404.81 191.44 412.83 192.13 415.44C197.248 434.61 204.134 453.263 212.7 471.16C211.95 431.2 229.02 394.8 252.5 363.32C268.16 342.33 282.68 322.88 289.38 266.75C289.83 262.98 293.4 260.27 297.01 261.45C347.97 278.13 375.21 362.99 370.98 433.95C399.13 437.98 399 408.57 399 408.57C390 380.91 396 329.5 452 306.5H452.1Z" fill="url(#paint0_linear_1_4)"/>
|
|
||||||
<path opacity="0.9" d="M850.55 422.87C859.06 615.37 700.81 781.34 507.84 781.34C327.19 781.34 179.16 641.71 165.77 464.49C163.381 481.085 162.125 497.824 162.01 514.59C163.38 704.21 322.67 862 512.01 862C705.31 862 862.01 705.3 862.01 512C862.01 481.2 858.02 451.33 850.55 422.87Z" fill="url(#paint1_radial_1_4)"/>
|
|
||||||
<path style="mix-blend-mode:screen" d="M503.47 332.01C499.7 325.34 482.29 315.47 474.68 313.75C503.48 221.5 650.2 193.18 740 209.5C777.37 216.3 823.91 236.66 838.07 247.24C796.45 213.25 735.73 191.84 668.11 191.84C570.24 191.84 474.2 229.45 452.16 306.5H452C396 329.5 390 380.93 399 408.58C407.64 375.59 448.75 335.05 503.47 332.01Z" fill="url(#paint2_radial_1_4)"/>
|
|
||||||
<path d="M605.18 268.3C526.56 283.77 500.87 288.83 474.56 313.84C504.11 235.61 579.54 219.75 669.42 255.41C648.028 259.82 626.615 264.12 605.18 268.31V268.3Z" fill="url(#paint3_linear_1_4)"/>
|
|
||||||
<path d="M181 410.93C159.52 498.87 176.12 602.23 273.7 688.97C244.65 657.2 209.18 539.9 287.45 456.1C292.72 450.45 301.79 454.6 302.08 462.32C308.53 636.48 449.06 742.85 611.08 722.96C560.88 720.14 394.86 661.99 518.36 638.99C582.91 626.96 684.12 608.11 684.12 517.29C684.12 370.07 570.29 327.03 501.26 333.43C454.02 337.81 411.97 367.79 399.03 408.56C404 424.63 384.19 435.88 370.98 433.99C375.22 363.04 347.98 278.13 297.01 261.45C293.41 260.27 289.83 262.98 289.38 266.75C282.68 322.88 268.16 342.33 252.51 363.32C229.02 394.81 211.95 431.2 212.7 471.16C204.134 453.263 197.248 434.61 192.13 415.44C191.56 413.28 188.43 407.25 184.65 406.97C182.6 406.82 181.51 408.82 181 410.93Z" fill="url(#paint4_radial_1_4)"/>
|
|
||||||
<path style="mix-blend-mode:screen" d="M474.99 647.9C570.03 725.07 761.16 667.21 761.16 479.58C684 596.54 585.72 677.22 475 647.9H474.99Z" fill="url(#paint5_linear_1_4)"/>
|
|
||||||
<path style="mix-blend-mode:screen" d="M287.45 456.1C288.314 455.133 289.403 454.394 290.62 453.947C291.838 453.501 293.146 453.361 294.43 453.54C224.37 538.99 280.88 689.06 319.66 725.93C321.83 732.07 282.87 700.14 277.5 692.67C248 667.64 205.72 543.61 287.45 456.1Z" fill="url(#paint6_linear_1_4)"/>
|
|
||||||
<path d="M512 654.97C607.06 654.97 684.13 592.09 684.13 514.52C684.13 436.95 607.06 374.07 512 374.07C430.9 374.07 339.83 426.83 339.87 516.57C339.91 655.24 486.41 735.02 611.29 722.94C601.91 721.85 543.39 718.74 503.84 674C500.27 669.97 494.08 662.93 496.89 658.36C499.69 653.79 507.41 654.96 511.99 654.96L512 654.97Z" fill="url(#paint7_linear_1_4)"/>
|
|
||||||
<path opacity="0.6" d="M665.38 450.7L529.34 580.88C517.27 589.46 504.42 590.08 491.74 582.3L358.31 451.18C362.117 445.062 366.396 439.251 371.11 433.8L385.11 446.9C420.15 479.74 448.48 506.27 488.41 540.35C506.43 555.73 512.03 555.43 529.71 540.35C575.39 501.35 608.8 471.85 652.23 433.06C657.07 438.586 661.464 444.488 665.37 450.71L665.38 450.7Z" fill="white"/>
|
|
||||||
<mask id="mask0_1_4" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="339" y="448" width="346" height="277">
|
|
||||||
<path d="M684.13 514.52C684.13 592.09 607.06 654.97 512 654.97C507.41 654.97 499.7 653.79 496.89 658.37C494.08 662.93 500.27 669.97 503.84 674C541 716.04 594.91 721.33 609.06 722.72L611.29 722.94C486.41 735.02 339.91 655.24 339.87 516.57C339.74 493.482 346.165 470.831 358.4 451.25L492.48 573.03C502.02 581.69 518.09 581.69 527.63 573.03L664.25 448.94C676.95 468.52 684.13 490.84 684.13 514.52Z" fill="white"/>
|
|
||||||
</mask>
|
|
||||||
<g mask="url(#mask0_1_4)">
|
|
||||||
<path opacity="0.7" d="M300 352.53H735.07V747H300V352.53Z" fill="url(#paint8_linear_1_4)"/>
|
|
||||||
<g filter="url(#filter0_f_1_4)">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M472.04 573.85C446.69 547.47 370.77 459.82 370.77 459.82L376.64 460.08L495.5 548.85C504.4 555.32 517.1 555.25 525.92 548.7L642.47 460.2L648.65 459.71C648.65 459.71 575.21 545.28 547.08 573.47C518.95 601.66 497.39 600.23 472.04 573.85Z" fill="#458FCD"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path d="M536.15 303.81C554.57 298.01 552.95 279.78 552.95 279.78C552.95 279.78 543.74 268.93 525.49 274.94C508.41 280.57 505.76 292.74 505.76 292.74C505.76 292.74 515.09 310.44 536.15 303.81Z" fill="white"/>
|
|
||||||
<defs>
|
|
||||||
<filter id="filter0_f_1_4" x="338.77" y="427.71" width="341.88" height="198.416" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
||||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
||||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
|
||||||
<feGaussianBlur stdDeviation="16" result="effect1_foregroundBlur_1_4"/>
|
|
||||||
</filter>
|
|
||||||
<linearGradient id="paint0_linear_1_4" x1="283.48" y1="307.2" x2="776.88" y2="767.42" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#1B91F3"/>
|
|
||||||
<stop offset="1" stop-color="#0B68CB"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint1_radial_1_4" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(282.57 465.55) rotate(66.5177) scale(295.96 283.519)">
|
|
||||||
<stop offset="0.53" stop-color="#0B4186" stop-opacity="0"/>
|
|
||||||
<stop offset="1" stop-color="#0B4186" stop-opacity="0.45"/>
|
|
||||||
</radialGradient>
|
|
||||||
<radialGradient id="paint2_radial_1_4" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(521 344) rotate(-127.997) scale(63.2702 104.698)">
|
|
||||||
<stop stop-color="#EF3ACC" stop-opacity="0"/>
|
|
||||||
<stop offset="1" stop-color="#EF3ACC" stop-opacity="0.64"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint3_linear_1_4" x1="420.77" y1="425.01" x2="598.31" y2="227.37" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#0F5DB0"/>
|
|
||||||
<stop offset="1" stop-color="#0F5DB0" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<radialGradient id="paint4_radial_1_4" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(380 702.7) rotate(-64.2624) scale(461.716 570.355)">
|
|
||||||
<stop offset="0.02" stop-color="#094188"/>
|
|
||||||
<stop offset="0.97" stop-color="#0B4186" stop-opacity="0"/>
|
|
||||||
</radialGradient>
|
|
||||||
<linearGradient id="paint5_linear_1_4" x1="731.92" y1="568.11" x2="649.37" y2="770.8" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#E247C4" stop-opacity="0"/>
|
|
||||||
<stop offset="1" stop-color="#E247C4" stop-opacity="0.64"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint6_linear_1_4" x1="220.01" y1="386.34" x2="292.74" y2="679.06" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop offset="0.1" stop-color="#EF3ACC"/>
|
|
||||||
<stop offset="1" stop-color="#EF3ACC" stop-opacity="0"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint7_linear_1_4" x1="512" y1="425.5" x2="512" y2="721.5" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="white"/>
|
|
||||||
<stop offset="0.91" stop-color="#BEE1FE"/>
|
|
||||||
<stop offset="1" stop-color="#96CEFD"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="paint8_linear_1_4" x1="517.54" y1="593" x2="517.54" y2="717" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#BCE0FD"/>
|
|
||||||
<stop offset="1" stop-color="#88CCFC"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 24 KiB |
28
index.html
|
@ -1,26 +1,16 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>You're invited to talk on Matrix</title>
|
<title>You're invited to talk on Matrix</title>
|
||||||
<meta name="description" content="You're invited to talk on Matrix">
|
<meta name="description" content="You're invited to talk on Matrix">
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||||
<link rel="stylesheet" type="text/css" href="css/main.css">
|
<link rel="stylesheet" type="text/css" href="css/main.css">
|
||||||
<meta property="twitter:card" content="summary"/>
|
|
||||||
<meta property="twitter:image" content="https://matrix.org/blog/img/matrix-logo.png"/>
|
|
||||||
<meta property="twitter:site" content="@matrixdotorg"/>
|
|
||||||
<meta property="twitter:title" content="Matrix - Decentralised and secure communication"/>
|
|
||||||
<meta property="twitter:description" content="You're invited to talk on Matrix. If you don't already have a client this link will help you pick one, and join the conversation. If you already have one, this link will help you join the conversation"/>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script id="main" type="module">
|
<script id="main" type="module">
|
||||||
import {main} from "./src/main.js";
|
import {main} from "./src/main.js";
|
||||||
main(document.body);
|
main(document.body);
|
||||||
</script>
|
</script>
|
||||||
<noscript>
|
|
||||||
<h1>Please enable javascript</h1>
|
|
||||||
<p>Matrix.to is a preview service from chat rooms, people and communities on <a href="https://matrix.org">Matrix</a>.</p>
|
|
||||||
<p>It preserves your privacy by only processing what you view on the client side. For this to work, it needs javascript.</p>
|
|
||||||
</noscript>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "matrix.to",
|
"name": "matrix.to",
|
||||||
"version": "1.2.17",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"finalhandler": "^1.1.2",
|
"finalhandler": "^1.1.2",
|
||||||
"mdn-polyfills": "^5.20.0",
|
"mdn-polyfills": "^5.20.0",
|
||||||
"postcss": "^8.4.31",
|
"postcss": "^8.1.1",
|
||||||
"postcss-css-variables": "^0.17.0",
|
"postcss-css-variables": "^0.17.0",
|
||||||
"postcss-flexbugs-fixes": "^4.2.1",
|
"postcss-flexbugs-fixes": "^4.2.1",
|
||||||
"postcss-import": "^12.0.1",
|
"postcss-import": "^12.0.1",
|
||||||
|
|
|
@ -52,16 +52,15 @@ async function build() {
|
||||||
await removeDirIfExists(targetDir);
|
await removeDirIfExists(targetDir);
|
||||||
await fs.mkdir(targetDir);
|
await fs.mkdir(targetDir);
|
||||||
await fs.mkdir(path.join(targetDir, "images"));
|
await fs.mkdir(path.join(targetDir, "images"));
|
||||||
await fs.mkdir(path.join(targetDir, "img")); // contains the badge image for historical reasons, unhashed
|
|
||||||
await fs.mkdir(path.join(targetDir, ".well-known"));
|
await fs.mkdir(path.join(targetDir, ".well-known"));
|
||||||
const assets = new AssetMap(targetDir);
|
const assets = new AssetMap(targetDir);
|
||||||
const imageAssets = await copyFolder(path.join(projectDir, "images"), path.join(targetDir, "images"));
|
const imageAssets = await copyFolder(path.join(projectDir, "images"), path.join(targetDir, "images"));
|
||||||
assets.addSubMap(imageAssets);
|
assets.addSubMap(imageAssets);
|
||||||
await assets.write(`bundle.js`, await buildJs("src/main.js", assets, ["src/polyfill.js"]));
|
await assets.write(`bundle-esm.js`, await buildJs("src/main.js", assets));
|
||||||
|
await assets.write(`bundle-legacy.js`, await buildJsLegacy("src/main.js", assets, ["src/polyfill.js"]));
|
||||||
await assets.write(`bundle.css`, await buildCss("css/main.css", targetDir, assets));
|
await assets.write(`bundle.css`, await buildCss("css/main.css", targetDir, assets));
|
||||||
await assets.writeUnhashed(".well-known/apple-app-site-association", buildAppleAssociatedAppsFile(createClients()));
|
await assets.writeUnhashed(".well-known/apple-app-site-association", buildAppleAssociatedAppsFile(createClients()));
|
||||||
await assets.writeUnhashed("index.html", await buildHtml(assets));
|
await assets.writeUnhashed("index.html", await buildHtml(assets));
|
||||||
await assets.writeUnhashed("img/matrix-badge.svg", await fs.readFile(path.join(projectDir, "images-nohash/matrix-badge.svg")));
|
|
||||||
const globalHash = assets.hashForAll();
|
const globalHash = assets.hashForAll();
|
||||||
console.log(`built matrix.to ${version} (${globalHash}) successfully with ${assets.size} files`);
|
console.log(`built matrix.to ${version} (${globalHash}) successfully with ${assets.size} files`);
|
||||||
}
|
}
|
||||||
|
@ -71,12 +70,9 @@ async function buildHtml(assets) {
|
||||||
const doc = cheerio.load(devHtml);
|
const doc = cheerio.load(devHtml);
|
||||||
doc("link[rel=stylesheet]").attr("href", assets.resolve(`bundle.css`));
|
doc("link[rel=stylesheet]").attr("href", assets.resolve(`bundle.css`));
|
||||||
const mainScripts = [
|
const mainScripts = [
|
||||||
// this is needed to avoid hitting https://github.com/facebook/regenerator/issues/378
|
`<script type="module">import {main} from "./${assets.resolve(`bundle-esm.js`)}"; main(document.body);</script>`,
|
||||||
// which prevents the whole bundle to load, as our CSP headers don't allow unsafe-eval
|
`<script type="text/javascript" nomodule src="${assets.resolve(`bundle-legacy.js`)}"></script>`,
|
||||||
// and I preferred this over disabling strict mode for the whole bundle
|
`<script type="text/javascript" nomodule>bundle.main(document.body);</script>`
|
||||||
`<script type="text/javascript">window.regeneratorRuntime = undefined;</script>`,
|
|
||||||
`<script type="text/javascript" src="${assets.resolve(`bundle.js`)}"></script>`,
|
|
||||||
`<script type="text/javascript">bundle.main(document.body);</script>`
|
|
||||||
];
|
];
|
||||||
doc("script#main").replaceWith(mainScripts.join(""));
|
doc("script#main").replaceWith(mainScripts.join(""));
|
||||||
return doc.html();
|
return doc.html();
|
||||||
|
@ -91,6 +87,19 @@ function createReplaceUrlPlugin(assets) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function buildJs(mainFile, assets, extraFiles = []) {
|
async function buildJs(mainFile, assets, extraFiles = []) {
|
||||||
|
// create js bundle
|
||||||
|
const bundle = await rollup({
|
||||||
|
input: extraFiles.concat(mainFile),
|
||||||
|
plugins: [multi(), terser(), createReplaceUrlPlugin(assets)],
|
||||||
|
});
|
||||||
|
const {output} = await bundle.generate({
|
||||||
|
format: 'es',
|
||||||
|
});
|
||||||
|
const code = output[0].code;
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildJsLegacy(mainFile, assets, extraFiles = []) {
|
||||||
// compile down to whatever IE 11 needs
|
// compile down to whatever IE 11 needs
|
||||||
const babelPlugin = babel.babel({
|
const babelPlugin = babel.babel({
|
||||||
babelHelpers: 'bundled',
|
babelHelpers: 'bundled',
|
||||||
|
@ -124,20 +133,21 @@ async function buildJs(mainFile, assets, extraFiles = []) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildAppleAssociatedAppsFile(clients) {
|
function buildAppleAssociatedAppsFile(clients) {
|
||||||
const appIds = clients.map(c => c.appleAssociatedAppId).flat().filter(id => !!id);
|
const appIds = clients.map(c => c.appleAssociatedAppId).filter(id => !!id);
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
"applinks": {
|
"applinks": {
|
||||||
"details": [
|
"apps": [],
|
||||||
{
|
"details": {
|
||||||
appIDs: appIds,
|
appIDs: appIds,
|
||||||
components: [
|
components: [
|
||||||
{
|
{
|
||||||
"#": "/*",
|
"#": "/*", // only open urls with a fragment, so you can still create links
|
||||||
"comment": "Only open urls with a fragment, so you can still create links"
|
}
|
||||||
}
|
]
|
||||||
]
|
},
|
||||||
}
|
},
|
||||||
]
|
"webcredentials": {
|
||||||
|
"apps": appIds
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -145,7 +155,7 @@ function buildAppleAssociatedAppsFile(clients) {
|
||||||
async function buildCss(entryPath, targetDir, assets) {
|
async function buildCss(entryPath, targetDir, assets) {
|
||||||
entryPath = path.join(projectDir, entryPath);
|
entryPath = path.join(projectDir, entryPath);
|
||||||
const assetUrlMapper = ({absolutePath}) => {
|
const assetUrlMapper = ({absolutePath}) => {
|
||||||
const relPath = absolutePath.slice(projectDir.length);
|
const relPath = absolutePath.substr(projectDir.length);
|
||||||
return assets.resolve(path.join(targetDir, relPath));
|
return assets.resolve(path.join(targetDir, relPath));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -210,7 +220,7 @@ class AssetMap {
|
||||||
if (!resourcePath.startsWith(this._targetDir)) {
|
if (!resourcePath.startsWith(this._targetDir)) {
|
||||||
throw new Error(`absolute path ${resourcePath} that is not within target dir ${this._targetDir}`);
|
throw new Error(`absolute path ${resourcePath} that is not within target dir ${this._targetDir}`);
|
||||||
}
|
}
|
||||||
relPath = resourcePath.slice(this._targetDir.length + 1); // + 1 for the /
|
relPath = resourcePath.substr(this._targetDir.length + 1); // + 1 for the /
|
||||||
}
|
}
|
||||||
return relPath;
|
return relPath;
|
||||||
}
|
}
|
||||||
|
@ -266,7 +276,7 @@ class AssetMap {
|
||||||
if (!assetMap.directory.startsWith(this.directory)) {
|
if (!assetMap.directory.startsWith(this.directory)) {
|
||||||
throw new Error(`map directory doesn't start with this directory: ${assetMap.directory} ${this.directory}`);
|
throw new Error(`map directory doesn't start with this directory: ${assetMap.directory} ${this.directory}`);
|
||||||
}
|
}
|
||||||
const relSubRoot = assetMap.directory.slice(this.directory.length + 1);
|
const relSubRoot = assetMap.directory.substr(this.directory.length + 1);
|
||||||
for (const [key, value] of assetMap._assets.entries()) {
|
for (const [key, value] of assetMap._assets.entries()) {
|
||||||
this._assets.set(path.join(relSubRoot, key), path.join(relSubRoot, value));
|
this._assets.set(path.join(relSubRoot, key), path.join(relSubRoot, value));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
set -e
|
|
||||||
VERSION=$(jq -r ".version" package.json)
|
|
||||||
PACKAGE=matrixto-$VERSION.tar.gz
|
|
||||||
yarn build
|
|
||||||
pushd build
|
|
||||||
tar -czvf ../$PACKAGE ./
|
|
||||||
popd
|
|
||||||
echo $PACKAGE
|
|
|
@ -23,26 +23,23 @@ const projectDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".
|
||||||
|
|
||||||
// Serve up parent directory with cache disabled
|
// Serve up parent directory with cache disabled
|
||||||
const serve = serveStatic(
|
const serve = serveStatic(
|
||||||
projectDir,
|
projectDir,
|
||||||
{
|
{
|
||||||
etag: false,
|
etag: false,
|
||||||
setHeaders: res => {
|
setHeaders: res => {
|
||||||
res.setHeader("Pragma", "no-cache");
|
res.setHeader("Pragma", "no-cache");
|
||||||
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
res.setHeader("Expires", "Wed, 21 Oct 2015 07:28:00 GMT");
|
res.setHeader("Expires", "Wed, 21 Oct 2015 07:28:00 GMT");
|
||||||
// same CSP as matrix.to server is using, so local testing happens under similar environment
|
},
|
||||||
res.setHeader("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src * data:; connect-src *; font-src 'self'; manifest-src 'self'; form-action 'self'; navigate-to *;");
|
index: ['index.html', 'index.htm']
|
||||||
},
|
}
|
||||||
index: ['index.html', 'index.htm']
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
const server = http.createServer(function onRequest (req, res) {
|
const server = http.createServer(function onRequest (req, res) {
|
||||||
console.log(req.method, req.url);
|
console.log(req.method, req.url);
|
||||||
serve(req, res, finalhandler(req, res))
|
serve(req, res, finalhandler(req, res))
|
||||||
});
|
});
|
||||||
|
|
||||||
// Listen
|
// Listen
|
||||||
server.listen(5000);
|
server.listen(5000);
|
||||||
console.log("Listening on port 5000");
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {TemplateView} from "./utils/TemplateView.js";
|
|
||||||
import {LinkKind, IdentifierKind} from "./Link.js";
|
|
||||||
|
|
||||||
export class InvalidUrlView extends TemplateView {
|
|
||||||
render(t, vm) {
|
|
||||||
return t.div({ className: "DisclaimerView card" }, [
|
|
||||||
t.h1("Invalid URL"),
|
|
||||||
t.p([
|
|
||||||
'The link you have entered is not valid. If you like, you can ',
|
|
||||||
t.a({ href: "#/" }, 'return to the home page.')
|
|
||||||
]),
|
|
||||||
vm.validFixes.length ? this._renderValidFixes(t, vm.validFixes) : [],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
_describeRoom(identifierKind) {
|
|
||||||
return identifierKind === IdentifierKind.RoomAlias ? "room alias" : "room";
|
|
||||||
}
|
|
||||||
|
|
||||||
_describeLinkKind(linkKind, identifierKind) {
|
|
||||||
switch (linkKind) {
|
|
||||||
case LinkKind.Room: return `The ${this._describeRoom(identifierKind)} `;
|
|
||||||
case LinkKind.User: return "The user ";
|
|
||||||
case LinkKind.Group: return "The group ";
|
|
||||||
case LinkKind.Event: return `An event in ${this._describeRoom(identifierKind)} `;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_renderValidFixes(t, validFixes) {
|
|
||||||
return t.p([
|
|
||||||
'Did you mean any of the following?',
|
|
||||||
t.ul(validFixes.map(fix =>
|
|
||||||
t.li([
|
|
||||||
this._describeLinkKind(fix.link.kind, fix.link.identifierKind),
|
|
||||||
t.a({ href: fix.url }, fix.link.identifier)
|
|
||||||
])
|
|
||||||
))
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {ViewModel} from "./utils/ViewModel.js";
|
|
||||||
import {tryFixUrl} from "./Link.js";
|
|
||||||
|
|
||||||
export class InvalidUrlViewModel extends ViewModel {
|
|
||||||
constructor(options) {
|
|
||||||
super(options);
|
|
||||||
this.validFixes = tryFixUrl(options.fragment);
|
|
||||||
}
|
|
||||||
}
|
|
255
src/Link.js
|
@ -24,70 +24,38 @@ const EVENTID_PATTERN = /^$([^:]+):(.+)$/;
|
||||||
const GROUPID_PATTERN = /^\+([^:]+):(.+)$/;
|
const GROUPID_PATTERN = /^\+([^:]+):(.+)$/;
|
||||||
|
|
||||||
export const IdentifierKind = createEnum(
|
export const IdentifierKind = createEnum(
|
||||||
"RoomId",
|
"RoomId",
|
||||||
"RoomAlias",
|
"RoomAlias",
|
||||||
"UserId",
|
"UserId",
|
||||||
"GroupId",
|
"GroupId",
|
||||||
);
|
);
|
||||||
|
|
||||||
function asPrefix(identifierKind) {
|
function asPrefix(identifierKind) {
|
||||||
switch (identifierKind) {
|
switch (identifierKind) {
|
||||||
case IdentifierKind.RoomId: return "!";
|
case IdentifierKind.RoomId: return "!";
|
||||||
case IdentifierKind.RoomAlias: return "#";
|
case IdentifierKind.RoomAlias: return "#";
|
||||||
case IdentifierKind.GroupId: return "+";
|
case IdentifierKind.GroupId: return "+";
|
||||||
case IdentifierKind.UserId: return "@";
|
case IdentifierKind.UserId: return "@";
|
||||||
default: throw new Error("invalid id kind " + identifierKind);
|
default: throw new Error("invalid id kind " + identifierKind);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function getWebInstanceMap(queryParams) {
|
|
||||||
const prefix = "web-instance[";
|
|
||||||
const postfix = "]";
|
|
||||||
const webInstanceParams = queryParams.filter(([key]) => key.startsWith(prefix) && key.endsWith(postfix));
|
|
||||||
const webInstances = webInstanceParams.map(([key, value]) => {
|
|
||||||
const noPrefix = key.slice(prefix.length);
|
|
||||||
const clientId = noPrefix.slice(0, -postfix.length);
|
|
||||||
return [clientId, value];
|
|
||||||
});
|
|
||||||
return webInstances.reduce((map, [clientId, host]) => {
|
|
||||||
map[clientId] = host;
|
|
||||||
return map;
|
|
||||||
}, {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLabelForLinkKind(kind) {
|
export function getLabelForLinkKind(kind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case LinkKind.User: return "Start chat";
|
case LinkKind.User: return "Start chat";
|
||||||
case LinkKind.Room: return "View room";
|
case LinkKind.Room: return "View room";
|
||||||
case LinkKind.Group: return "View community";
|
case LinkKind.Group: return "View community";
|
||||||
case LinkKind.Event: return "View message";
|
case LinkKind.Event: return "View message";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LinkKind = createEnum(
|
export const LinkKind = createEnum(
|
||||||
"Room",
|
"Room",
|
||||||
"User",
|
"User",
|
||||||
"Group",
|
"Group",
|
||||||
"Event"
|
"Event"
|
||||||
)
|
)
|
||||||
|
|
||||||
export function tryFixUrl(fragment) {
|
|
||||||
const attempts = [];
|
|
||||||
const afterHash = fragment.substring(fragment.startsWith("#/") ? 2 : 1);
|
|
||||||
attempts.push('#/@' + afterHash);
|
|
||||||
attempts.push('#/#' + afterHash);
|
|
||||||
attempts.push('#/!' + afterHash);
|
|
||||||
|
|
||||||
const validAttempts = [];
|
|
||||||
for (const attempt of [...new Set(attempts)]) {
|
|
||||||
const link = Link.parseFragment(attempt);
|
|
||||||
if (link) {
|
|
||||||
validAttempts.push({ url: attempt, link });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return validAttempts;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Link {
|
export class Link {
|
||||||
static validateIdentifier(identifier) {
|
static validateIdentifier(identifier) {
|
||||||
return !!(
|
return !!(
|
||||||
|
@ -98,115 +66,98 @@ export class Link {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static parseIdentifier(identifier) {
|
static parse(fragment) {
|
||||||
return Link._parse(identifier);
|
if (!fragment) {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
let [linkStr, queryParamsStr] = fragment.split("?");
|
||||||
|
|
||||||
static parseFragment(fragment) {
|
let viaServers = [];
|
||||||
if (!fragment) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let [linkStr, queryParamsStr] = fragment.split("?");
|
|
||||||
if (!linkStr.startsWith("#/")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
linkStr = linkStr.slice(2);
|
|
||||||
const [identifier, eventId] = linkStr.split("/");
|
|
||||||
|
|
||||||
let viaServers = [];
|
|
||||||
let clientId = null;
|
let clientId = null;
|
||||||
let webInstances = {};
|
if (queryParamsStr) {
|
||||||
if (queryParamsStr) {
|
const queryParams = queryParamsStr.split("&").map(pair => pair.split("="));
|
||||||
const queryParams = queryParamsStr.split("&").map(pair => {
|
viaServers = queryParams
|
||||||
const [key, value] = pair.split("=");
|
.filter(([key, value]) => key === "via")
|
||||||
return [decodeURIComponent(key), decodeURIComponent(value)];
|
.map(([,value]) => value);
|
||||||
});
|
|
||||||
viaServers = queryParams
|
|
||||||
.filter(([key, value]) => key === "via")
|
|
||||||
.map(([,value]) => value);
|
|
||||||
const clientParam = queryParams.find(([key]) => key === "client");
|
const clientParam = queryParams.find(([key]) => key === "client");
|
||||||
if (clientParam) {
|
if (clientParam) {
|
||||||
clientId = clientParam[1];
|
clientId = clientParam[1];
|
||||||
}
|
}
|
||||||
webInstances = getWebInstanceMap(queryParams);
|
}
|
||||||
}
|
|
||||||
return Link._parse(identifier, eventId, clientId, viaServers, webInstances);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _parse(identifier, eventId = undefined, clientId = null, viaServers = [], webInstances = {}) {
|
if (linkStr.startsWith("#/")) {
|
||||||
if (!identifier) {
|
linkStr = linkStr.substr(2);
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
let matches;
|
|
||||||
matches = USERID_PATTERN.exec(identifier);
|
|
||||||
if (matches) {
|
|
||||||
const server = matches[2];
|
|
||||||
const localPart = matches[1];
|
|
||||||
return new Link(clientId, viaServers, IdentifierKind.UserId, localPart, server, webInstances);
|
|
||||||
}
|
|
||||||
matches = ROOMALIAS_PATTERN.exec(identifier);
|
|
||||||
if (matches) {
|
|
||||||
const server = matches[2];
|
|
||||||
const localPart = matches[1];
|
|
||||||
return new Link(clientId, viaServers, IdentifierKind.RoomAlias, localPart, server, webInstances, eventId);
|
|
||||||
}
|
|
||||||
matches = ROOMID_PATTERN.exec(identifier);
|
|
||||||
if (matches) {
|
|
||||||
const server = matches[2];
|
|
||||||
const localPart = matches[1];
|
|
||||||
return new Link(clientId, viaServers, IdentifierKind.RoomId, localPart, server, webInstances, eventId);
|
|
||||||
}
|
|
||||||
matches = GROUPID_PATTERN.exec(identifier);
|
|
||||||
if (matches) {
|
|
||||||
const server = matches[2];
|
|
||||||
const localPart = matches[1];
|
|
||||||
return new Link(clientId, viaServers, IdentifierKind.GroupId, localPart, server, webInstances);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(clientId, viaServers, identifierKind, localPart, server, webInstances, eventId) {
|
const [identifier, eventId] = linkStr.split("/");
|
||||||
const servers = [server];
|
|
||||||
servers.push(...viaServers);
|
let matches;
|
||||||
this.webInstances = webInstances;
|
matches = USERID_PATTERN.exec(identifier);
|
||||||
this.servers = orderedUnique(servers);
|
if (matches) {
|
||||||
this.identifierKind = identifierKind;
|
const server = matches[2];
|
||||||
this.identifier = `${asPrefix(identifierKind)}${localPart}:${server}`;
|
const localPart = matches[1];
|
||||||
this.eventId = eventId;
|
return new Link(clientId, viaServers, IdentifierKind.UserId, localPart, server);
|
||||||
|
}
|
||||||
|
matches = ROOMALIAS_PATTERN.exec(identifier);
|
||||||
|
if (matches) {
|
||||||
|
const server = matches[2];
|
||||||
|
const localPart = matches[1];
|
||||||
|
return new Link(clientId, viaServers, IdentifierKind.RoomAlias, localPart, server, eventId);
|
||||||
|
}
|
||||||
|
matches = ROOMID_PATTERN.exec(identifier);
|
||||||
|
if (matches) {
|
||||||
|
const server = matches[2];
|
||||||
|
const localPart = matches[1];
|
||||||
|
return new Link(clientId, viaServers, IdentifierKind.RoomId, localPart, server, eventId);
|
||||||
|
}
|
||||||
|
matches = GROUPID_PATTERN.exec(identifier);
|
||||||
|
if (matches) {
|
||||||
|
const server = matches[2];
|
||||||
|
const localPart = matches[1];
|
||||||
|
return new Link(clientId, viaServers, IdentifierKind.GroupId, localPart, server);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(clientId, viaServers, identifierKind, localPart, server, eventId) {
|
||||||
|
const servers = [server];
|
||||||
|
servers.push(...viaServers);
|
||||||
|
this.servers = orderedUnique(servers);
|
||||||
|
this.identifierKind = identifierKind;
|
||||||
|
this.identifier = `${asPrefix(identifierKind)}${localPart}:${server}`;
|
||||||
|
this.eventId = eventId;
|
||||||
this.clientId = clientId;
|
this.clientId = clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
get kind() {
|
get kind() {
|
||||||
if (this.eventId) {
|
if (this.eventId) {
|
||||||
return LinkKind.Event;
|
return LinkKind.Event;
|
||||||
}
|
}
|
||||||
switch (this.identifierKind) {
|
switch (this.identifierKind) {
|
||||||
case IdentifierKind.RoomId:
|
case IdentifierKind.RoomId:
|
||||||
case IdentifierKind.RoomAlias:
|
case IdentifierKind.RoomAlias:
|
||||||
return LinkKind.Room;
|
return LinkKind.Room;
|
||||||
case IdentifierKind.UserId:
|
case IdentifierKind.UserId:
|
||||||
return LinkKind.User;
|
return LinkKind.User;
|
||||||
case IdentifierKind.GroupId:
|
case IdentifierKind.GroupId:
|
||||||
return LinkKind.Group;
|
return LinkKind.Group;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(link) {
|
equals(link) {
|
||||||
return link &&
|
return link &&
|
||||||
link.identifier === this.identifier &&
|
link.identifier === this.identifier &&
|
||||||
this.servers.length === link.servers.length &&
|
this.servers.length === link.servers.length &&
|
||||||
this.servers.every((s, i) => link.servers[i] === s) &&
|
this.servers.every((s, i) => link.servers[i] === s);
|
||||||
Object.keys(this.webInstances).length === Object.keys(link.webInstances).length &&
|
}
|
||||||
Object.keys(this.webInstances).every(k => this.webInstances[k] === link.webInstances[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
toFragment() {
|
toFragment() {
|
||||||
if (this.eventId) {
|
if (this.eventId) {
|
||||||
return `/${this.identifier}/${this.eventId}`;
|
return `/${this.identifier}/${this.eventId}`;
|
||||||
} else {
|
} else {
|
||||||
return `/${this.identifier}`;
|
return `/${this.identifier}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,17 +17,17 @@ limitations under the License.
|
||||||
import {createEnum} from "./utils/enum.js";
|
import {createEnum} from "./utils/enum.js";
|
||||||
|
|
||||||
export const Platform = createEnum(
|
export const Platform = createEnum(
|
||||||
"DesktopWeb",
|
"DesktopWeb",
|
||||||
"MobileWeb",
|
"MobileWeb",
|
||||||
"Android",
|
"Android",
|
||||||
"iOS",
|
"iOS",
|
||||||
"Windows",
|
"Windows",
|
||||||
"macOS",
|
"macOS",
|
||||||
"Linux"
|
"Linux"
|
||||||
);
|
);
|
||||||
|
|
||||||
export function guessApplicablePlatforms(userAgent, platform) {
|
export function guessApplicablePlatforms(userAgent, platform) {
|
||||||
// return [Platform.DesktopWeb, Platform.Linux];
|
// return [Platform.DesktopWeb, Platform.Linux];
|
||||||
let nativePlatform;
|
let nativePlatform;
|
||||||
let webPlatform;
|
let webPlatform;
|
||||||
if (/android/i.test(userAgent)) {
|
if (/android/i.test(userAgent)) {
|
||||||
|
@ -55,10 +55,10 @@ export function guessApplicablePlatforms(userAgent, platform) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isWebPlatform(p) {
|
export function isWebPlatform(p) {
|
||||||
return p === Platform.DesktopWeb || p === Platform.MobileWeb;
|
return p === Platform.DesktopWeb || p === Platform.MobileWeb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function isDesktopPlatform(p) {
|
export function isDesktopPlatform(p) {
|
||||||
return p === Platform.Linux || p === Platform.Windows || p === Platform.macOS;
|
return p === Platform.Linux || p === Platform.Windows || p === Platform.macOS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,51 +18,51 @@ import {Platform} from "./Platform.js";
|
||||||
import {EventEmitter} from "./utils/ViewModel.js";
|
import {EventEmitter} from "./utils/ViewModel.js";
|
||||||
|
|
||||||
export class Preferences extends EventEmitter {
|
export class Preferences extends EventEmitter {
|
||||||
constructor(localStorage) {
|
constructor(localStorage) {
|
||||||
super();
|
super();
|
||||||
this._localStorage = localStorage;
|
this._localStorage = localStorage;
|
||||||
this.clientId = null;
|
this.clientId = null;
|
||||||
// used to differentiate web from native if a client supports both
|
// used to differentiate web from native if a client supports both
|
||||||
this.platform = null;
|
this.platform = null;
|
||||||
this.homeservers = null;
|
this.homeservers = null;
|
||||||
|
|
||||||
const prefsStr = localStorage.getItem("preferred_client");
|
const prefsStr = localStorage.getItem("preferred_client");
|
||||||
if (prefsStr) {
|
if (prefsStr) {
|
||||||
const {id, platform} = JSON.parse(prefsStr);
|
const {id, platform} = JSON.parse(prefsStr);
|
||||||
this.clientId = id;
|
this.clientId = id;
|
||||||
this.platform = Platform[platform];
|
this.platform = Platform[platform];
|
||||||
}
|
}
|
||||||
const serversStr = localStorage.getItem("consented_servers");
|
const serversStr = localStorage.getItem("consented_servers");
|
||||||
if (serversStr) {
|
if (serversStr) {
|
||||||
this.homeservers = JSON.parse(serversStr);
|
this.homeservers = JSON.parse(serversStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setClient(id, platform) {
|
setClient(id, platform) {
|
||||||
this.clientId = id;
|
this.clientId = id;
|
||||||
platform = Platform[platform];
|
platform = Platform[platform];
|
||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this._localStorage.setItem("preferred_client", JSON.stringify({id, platform}));
|
this._localStorage.setItem("preferred_client", JSON.stringify({id, platform}));
|
||||||
this.emit("canClear")
|
this.emit("canClear")
|
||||||
}
|
}
|
||||||
|
|
||||||
setHomeservers(homeservers, persist) {
|
setHomeservers(homeservers, persist) {
|
||||||
this.homeservers = homeservers;
|
this.homeservers = homeservers;
|
||||||
if (persist) {
|
if (persist) {
|
||||||
this._localStorage.setItem("consented_servers", JSON.stringify(homeservers));
|
this._localStorage.setItem("consented_servers", JSON.stringify(homeservers));
|
||||||
this.emit("canClear");
|
this.emit("canClear");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this._localStorage.removeItem("preferred_client");
|
this._localStorage.removeItem("preferred_client");
|
||||||
this._localStorage.removeItem("consented_servers");
|
this._localStorage.removeItem("consented_servers");
|
||||||
this.clientId = null;
|
this.clientId = null;
|
||||||
this.platform = null;
|
this.platform = null;
|
||||||
this.homeservers = null;
|
this.homeservers = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get canClear() {
|
get canClear() {
|
||||||
return !!this.clientId || !!this.platform || !!this.homeservers;
|
return !!this.clientId || !!this.platform || !!this.homeservers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,32 +18,27 @@ import {TemplateView} from "./utils/TemplateView.js";
|
||||||
import {OpenLinkView} from "./open/OpenLinkView.js";
|
import {OpenLinkView} from "./open/OpenLinkView.js";
|
||||||
import {CreateLinkView} from "./create/CreateLinkView.js";
|
import {CreateLinkView} from "./create/CreateLinkView.js";
|
||||||
import {LoadServerPolicyView} from "./policy/LoadServerPolicyView.js";
|
import {LoadServerPolicyView} from "./policy/LoadServerPolicyView.js";
|
||||||
import {DisclaimerView} from "./disclaimer/DisclaimerView.js";
|
|
||||||
import {InvalidUrlView} from "./InvalidUrlView.js";
|
|
||||||
|
|
||||||
export class RootView extends TemplateView {
|
export class RootView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "RootView"}, [
|
return t.div({className: "RootView"}, [
|
||||||
t.mapView(vm => vm.invalidUrlViewModel, invalidVM => invalidVM ? new InvalidUrlView(invalidVM) : null),
|
t.mapView(vm => vm.openLinkViewModel, vm => vm ? new OpenLinkView(vm) : null),
|
||||||
t.mapView(vm => vm.showDisclaimer, disclaimer => disclaimer ? new DisclaimerView() : null),
|
t.mapView(vm => vm.createLinkViewModel, vm => vm ? new CreateLinkView(vm) : null),
|
||||||
t.mapView(vm => vm.openLinkViewModel, vm => vm ? new OpenLinkView(vm) : null),
|
|
||||||
t.mapView(vm => vm.createLinkViewModel, vm => vm ? new CreateLinkView(vm) : null),
|
|
||||||
t.mapView(vm => vm.loadServerPolicyViewModel, vm => vm ? new LoadServerPolicyView(vm) : null),
|
t.mapView(vm => vm.loadServerPolicyViewModel, vm => vm ? new LoadServerPolicyView(vm) : null),
|
||||||
t.div({className: "footer"}, [
|
t.div({className: "footer"}, [
|
||||||
t.p(t.img({src: "images/matrix-logo.svg"})),
|
t.p(t.img({src: "images/matrix-logo.svg"})),
|
||||||
t.p(["This invite uses ", externalLink(t, "https://matrix.org", "Matrix"), ", an open network for secure, decentralized communication."]),
|
t.p(["This invite uses ", externalLink(t, "https://matrix.org", "Matrix"), ", an open network for secure, decentralized communication."]),
|
||||||
t.ul({className: "links"}, [
|
t.ul({className: "links"}, [
|
||||||
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to", "GitHub project")),
|
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to", "GitHub project")),
|
||||||
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to/tree/main/src/open/clients", "Add your app")),
|
t.li(externalLink(t, "https://github.com/matrix-org/matrix.to/tree/main/src/clients", "Add your app")),
|
||||||
t.li({className: {hidden: vm => !vm.hasPreferences}},
|
t.li({className: {hidden: vm => !vm.hasPreferences}},
|
||||||
t.button({className: "text", onClick: () => vm.clearPreferences()}, "Clear preferences")),
|
t.button({className: "text", onClick: () => vm.clearPreferences()}, "Clear preferences")),
|
||||||
t.li(t.a({href: "#/disclaimer/"}, "Disclaimer")),
|
])
|
||||||
])
|
])
|
||||||
])
|
]);
|
||||||
]);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function externalLink(t, href, label) {
|
function externalLink(t, href, label) {
|
||||||
return t.a({href, target: "_blank", rel: "noopener noreferrer"}, label);
|
return t.a({href, target: "_blank", rel: "noopener noreferrer"}, label);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,79 +20,54 @@ import {OpenLinkViewModel} from "./open/OpenLinkViewModel.js";
|
||||||
import {createClients} from "./open/clients/index.js";
|
import {createClients} from "./open/clients/index.js";
|
||||||
import {CreateLinkViewModel} from "./create/CreateLinkViewModel.js";
|
import {CreateLinkViewModel} from "./create/CreateLinkViewModel.js";
|
||||||
import {LoadServerPolicyViewModel} from "./policy/LoadServerPolicyViewModel.js";
|
import {LoadServerPolicyViewModel} from "./policy/LoadServerPolicyViewModel.js";
|
||||||
import {InvalidUrlViewModel} from "./InvalidUrlViewModel.js";
|
|
||||||
import {Platform} from "./Platform.js";
|
import {Platform} from "./Platform.js";
|
||||||
|
|
||||||
export class RootViewModel extends ViewModel {
|
export class RootViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
this.link = null;
|
this.link = null;
|
||||||
this.openLinkViewModel = null;
|
this.openLinkViewModel = null;
|
||||||
this.createLinkViewModel = null;
|
this.createLinkViewModel = null;
|
||||||
this.loadServerPolicyViewModel = null;
|
this.loadServerPolicyViewModel = null;
|
||||||
this.invalidUrlViewModel = null;
|
|
||||||
this.showDisclaimer = false;
|
|
||||||
this.preferences.on("canClear", () => {
|
this.preferences.on("canClear", () => {
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateChildVMs(newLink, oldLink) {
|
_updateChildVMs(oldLink) {
|
||||||
this.link = newLink;
|
if (this.link) {
|
||||||
if (!newLink) {
|
this.createLinkViewModel = null;
|
||||||
this.openLinkViewModel = null;
|
if (!oldLink || !oldLink.equals(this.link)) {
|
||||||
} else if (!oldLink || !oldLink.equals(newLink)) {
|
this.openLinkViewModel = new OpenLinkViewModel(this.childOptions({
|
||||||
this.openLinkViewModel = new OpenLinkViewModel(this.childOptions({
|
link: this.link,
|
||||||
link: newLink,
|
clients: createClients(),
|
||||||
clients: createClients(),
|
}));
|
||||||
}));
|
}
|
||||||
}
|
} else {
|
||||||
}
|
this.openLinkViewModel = null;
|
||||||
|
this.createLinkViewModel = new CreateLinkViewModel(this.childOptions());
|
||||||
|
}
|
||||||
|
this.emitChange();
|
||||||
|
}
|
||||||
|
|
||||||
_hideLinks() {
|
updateHash(hash) {
|
||||||
this.link = null;
|
|
||||||
this.openLinkViewModel = null;
|
|
||||||
this.createLinkViewModel = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateHash(hash) {
|
|
||||||
// All view models except openLink are re-created anyway. Might as well
|
|
||||||
// clear them to avoid having to manually reset (n-1)/n view models in every case.
|
|
||||||
// That just doesn't scale well when we add new views.
|
|
||||||
const oldLink = this.link;
|
|
||||||
this.invalidUrlViewModel = null;
|
|
||||||
this.showDisclaimer = false;
|
|
||||||
this.loadServerPolicyViewModel = null;
|
|
||||||
this.createLinkViewModel = null;
|
|
||||||
let newLink;
|
|
||||||
if (hash.startsWith("#/policy/")) {
|
if (hash.startsWith("#/policy/")) {
|
||||||
const server = hash.slice(9);
|
const server = hash.substr(9);
|
||||||
this._updateChildVMs(null, oldLink);
|
|
||||||
this.loadServerPolicyViewModel = new LoadServerPolicyViewModel(this.childOptions({server}));
|
this.loadServerPolicyViewModel = new LoadServerPolicyViewModel(this.childOptions({server}));
|
||||||
this.loadServerPolicyViewModel.load();
|
this.loadServerPolicyViewModel.load();
|
||||||
} else if (hash.startsWith("#/disclaimer/")) {
|
|
||||||
this._updateChildVMs(null, oldLink);
|
|
||||||
this.showDisclaimer = true;
|
|
||||||
} else if (hash === "" || hash === "#" || hash === "#/") {
|
|
||||||
this._updateChildVMs(null, oldLink);
|
|
||||||
this.createLinkViewModel = new CreateLinkViewModel(this.childOptions());
|
|
||||||
} else if (newLink = Link.parseFragment(hash)) {
|
|
||||||
this._updateChildVMs(newLink, oldLink);
|
|
||||||
} else {
|
} else {
|
||||||
this._updateChildVMs(null, oldLink);
|
const oldLink = this.link;
|
||||||
this.invalidUrlViewModel = new InvalidUrlViewModel(this.childOptions({
|
this.link = Link.parse(hash);
|
||||||
fragment: hash
|
this._updateChildVMs(oldLink);
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
this.emitChange();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
clearPreferences() {
|
clearPreferences() {
|
||||||
this.preferences.clear();
|
this.preferences.clear();
|
||||||
this._updateChildVMs();
|
this._updateChildVMs();
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasPreferences() {
|
get hasPreferences() {
|
||||||
return this.preferences.canClear;
|
return this.preferences.canClear;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,31 +19,31 @@ import {PreviewView} from "../preview/PreviewView.js";
|
||||||
import {copyButton} from "../utils/copy.js";
|
import {copyButton} from "../utils/copy.js";
|
||||||
|
|
||||||
export class CreateLinkView extends TemplateView {
|
export class CreateLinkView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
const link = t.a({href: vm => vm.linkUrl}, vm => vm.linkUrl);
|
const link = t.a({href: vm => vm.linkUrl}, vm => vm.linkUrl);
|
||||||
return t.div({className: "CreateLinkView card"}, [
|
return t.div({className: "CreateLinkView card"}, [
|
||||||
t.h1("Create shareable links to Matrix rooms, users or messages without being tied to any app"),
|
t.h1("Create shareable links to Matrix rooms, users or messages without being tied to any app"),
|
||||||
t.form({action: "#", onSubmit: evt => this._onSubmit(evt)}, [
|
t.form({action: "#", onSubmit: evt => this._onSubmit(evt)}, [
|
||||||
t.div(t.input({
|
t.div(t.input({
|
||||||
className: "fullwidth large",
|
className: "fullwidth large",
|
||||||
type: "text",
|
type: "text",
|
||||||
name: "identifier",
|
name: "identifier",
|
||||||
required: true,
|
required: true,
|
||||||
placeholder: "#room:example.com, @user:example.com",
|
placeholder: "#room:example.com, @user:example.com",
|
||||||
onChange: evt => this._onIdentifierChange(evt)
|
onChange: evt => this._onIdentifierChange(evt)
|
||||||
})),
|
})),
|
||||||
t.div(t.input({className: "primary fullwidth icon link", type: "submit", value: "Create link"}))
|
t.div(t.input({className: "primary fullwidth icon link", type: "submit", value: "Create link"}))
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSubmit(evt) {
|
_onSubmit(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
const form = evt.target;
|
const form = evt.target;
|
||||||
const {identifier} = form.elements;
|
const {identifier} = form.elements;
|
||||||
this.value.createLink(identifier.value);
|
this.value.createLink(identifier.value);
|
||||||
identifier.value = "";
|
identifier.value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
_onIdentifierChange(evt) {
|
_onIdentifierChange(evt) {
|
||||||
const inputField = evt.target;
|
const inputField = evt.target;
|
||||||
|
|
|
@ -19,18 +19,18 @@ import {PreviewViewModel} from "../preview/PreviewViewModel.js";
|
||||||
import {Link} from "../Link.js";
|
import {Link} from "../Link.js";
|
||||||
|
|
||||||
export class CreateLinkViewModel extends ViewModel {
|
export class CreateLinkViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
this._link = null;
|
this._link = null;
|
||||||
this.previewViewModel = null;
|
this.previewViewModel = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
validateIdentifier(identifier) {
|
validateIdentifier(identifier) {
|
||||||
return Link.validateIdentifier(identifier);
|
return Link.validateIdentifier(identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createLink(identifier) {
|
async createLink(identifier) {
|
||||||
this._link = Link.parseIdentifier(identifier);
|
this._link = Link.parse(identifier);
|
||||||
if (this._link) {
|
if (this._link) {
|
||||||
this.openLink("#" + this._link.toFragment());
|
this.openLink("#" + this._link.toFragment());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {TemplateView} from "../utils/TemplateView.js";
|
|
||||||
|
|
||||||
export class DisclaimerView extends TemplateView {
|
|
||||||
render(t) {
|
|
||||||
return t.div({ className: "DisclaimerView card" }, [
|
|
||||||
t.h1("Disclaimer"),
|
|
||||||
t.p(
|
|
||||||
'Matrix.to is a service provided by the Matrix.org Foundation ' +
|
|
||||||
'which allows you to easily create invites to Matrix rooms and accounts, ' +
|
|
||||||
'regardless of your Matrix homeserver. The service is provided "as is" without ' +
|
|
||||||
'warranty of any kind, either express, implied, statutory or otherwise. ' +
|
|
||||||
'The Matrix.org Foundation shall not be responsible or liable for the room ' +
|
|
||||||
'and account contents shared via this service.'
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
28
src/main.js
|
@ -21,18 +21,18 @@ import {Preferences} from "./Preferences.js";
|
||||||
import {guessApplicablePlatforms} from "./Platform.js";
|
import {guessApplicablePlatforms} from "./Platform.js";
|
||||||
|
|
||||||
export async function main(container) {
|
export async function main(container) {
|
||||||
const vm = new RootViewModel({
|
const vm = new RootViewModel({
|
||||||
request: xhrRequest,
|
request: xhrRequest,
|
||||||
openLink: url => location.href = url,
|
openLink: url => location.href = url,
|
||||||
platforms: guessApplicablePlatforms(navigator.userAgent, navigator.platform),
|
platforms: guessApplicablePlatforms(navigator.userAgent, navigator.platform),
|
||||||
preferences: new Preferences(window.localStorage),
|
preferences: new Preferences(window.localStorage),
|
||||||
origin: location.origin,
|
origin: location.origin,
|
||||||
});
|
});
|
||||||
vm.updateHash(decodeURIComponent(location.hash));
|
vm.updateHash(location.hash);
|
||||||
window.__rootvm = vm;
|
window.__rootvm = vm;
|
||||||
const view = new RootView(vm);
|
const view = new RootView(vm);
|
||||||
container.appendChild(view.mount());
|
container.appendChild(view.mount());
|
||||||
window.addEventListener('hashchange', () => {
|
window.addEventListener('hashchange', () => {
|
||||||
vm.updateHash(decodeURIComponent(location.hash));
|
vm.updateHash(location.hash);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,50 +18,52 @@ import {TemplateView} from "../utils/TemplateView.js";
|
||||||
import {ClientView} from "./ClientView.js";
|
import {ClientView} from "./ClientView.js";
|
||||||
|
|
||||||
export class ClientListView extends TemplateView {
|
export class ClientListView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.mapView(vm => vm.clientViewModel, () => {
|
return t.mapView(vm => vm.clientViewModel, () => {
|
||||||
if (vm.clientViewModel) {
|
if (vm.clientViewModel) {
|
||||||
return new ContinueWithClientView(vm);
|
return new ContinueWithClientView(vm);
|
||||||
} else {
|
} else {
|
||||||
return new AllClientsView(vm);
|
return new AllClientsView(vm);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AllClientsView extends TemplateView {
|
class AllClientsView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "ClientListView"}, [
|
return t.div({className: "ClientListView"}, [
|
||||||
t.h2("Choose an app to continue"),
|
t.h2("Choose an app to continue"),
|
||||||
t.map(vm => vm.clientList, (clientList, t) => {
|
t.mapView(vm => vm.clientList, () => {
|
||||||
return t.div({className: "list"}, clientList.map(clientViewModel => {
|
return new TemplateView(vm, t => {
|
||||||
return t.view(new ClientView(clientViewModel));
|
return t.div({className: "list"}, vm.clientList.map(clientViewModel => {
|
||||||
}));
|
return t.view(new ClientView(clientViewModel));
|
||||||
}),
|
}));
|
||||||
t.div(t.label([
|
});
|
||||||
t.input({
|
}),
|
||||||
type: "checkbox",
|
t.div(t.label([
|
||||||
checked: vm.showUnsupportedPlatforms,
|
t.input({
|
||||||
onChange: evt => vm.showUnsupportedPlatforms = evt.target.checked,
|
type: "checkbox",
|
||||||
}),
|
checked: vm.showUnsupportedPlatforms,
|
||||||
"Show apps not available on my platform"
|
onChange: evt => vm.showUnsupportedPlatforms = evt.target.checked,
|
||||||
])),
|
}),
|
||||||
t.div(t.label({className: "filterOption"}, [
|
"Show apps not available on my platform"
|
||||||
t.input({
|
])),
|
||||||
type: "checkbox",
|
t.div(t.label({className: "filterOption"}, [
|
||||||
checked: vm.showExperimental,
|
t.input({
|
||||||
onChange: evt => vm.showExperimental = evt.target.checked,
|
type: "checkbox",
|
||||||
}),
|
checked: vm.showExperimental,
|
||||||
"Show experimental apps"
|
onChange: evt => vm.showExperimental = evt.target.checked,
|
||||||
])),
|
}),
|
||||||
]);
|
"Show experimental apps"
|
||||||
}
|
])),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ContinueWithClientView extends TemplateView {
|
class ContinueWithClientView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "ClientListView"}, [
|
return t.div({className: "ClientListView"}, [
|
||||||
t.div({className: "list"}, t.view(new ClientView(vm.clientViewModel)))
|
t.div({className: "list"}, t.view(new ClientView(vm.clientViewModel)))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,70 +20,67 @@ import {ClientViewModel} from "./ClientViewModel.js";
|
||||||
import {ViewModel} from "../utils/ViewModel.js";
|
import {ViewModel} from "../utils/ViewModel.js";
|
||||||
|
|
||||||
export class ClientListViewModel extends ViewModel {
|
export class ClientListViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
const {clients, client, link} = options;
|
const {clients, client, link} = options;
|
||||||
this._clients = clients;
|
this._clients = clients;
|
||||||
this._link = link;
|
this._link = link;
|
||||||
this.clientList = null;
|
this.clientList = null;
|
||||||
this._showExperimental = false;
|
this._showExperimental = false;
|
||||||
this._showUnsupportedPlatforms = false;
|
this._showUnsupportedPlatforms = false;
|
||||||
this._filterClients();
|
this._filterClients();
|
||||||
this.clientViewModel = null;
|
this.clientViewModel = null;
|
||||||
if (client) {
|
if (client) {
|
||||||
this._pickClient(client);
|
this._pickClient(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get showUnsupportedPlatforms() {
|
get showUnsupportedPlatforms() {
|
||||||
return this._showUnsupportedPlatforms;
|
return this._showUnsupportedPlatforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
get showExperimental() {
|
get showExperimental() {
|
||||||
return this._showExperimental;
|
return this._showExperimental;
|
||||||
}
|
}
|
||||||
|
|
||||||
set showUnsupportedPlatforms(enabled) {
|
set showUnsupportedPlatforms(enabled) {
|
||||||
this._showUnsupportedPlatforms = enabled;
|
this._showUnsupportedPlatforms = enabled;
|
||||||
this._filterClients();
|
this._filterClients();
|
||||||
}
|
}
|
||||||
|
|
||||||
set showExperimental(enabled) {
|
set showExperimental(enabled) {
|
||||||
this._showExperimental = enabled;
|
this._showExperimental = enabled;
|
||||||
this._filterClients();
|
this._filterClients();
|
||||||
}
|
}
|
||||||
|
|
||||||
_filterClients() {
|
_filterClients() {
|
||||||
const clientVMs = this._clients.filter(client => {
|
this.clientList = this._clients.filter(client => {
|
||||||
const platformMaturities = this.platforms.map(p => client.getMaturity(p));
|
const platformMaturities = this.platforms.map(p => client.getMaturity(p));
|
||||||
const isStable = platformMaturities.includes(Maturity.Stable) || platformMaturities.includes(Maturity.Beta);
|
const isStable = platformMaturities.includes(Maturity.Stable) || platformMaturities.includes(Maturity.Beta);
|
||||||
const isSupported = client.platforms.some(p => this.platforms.includes(p));
|
const isSupported = client.platforms.some(p => this.platforms.includes(p));
|
||||||
if (!this._showExperimental && !isStable) {
|
if (!this._showExperimental && !isStable) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!this._showUnsupportedPlatforms && !isSupported) {
|
if (!this._showUnsupportedPlatforms && !isSupported) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}).map(client => new ClientViewModel(this.childOptions({
|
}).map(client => new ClientViewModel(this.childOptions({
|
||||||
client,
|
client,
|
||||||
link: this._link,
|
link: this._link,
|
||||||
pickClient: client => this._pickClient(client)
|
pickClient: client => this._pickClient(client)
|
||||||
})));
|
})));
|
||||||
const preferredClientVMs = clientVMs.filter(c => c.hasPreferredWebInstance);
|
this.emitChange();
|
||||||
const otherClientVMs = clientVMs.filter(c => !c.hasPreferredWebInstance);
|
}
|
||||||
this.clientList = preferredClientVMs.concat(otherClientVMs);
|
|
||||||
this.emitChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
_pickClient(client) {
|
_pickClient(client) {
|
||||||
this.clientViewModel = this.clientList.find(vm => vm.clientId === client.id);
|
this.clientViewModel = this.clientList.find(vm => vm.clientId === client.id);
|
||||||
this.clientViewModel.pick(this);
|
this.clientViewModel.pick(this);
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
showAll() {
|
showAll() {
|
||||||
this.clientViewModel = null;
|
this.clientViewModel = null;
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,11 @@ import {copy} from "../utils/copy.js";
|
||||||
import {text, tag} from "../utils/html.js";
|
import {text, tag} from "../utils/html.js";
|
||||||
|
|
||||||
function formatPlatforms(platforms) {
|
function formatPlatforms(platforms) {
|
||||||
return platforms.reduce((str, p, i, all) => {
|
return platforms.reduce((str, p, i, all) => {
|
||||||
const first = i === 0;
|
const first = i === 0;
|
||||||
const last = i === all.length - 1;
|
const last = i === all.length - 1;
|
||||||
return str + (first ? "" : last ? " & " : ", ") + p;
|
return str + (first ? "" : last ? " & " : ", ") + p;
|
||||||
}, "");
|
}, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderInstructions(parts) {
|
function renderInstructions(parts) {
|
||||||
|
@ -38,46 +38,50 @@ function renderInstructions(parts) {
|
||||||
|
|
||||||
export class ClientView extends TemplateView {
|
export class ClientView extends TemplateView {
|
||||||
|
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: {"ClientView": true, "isPreferred": vm => vm.hasPreferredWebInstance}}, [
|
return t.div({className: "ClientView"}, [
|
||||||
... vm.hasPreferredWebInstance ? [t.div({className: "hostedBanner"}, vm.hostedByBannerLabel)] : [],
|
t.div({className: "header"}, [
|
||||||
t.div({className: "header"}, [
|
t.div({className: "description"}, [
|
||||||
t.div({className: "description"}, [
|
t.h3(vm.name),
|
||||||
t.h3(vm.name),
|
t.p([vm.description, " ", t.a({
|
||||||
t.p([vm.description, " ", t.a({
|
|
||||||
href: vm.homepage,
|
href: vm.homepage,
|
||||||
target: "_blank",
|
target: "_blank",
|
||||||
rel: "noopener noreferrer"
|
rel: "noopener noreferrer"
|
||||||
}, "Learn more")]),
|
}, "Learn more")]),
|
||||||
t.p({className: "platforms"}, formatPlatforms(vm.availableOnPlatformNames)),
|
t.p({className: "platforms"}, formatPlatforms(vm.availableOnPlatformNames)),
|
||||||
]),
|
]),
|
||||||
t.img({className: "clientIcon", src: vm.iconUrl})
|
t.img({className: "clientIcon", src: vm.iconUrl})
|
||||||
]),
|
]),
|
||||||
t.mapView(vm => vm.stage, stage => {
|
t.mapView(vm => vm.stage, stage => {
|
||||||
switch (stage) {
|
switch (stage) {
|
||||||
case "open": return new OpenClientView(vm);
|
case "open": return new OpenClientView(vm);
|
||||||
case "install": return new InstallClientView(vm);
|
case "install": return new InstallClientView(vm);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpenClientView extends TemplateView {
|
class OpenClientView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "OpenClientView"}, [
|
return t.div({className: "OpenClientView"}, [
|
||||||
...vm.openActions.map(a => renderAction(t, a)),
|
t.a({
|
||||||
|
className: "primary fullwidth",
|
||||||
|
href: vm.deepLink,
|
||||||
|
rel: "noopener noreferrer",
|
||||||
|
onClick: () => vm.deepLinkActivated(),
|
||||||
|
}, "Continue"),
|
||||||
showBack(t, vm),
|
showBack(t, vm),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InstallClientView extends TemplateView {
|
class InstallClientView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
const children = [];
|
const children = [];
|
||||||
|
|
||||||
const textInstructions = vm.textInstructions;
|
const textInstructions = vm.textInstructions;
|
||||||
if (textInstructions) {
|
if (textInstructions) {
|
||||||
const copyButton = t.button({
|
const copyButton = t.button({
|
||||||
className: "copy",
|
className: "copy",
|
||||||
title: "Copy instructions",
|
title: "Copy instructions",
|
||||||
|
@ -91,25 +95,45 @@ class InstallClientView extends TemplateView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
children.push(t.p({className: "instructions"}, renderInstructions(textInstructions).concat(copyButton)));
|
children.push(t.p({className: "instructions"}, renderInstructions(textInstructions).concat(copyButton)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = t.div({className: "actions"}, vm.installActions.map(a => renderAction(t, a)));
|
const actions = t.div({className: "actions"}, vm.actions.map(a => {
|
||||||
children.push(actions);
|
let badgeUrl;
|
||||||
|
switch (a.kind) {
|
||||||
|
case "play-store": badgeUrl = "images/google-play-us.svg"; break;
|
||||||
|
case "fdroid": badgeUrl = "images/fdroid-badge.png"; break;
|
||||||
|
case "apple-app-store": badgeUrl = "images/app-store-us-alt.svg"; break;
|
||||||
|
case "flathub": badgeUrl = "images/flathub-badge.svg"; break;
|
||||||
|
}
|
||||||
|
return t.a({
|
||||||
|
href: a.url,
|
||||||
|
className: {
|
||||||
|
fullwidth: !badgeUrl,
|
||||||
|
primary: a.primary && !badgeUrl,
|
||||||
|
secondary: !a.primary && !badgeUrl,
|
||||||
|
badge: !!badgeUrl,
|
||||||
|
},
|
||||||
|
rel: "noopener noreferrer",
|
||||||
|
["aria-label"]: a.label,
|
||||||
|
onClick: () => a.activated()
|
||||||
|
}, badgeUrl ? t.img({src: badgeUrl}) : a.label);
|
||||||
|
}));
|
||||||
|
children.push(actions);
|
||||||
|
|
||||||
if (vm.showDeepLinkInInstall) {
|
if (vm.showDeepLinkInInstall) {
|
||||||
const openItHere = t.a({
|
const deepLink = t.a({
|
||||||
rel: "noopener noreferrer",
|
rel: "noopener noreferrer",
|
||||||
href: vm.openActions[0].url,
|
href: vm.deepLink,
|
||||||
onClick: () => vm.openActions[0].activated(),
|
onClick: () => vm.deepLinkActivated(),
|
||||||
}, "open it here");
|
}, "open it here");
|
||||||
children.push(t.p([`If you already have ${vm.name} installed, you can `, openItHere, "."]))
|
children.push(t.p([`If you already have ${vm.name} installed, you can `, deepLink, "."]))
|
||||||
}
|
}
|
||||||
|
|
||||||
children.push(showBack(t, vm));
|
children.push(showBack(t, vm));
|
||||||
|
|
||||||
return t.div({className: "InstallClientView"}, children);
|
return t.div({className: "InstallClientView"}, children);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showBack(t, vm) {
|
function showBack(t, vm) {
|
||||||
|
@ -118,25 +142,3 @@ function showBack(t, vm) {
|
||||||
t.button({className: "text", onClick: () => vm.back()}, "Change"),
|
t.button({className: "text", onClick: () => vm.back()}, "Change"),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAction(t, a) {
|
|
||||||
let badgeUrl;
|
|
||||||
switch (a.kind) {
|
|
||||||
case "play-store": badgeUrl = "images/google-play-us.svg"; break;
|
|
||||||
case "fdroid": badgeUrl = "images/fdroid-badge.png"; break;
|
|
||||||
case "apple-app-store": badgeUrl = "images/app-store-us-alt.svg"; break;
|
|
||||||
case "flathub": badgeUrl = "images/flathub-badge.svg"; break;
|
|
||||||
}
|
|
||||||
return t.a({
|
|
||||||
href: a.url,
|
|
||||||
className: {
|
|
||||||
fullwidth: !badgeUrl,
|
|
||||||
primary: a.primary && !badgeUrl,
|
|
||||||
secondary: !a.primary && !badgeUrl,
|
|
||||||
badge: !!badgeUrl,
|
|
||||||
},
|
|
||||||
rel: "noopener noreferrer",
|
|
||||||
["aria-label"]: a.label,
|
|
||||||
onClick: () => a.activated()
|
|
||||||
}, badgeUrl ? t.img({src: badgeUrl}) : a.label);
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,140 +27,70 @@ function getMatchingPlatforms(client, supportedPlatforms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClientViewModel extends ViewModel {
|
export class ClientViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
const {client, link, pickClient} = options;
|
const {client, link, pickClient} = options;
|
||||||
this._client = client;
|
this._client = client;
|
||||||
this._link = link;
|
this._link = link;
|
||||||
this._pickClient = pickClient;
|
this._pickClient = pickClient;
|
||||||
// to provide "choose other client" button after calling pick()
|
// to provide "choose other client" button after calling pick()
|
||||||
this._clientListViewModel = null;
|
this._clientListViewModel = null;
|
||||||
this._update();
|
|
||||||
}
|
|
||||||
|
|
||||||
_update() {
|
const matchingPlatforms = getMatchingPlatforms(client, this.platforms);
|
||||||
const matchingPlatforms = getMatchingPlatforms(this._client, this.platforms);
|
const nativePlatform = matchingPlatforms.find(p => !isWebPlatform(p));
|
||||||
this._webPlatform = matchingPlatforms.find(p => isWebPlatform(p));
|
const webPlatform = matchingPlatforms.find(p => isWebPlatform(p));
|
||||||
this._nativePlatform = matchingPlatforms.find(p => !isWebPlatform(p));
|
|
||||||
const preferredPlatform = matchingPlatforms.find(p => p === this.preferences.platform);
|
this._proposedPlatform = this.preferences.platform || nativePlatform || webPlatform;
|
||||||
this._proposedPlatform = preferredPlatform || this._nativePlatform || this._webPlatform;
|
this._nativePlatform = nativePlatform || this._proposedPlatform;
|
||||||
|
|
||||||
this.openActions = this._createOpenActions();
|
this.actions = this._createActions(client, link, nativePlatform, webPlatform);
|
||||||
this.installActions = this._createInstallActions();
|
this._clientCanIntercept = !!(nativePlatform && client.canInterceptMatrixToLinks(nativePlatform));
|
||||||
this._clientCanIntercept = !!(this._nativePlatform && this._client.canInterceptMatrixToLinks(this._nativePlatform));
|
this._showOpen = this.deepLink && !this._clientCanIntercept;
|
||||||
this._showOpen = this.openActions.length && !this._clientCanIntercept;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// these are only shown in the open stage
|
_createActions(client, link, nativePlatform, webPlatform) {
|
||||||
_createOpenActions() {
|
let actions = [];
|
||||||
const hasPreferredWebInstance = this.hasPreferredWebInstance;
|
if (nativePlatform) {
|
||||||
let deepLinkLabel = "Continue";
|
const nativeActions = (client.getInstallLinks(nativePlatform) || []).map(installLink => {
|
||||||
if (hasPreferredWebInstance) {
|
return {
|
||||||
if (this._proposedPlatform === this._nativePlatform) {
|
label: installLink.getDescription(nativePlatform),
|
||||||
deepLinkLabel = "Open in app";
|
url: installLink.createInstallURL(link),
|
||||||
} else {
|
kind: installLink.channelId,
|
||||||
deepLinkLabel = `Open on ${this._client.getPreferredWebInstance(this._link)}`;
|
primary: true,
|
||||||
}
|
activated: () => this.preferences.setClient(client.id, nativePlatform),
|
||||||
}
|
};
|
||||||
const actions = [];
|
});
|
||||||
const proposedDeepLink = this._client.getDeepLink(this._proposedPlatform, this._link);
|
actions.push(...nativeActions);
|
||||||
if (proposedDeepLink) {
|
}
|
||||||
actions.push({
|
if (webPlatform) {
|
||||||
label: deepLinkLabel,
|
const webDeepLink = client.getDeepLink(webPlatform, link);
|
||||||
url: proposedDeepLink,
|
if (webDeepLink) {
|
||||||
primary: true,
|
actions.push({
|
||||||
activated: () => {
|
label: `Continue in your browser`,
|
||||||
this._pickClient(this._client);
|
url: webDeepLink,
|
||||||
this.preferences.setClient(this._client.id, this._proposedPlatform);
|
kind: "open-in-web",
|
||||||
// only show install screen if we tried to open a native deeplink
|
activated: () => this.preferences.setClient(client.id, webPlatform),
|
||||||
if (this._showOpen && this._proposedPlatform === this._nativePlatform) {
|
});
|
||||||
this._showOpen = false;
|
}
|
||||||
this.emitChange();
|
}
|
||||||
}
|
return actions;
|
||||||
},
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
// show only if there is a preferred instance, and if we don't already link to it in the first button
|
|
||||||
if (hasPreferredWebInstance && this._webPlatform && this._proposedPlatform !== this._webPlatform) {
|
|
||||||
actions.push({
|
|
||||||
label: `Open on ${this._client.getPreferredWebInstance(this._link)}`,
|
|
||||||
url: this._client.getDeepLink(this._webPlatform, this._link),
|
|
||||||
kind: "open-in-web",
|
|
||||||
activated: () => {} // don't persist this choice as we don't persist the preferred web instance, it's in the url
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// these are only shown in the install stage
|
|
||||||
_createInstallActions() {
|
|
||||||
let actions = [];
|
|
||||||
if (this._nativePlatform) {
|
|
||||||
const nativeActions = (this._client.getInstallLinks(this._nativePlatform) || []).map(installLink => {
|
|
||||||
return {
|
|
||||||
label: installLink.getDescription(this._nativePlatform),
|
|
||||||
url: installLink.createInstallURL(this._link),
|
|
||||||
kind: installLink.channelId,
|
|
||||||
primary: true,
|
|
||||||
activated: () => this.preferences.setClient(this._client.id, this._nativePlatform),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
actions.push(...nativeActions);
|
|
||||||
}
|
|
||||||
if (this._webPlatform) {
|
|
||||||
const webDeepLink = this._client.getDeepLink(this._webPlatform, this._link);
|
|
||||||
if (webDeepLink) {
|
|
||||||
const webLabel = this.hasPreferredWebInstance ?
|
|
||||||
`Open on ${this._client.getPreferredWebInstance(this._link)}` :
|
|
||||||
`Continue in your browser`;
|
|
||||||
actions.push({
|
|
||||||
label: webLabel,
|
|
||||||
url: webDeepLink,
|
|
||||||
kind: "open-in-web",
|
|
||||||
activated: () => {
|
|
||||||
if (!this.hasPreferredWebInstance) {
|
|
||||||
this.preferences.setClient(this._client.id, this._webPlatform);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasPreferredWebInstance() {
|
|
||||||
// also check there is a web platform that matches the platforms the user is on (mobile or desktop web)
|
|
||||||
return this._webPlatform && typeof this._client.getPreferredWebInstance(this._link) === "string";
|
|
||||||
}
|
|
||||||
|
|
||||||
get hostedByBannerLabel() {
|
|
||||||
const preferredWebInstance = this._client.getPreferredWebInstance(this._link);
|
|
||||||
if (this._webPlatform && preferredWebInstance) {
|
|
||||||
let label = preferredWebInstance;
|
|
||||||
const subDomainIdx = preferredWebInstance.lastIndexOf(".", preferredWebInstance.lastIndexOf("."));
|
|
||||||
if (subDomainIdx !== -1) {
|
|
||||||
label = preferredWebInstance.slice(preferredWebInstance.length - subDomainIdx + 1);
|
|
||||||
}
|
|
||||||
return `Hosted by ${label}`;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
get homepage() {
|
get homepage() {
|
||||||
return this._client.homepage;
|
return this._client.homepage;
|
||||||
}
|
}
|
||||||
|
|
||||||
get identifier() {
|
get identifier() {
|
||||||
return this._link.identifier;
|
return this._link.identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
get description() {
|
get description() {
|
||||||
return this._client.description;
|
return this._client.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
get clientId() {
|
get clientId() {
|
||||||
return this._client.id;
|
return this._client.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
return this._client.name;
|
return this._client.name;
|
||||||
|
@ -170,56 +100,69 @@ export class ClientViewModel extends ViewModel {
|
||||||
return this._client.icon;
|
return this._client.icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
get stage() {
|
get stage() {
|
||||||
return this._showOpen ? "open" : "install";
|
return this._showOpen ? "open" : "install";
|
||||||
}
|
}
|
||||||
|
|
||||||
get textInstructions() {
|
get textInstructions() {
|
||||||
let instructions = this._client.getLinkInstructions(this._proposedPlatform, this._link);
|
let instructions = this._client.getLinkInstructions(this._proposedPlatform, this._link);
|
||||||
if (instructions && !Array.isArray(instructions)) {
|
if (instructions && !Array.isArray(instructions)) {
|
||||||
instructions = [instructions];
|
instructions = [instructions];
|
||||||
}
|
}
|
||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
get copyString() {
|
get copyString() {
|
||||||
return this._client.getCopyString(this._proposedPlatform, this._link);
|
return this._client.getCopyString(this._proposedPlatform, this._link);
|
||||||
}
|
}
|
||||||
|
|
||||||
get showDeepLinkInInstall() {
|
get showDeepLinkInInstall() {
|
||||||
// we can assume this._nativePlatform as this._clientCanIntercept already checks it
|
return this._clientCanIntercept && this.deepLink;
|
||||||
return this._clientCanIntercept && !!this._client.getDeepLink(this._nativePlatform, this._link);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
get availableOnPlatformNames() {
|
get availableOnPlatformNames() {
|
||||||
const platforms = this._client.platforms;
|
const platforms = this._client.platforms;
|
||||||
const textPlatforms = [];
|
const textPlatforms = [];
|
||||||
const hasWebPlatform = platforms.some(p => isWebPlatform(p));
|
const hasWebPlatform = platforms.some(p => isWebPlatform(p));
|
||||||
if (hasWebPlatform) {
|
if (hasWebPlatform) {
|
||||||
textPlatforms.push("Web");
|
textPlatforms.push("Web");
|
||||||
}
|
}
|
||||||
const desktopPlatforms = platforms.filter(p => isDesktopPlatform(p));
|
const desktopPlatforms = platforms.filter(p => isDesktopPlatform(p));
|
||||||
if (desktopPlatforms.length === 1) {
|
if (desktopPlatforms.length === 1) {
|
||||||
textPlatforms.push(desktopPlatforms[0]);
|
textPlatforms.push(desktopPlatforms[0]);
|
||||||
} else {
|
} else {
|
||||||
textPlatforms.push("Desktop");
|
textPlatforms.push("Desktop");
|
||||||
}
|
}
|
||||||
if (platforms.includes(Platform.Android)) {
|
if (platforms.includes(Platform.Android)) {
|
||||||
textPlatforms.push("Android");
|
textPlatforms.push("Android");
|
||||||
}
|
}
|
||||||
if (platforms.includes(Platform.iOS)) {
|
if (platforms.includes(Platform.iOS)) {
|
||||||
textPlatforms.push("iOS");
|
textPlatforms.push("iOS");
|
||||||
}
|
}
|
||||||
return textPlatforms;
|
return textPlatforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
get deepLink() {
|
||||||
|
const platform = this.showBack ? this._proposedPlatform : this._nativePlatform;
|
||||||
|
return this._client.getDeepLink(platform, this._link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deepLinkActivated() {
|
||||||
|
this._pickClient(this._client);
|
||||||
|
this.preferences.setClient(this._client.id, this._proposedPlatform);
|
||||||
|
if (this._showOpen) {
|
||||||
|
this._showOpen = false;
|
||||||
|
this.emitChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pick(clientListViewModel) {
|
pick(clientListViewModel) {
|
||||||
this._clientListViewModel = clientListViewModel;
|
this._clientListViewModel = clientListViewModel;
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
// whether or not we are only showing this client (in open or install stage)
|
|
||||||
get showBack() {
|
get showBack() {
|
||||||
|
// if we're not only showing this client, don't show back (see pick())
|
||||||
return !!this._clientListViewModel;
|
return !!this._clientListViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,11 +170,6 @@ export class ClientViewModel extends ViewModel {
|
||||||
if (this._clientListViewModel) {
|
if (this._clientListViewModel) {
|
||||||
const vm = this._clientListViewModel;
|
const vm = this._clientListViewModel;
|
||||||
this._clientListViewModel = null;
|
this._clientListViewModel = null;
|
||||||
// clear the client preference so we default back to to native link if any
|
|
||||||
// in the list with all clients, and also if we refresh, we get the list with
|
|
||||||
// all clients rather than having our "change client" click reverted.
|
|
||||||
this.preferences.setClient(undefined, undefined);
|
|
||||||
this._update();
|
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
vm.showAll();
|
vm.showAll();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,14 +20,14 @@ import {PreviewView} from "../preview/PreviewView.js";
|
||||||
import {ServerConsentView} from "./ServerConsentView.js";
|
import {ServerConsentView} from "./ServerConsentView.js";
|
||||||
|
|
||||||
export class OpenLinkView extends TemplateView {
|
export class OpenLinkView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "OpenLinkView card"}, [
|
return t.div({className: "OpenLinkView card"}, [
|
||||||
t.mapView(vm => vm.previewViewModel, previewVM => previewVM ?
|
t.mapView(vm => vm.previewViewModel, previewVM => previewVM ?
|
||||||
new ShowLinkView(vm) :
|
new ShowLinkView(vm) :
|
||||||
new ServerConsentView(vm.serverConsentViewModel)
|
new ServerConsentView(vm.serverConsentViewModel)
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ShowLinkView extends TemplateView {
|
class ShowLinkView extends TemplateView {
|
||||||
|
|
|
@ -23,21 +23,21 @@ import {getLabelForLinkKind} from "../Link.js";
|
||||||
import {orderedUnique} from "../utils/unique.js";
|
import {orderedUnique} from "../utils/unique.js";
|
||||||
|
|
||||||
export class OpenLinkViewModel extends ViewModel {
|
export class OpenLinkViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
const {clients, link} = options;
|
const {clients, link} = options;
|
||||||
this._link = link;
|
this._link = link;
|
||||||
this._clients = clients;
|
this._clients = clients;
|
||||||
this.serverConsentViewModel = null;
|
this.serverConsentViewModel = null;
|
||||||
this.previewViewModel = null;
|
this.previewViewModel = null;
|
||||||
this.clientsViewModel = null;
|
this.clientsViewModel = null;
|
||||||
this.previewLoading = false;
|
this.previewLoading = false;
|
||||||
if (this.preferences.homeservers === null) {
|
if (this.preferences.homeservers === null) {
|
||||||
this._showServerConsent();
|
this._showServerConsent();
|
||||||
} else {
|
} else {
|
||||||
this._showLink();
|
this._showLink();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_showServerConsent() {
|
_showServerConsent() {
|
||||||
let servers = [];
|
let servers = [];
|
||||||
|
@ -67,24 +67,24 @@ export class OpenLinkViewModel extends ViewModel {
|
||||||
link: this._link,
|
link: this._link,
|
||||||
consentedServers: this.preferences.homeservers
|
consentedServers: this.preferences.homeservers
|
||||||
}));
|
}));
|
||||||
this.previewLoading = true;
|
this.previewLoading = true;
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
await this.previewViewModel.load();
|
await this.previewViewModel.load();
|
||||||
this.previewLoading = false;
|
this.previewLoading = false;
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
get previewDomain() {
|
get previewDomain() {
|
||||||
return this.previewViewModel?.domain;
|
return this.previewViewModel?.domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
get previewFailed() {
|
get previewFailed() {
|
||||||
return this.previewViewModel?.failed;
|
return this.previewViewModel?.failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
get showClientsLabel() {
|
get showClientsLabel() {
|
||||||
return getLabelForLinkKind(this._link.kind);
|
return getLabelForLinkKind(this._link.kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeServer() {
|
changeServer() {
|
||||||
this.previewViewModel = null;
|
this.previewViewModel = null;
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class ServerConsentView extends TemplateView {
|
||||||
className: "text",
|
className: "text",
|
||||||
onClick: () => vm.continueWithoutConsent(this._askEveryTimeChecked)
|
onClick: () => vm.continueWithoutConsent(this._askEveryTimeChecked)
|
||||||
}, "continue without a preview");
|
}, "continue without a preview");
|
||||||
return t.div({className: "ServerConsentView"}, [
|
return t.div({className: "ServerConsentView"}, [
|
||||||
t.p([
|
t.p([
|
||||||
"Preview this link using the ",
|
"Preview this link using the ",
|
||||||
t.strong(vm => vm.selectedServer || "…"),
|
t.strong(vm => vm.selectedServer || "…"),
|
||||||
|
@ -56,7 +56,7 @@ export class ServerConsentView extends TemplateView {
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSubmit(evt) {
|
_onSubmit(evt) {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
|
|
@ -22,13 +22,13 @@ import {getLabelForLinkKind} from "../Link.js";
|
||||||
import {orderedUnique} from "../utils/unique.js";
|
import {orderedUnique} from "../utils/unique.js";
|
||||||
|
|
||||||
export class ServerConsentViewModel extends ViewModel {
|
export class ServerConsentViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
this.servers = options.servers;
|
this.servers = options.servers;
|
||||||
this.done = options.done;
|
this.done = options.done;
|
||||||
this.selectedServer = this.servers[0];
|
this.selectedServer = this.servers[0];
|
||||||
this.showSelectServer = false;
|
this.showSelectServer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setShowServers() {
|
setShowServers() {
|
||||||
this.showSelectServer = true;
|
this.showSelectServer = true;
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
Copyright 2022 3nt3 <gott@3nt3.de>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Maturity, Platform, LinkKind, FlathubLink, style } from "../types.js";
|
|
||||||
|
|
||||||
export class Cinny {
|
|
||||||
get id() {
|
|
||||||
return "cinny";
|
|
||||||
}
|
|
||||||
get name() {
|
|
||||||
return "Cinny";
|
|
||||||
}
|
|
||||||
get icon() {
|
|
||||||
return "images/client-icons/cinny.svg";
|
|
||||||
}
|
|
||||||
get author() {
|
|
||||||
return "Copyright (c) 2021-present Ajay Bura (ajbura) and contributors";
|
|
||||||
}
|
|
||||||
get homepage() {
|
|
||||||
return "https://cinny.in";
|
|
||||||
}
|
|
||||||
get platforms() {
|
|
||||||
return [
|
|
||||||
Platform.DesktopWeb,
|
|
||||||
Platform.Linux,
|
|
||||||
Platform.macOS,
|
|
||||||
Platform.Windows,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
get description() {
|
|
||||||
return "A Matrix client focusing primarily on simple, elegant and secure interface. The main goal is to have an instant messaging application that is easy on people and has a modern touch.";
|
|
||||||
}
|
|
||||||
getMaturity(platform) {
|
|
||||||
return Maturity.Stable;
|
|
||||||
}
|
|
||||||
|
|
||||||
getDeepLink(platform, link) {
|
|
||||||
let fragmentPath;
|
|
||||||
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User:
|
|
||||||
fragmentPath = `direct/create?userId=${encodeURIComponent(link.identifier)}`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Room:
|
|
||||||
fragmentPath = `home/${encodeURIComponent(link.identifier)}`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Event:
|
|
||||||
fragmentPath = `home/${encodeURIComponent(link.identifier)}/${encodeURIComponent(link.eventId)}`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((link.kind === LinkKind.Event || link.kind === LinkKind.Room) && link.servers.length > 0) {
|
|
||||||
fragmentPath += `?via=${link.servers.map(server => encodeURIComponent(server)).join(',')}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `https://app.cinny.in/${fragmentPath}`
|
|
||||||
}
|
|
||||||
|
|
||||||
canInterceptMatrixToLinks(platform) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {}
|
|
||||||
|
|
||||||
getCopyString(platform, link) {}
|
|
||||||
|
|
||||||
getInstallLinks(platform) {}
|
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
|
|
@ -15,100 +15,66 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Maturity, Platform, LinkKind,
|
import {Maturity, Platform, LinkKind,
|
||||||
FDroidLink, AppleStoreLink, PlayStoreLink, WebsiteLink} from "../types.js";
|
FDroidLink, AppleStoreLink, PlayStoreLink, WebsiteLink} from "../types.js";
|
||||||
|
|
||||||
const trustedWebInstances = [
|
|
||||||
"app.element.io", // first one is the default one
|
|
||||||
"develop.element.io",
|
|
||||||
"chat.fedoraproject.org",
|
|
||||||
"chat.fosdem.org",
|
|
||||||
"chat.mozilla.org",
|
|
||||||
"webchat.kde.org",
|
|
||||||
"app.gitter.im",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information on how to deep link to a given matrix client.
|
* Information on how to deep link to a given matrix client.
|
||||||
*/
|
*/
|
||||||
export class Element {
|
export class Element {
|
||||||
get id() { return "element.io"; }
|
get id() { return "element.io"; }
|
||||||
|
|
||||||
get platforms() {
|
get platforms() {
|
||||||
return [
|
return [
|
||||||
Platform.Android, Platform.iOS,
|
Platform.Android, Platform.iOS,
|
||||||
Platform.Windows, Platform.macOS, Platform.Linux,
|
Platform.Windows, Platform.macOS, Platform.Linux,
|
||||||
Platform.DesktopWeb
|
Platform.DesktopWeb
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
get icon() { return "images/client-icons/element.svg"; }
|
get icon() { return "images/client-icons/element.svg"; }
|
||||||
get appleAssociatedAppId() {
|
get appleAssociatedAppId() { return "7J4U792NQT.im.vector.app"; }
|
||||||
return [
|
get name() {return "Element"; }
|
||||||
"7J4U792NQT.im.vector.app",
|
get description() { return 'Fully-featured Matrix client, used by millions.'; }
|
||||||
"7J4U792NQT.io.element.elementx",
|
get homepage() { return "https://element.io"; }
|
||||||
"7J4U792NQT.io.element.elementx.nightly",
|
get author() { return "Element"; }
|
||||||
"7J4U792NQT.io.element.elementx.pr"
|
getMaturity(platform) { return Maturity.Stable; }
|
||||||
];
|
|
||||||
}
|
|
||||||
get name() {return "Element"; }
|
|
||||||
get description() { return 'Fully-featured Matrix client, used by millions.'; }
|
|
||||||
get homepage() { return "https://element.io"; }
|
|
||||||
get author() { return "Element"; }
|
|
||||||
getMaturity(platform) { return Maturity.Stable; }
|
|
||||||
|
|
||||||
getDeepLink(platform, link) {
|
getDeepLink(platform, link) {
|
||||||
let fragmentPath;
|
let fragmentPath;
|
||||||
switch (link.kind) {
|
switch (link.kind) {
|
||||||
case LinkKind.User:
|
case LinkKind.User:
|
||||||
fragmentPath = `user/${encodeURIComponent(link.identifier)}`;
|
fragmentPath = `user/${link.identifier}`;
|
||||||
break;
|
break;
|
||||||
case LinkKind.Room:
|
case LinkKind.Room:
|
||||||
fragmentPath = `room/${encodeURIComponent(link.identifier)}`;
|
fragmentPath = `room/${link.identifier}`;
|
||||||
break;
|
break;
|
||||||
case LinkKind.Group:
|
case LinkKind.Group:
|
||||||
fragmentPath = `group/${encodeURIComponent(link.identifier)}`;
|
fragmentPath = `group/${link.identifier}`;
|
||||||
break;
|
break;
|
||||||
case LinkKind.Event:
|
case LinkKind.Event:
|
||||||
fragmentPath = `room/${encodeURIComponent(link.identifier)}/${encodeURIComponent(link.eventId)}`;
|
fragmentPath = `room/${link.identifier}/${link.eventId}`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (platform === Platform.DesktopWeb || platform === Platform.MobileWeb || platform === Platform.iOS) {
|
||||||
if ((link.kind === LinkKind.Event || link.kind === LinkKind.Room) && link.servers.length > 0) {
|
return `https://app.element.io/#/${fragmentPath}`;
|
||||||
fragmentPath += '?' + link.servers.map(server => `via=${encodeURIComponent(server)}`).join('&');
|
} else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) {
|
||||||
}
|
return `element://vector/webapp/#/${fragmentPath}`;
|
||||||
|
} else {
|
||||||
const isWebPlatform = platform === Platform.DesktopWeb || platform === Platform.MobileWeb;
|
|
||||||
if (isWebPlatform || platform === Platform.iOS) {
|
|
||||||
let instanceHost = trustedWebInstances[0];
|
|
||||||
// we use app.element.io which iOS will intercept, but it likely won't intercept any other trusted instances
|
|
||||||
// so only use a preferred web instance for true web links.
|
|
||||||
if (isWebPlatform && trustedWebInstances.includes(link.webInstances[this.id])) {
|
|
||||||
instanceHost = link.webInstances[this.id];
|
|
||||||
}
|
|
||||||
return `https://${instanceHost}/#/${fragmentPath}`;
|
|
||||||
} else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) {
|
|
||||||
return `element://vector/webapp/#/${fragmentPath}`;
|
|
||||||
} else {
|
|
||||||
return `element://${fragmentPath}`;
|
return `element://${fragmentPath}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {}
|
getLinkInstructions(platform, link) {}
|
||||||
getCopyString(platform, link) {}
|
getCopyString(platform, link) {}
|
||||||
getInstallLinks(platform) {
|
getInstallLinks(platform) {
|
||||||
switch (platform) {
|
switch (platform) {
|
||||||
case Platform.iOS: return [new AppleStoreLink('vector', 'id1083446067')];
|
case Platform.iOS: return [new AppleStoreLink('vector', 'id1083446067')];
|
||||||
case Platform.Android: return [new PlayStoreLink('im.vector.app'), new FDroidLink('im.vector.app')];
|
case Platform.Android: return [new PlayStoreLink('im.vector.app'), new FDroidLink('im.vector.app')];
|
||||||
default: return [new WebsiteLink("https://element.io/download")];
|
default: return [new WebsiteLink("https://element.io/get-started")];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
canInterceptMatrixToLinks(platform) {
|
canInterceptMatrixToLinks(platform) {
|
||||||
return platform === Platform.Android;
|
return platform === Platform.iOS || platform === Platform.Android;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreferredWebInstance(link) {
|
|
||||||
const idx = trustedWebInstances.indexOf(link.webInstances[this.id])
|
|
||||||
return idx === -1 ? undefined : trustedWebInstances[idx];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Maturity, Platform, LinkKind, FlathubLink, AppleStoreLink, PlayStoreLink, FDroidLink, WebsiteLink } from "../types.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information on how to deep link to a given matrix client.
|
|
||||||
*/
|
|
||||||
export class Fluffychat {
|
|
||||||
get id() { return "im.fluffychat"; }
|
|
||||||
get name() { return "FluffyChat"; }
|
|
||||||
get icon() { return "images/client-icons/fluffychat.svg"; }
|
|
||||||
get author() { return "Krille Fear"; }
|
|
||||||
get homepage() { return "https://fluffychat.im"; }
|
|
||||||
get platforms() {
|
|
||||||
return [
|
|
||||||
Platform.Android, Platform.iOS,
|
|
||||||
Platform.Windows, Platform.macOS, Platform.Linux,
|
|
||||||
Platform.DesktopWeb,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
get description() { return "Chat with your friends using the cutest messenger in the Matrix network"; }
|
|
||||||
getMaturity(platform) {
|
|
||||||
switch (platform) {
|
|
||||||
case Platform.Android: return Maturity.Stable;
|
|
||||||
case Platform.iOS: return Maturity.Stable;
|
|
||||||
case Platform.DesktopWeb: return Maturity.Stable;
|
|
||||||
case Platform.Linux: return Maturity.Stable;
|
|
||||||
case Platform.macOS: return Maturity.Beta;
|
|
||||||
case Platform.Windows: return Maturity.Beta;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getInstallLinks(platform) {
|
|
||||||
switch (platform) {
|
|
||||||
case Platform.iOS: return [new AppleStoreLink("fluffychat", "id1551469600")];
|
|
||||||
case Platform.Android: return [
|
|
||||||
new PlayStoreLink("chat.fluffy.fluffychat"),
|
|
||||||
new FDroidLink('chat.fluffy.fluffychat'),
|
|
||||||
];
|
|
||||||
case Platform.Linux: return [
|
|
||||||
new FlathubLink("im.fluffychat.Fluffychat"),
|
|
||||||
new WebsiteLink("https://fluffychat.im"),
|
|
||||||
];
|
|
||||||
default: return [new WebsiteLink("https://fluffychat.im")];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {
|
|
||||||
if (link.kind === LinkKind.User) {
|
|
||||||
switch (platform) {
|
|
||||||
case Platform.Android: return;
|
|
||||||
case Platform.DesktopWeb: return "Open the web app at https://fluffychat.im/web/ and log in to your account. Click on '+' and paste the username.";
|
|
||||||
default: return "Open the app and click on '+' and paste the username.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (link.kind === LinkKind.Room) {
|
|
||||||
switch (platform) {
|
|
||||||
case Platform.Android: return;
|
|
||||||
case Platform.DesktopWeb: return "Open the web app at https://fluffychat.im/web/ and log in to your account. Click on 'Discover' and paste the identifier.";
|
|
||||||
default: return "Open the app on your device. Click on 'Discover' and paste the identifier.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCopyString(platform, link) {
|
|
||||||
if (link.kind === LinkKind.User || link.kind === LinkKind.Room) {
|
|
||||||
return link.identifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getDeepLink(platform, link) {
|
|
||||||
switch (platform) {
|
|
||||||
case Platform.Android: return `im.fluffychat://chat/${link.identifier}`;
|
|
||||||
case Platform.iOS: return `im.fluffychat://chat/${link.identifier}`;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canInterceptMatrixToLinks(platform) {
|
|
||||||
return platform === Platform.Android;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
|
|
@ -20,50 +20,22 @@ import {Maturity, Platform, LinkKind, FlathubLink} from "../types.js";
|
||||||
* Information on how to deep link to a given matrix client.
|
* Information on how to deep link to a given matrix client.
|
||||||
*/
|
*/
|
||||||
export class Fractal {
|
export class Fractal {
|
||||||
get id() { return "fractal"; }
|
get id() { return "fractal"; }
|
||||||
get name() { return "Fractal"; }
|
get name() { return "Fractal"; }
|
||||||
get icon() { return "images/client-icons/fractal.svg"; }
|
get icon() { return "images/client-icons/fractal.png"; }
|
||||||
get author() { return "Daniel Garcia Moreno"; }
|
get author() { return "Daniel Garcia Moreno"; }
|
||||||
get homepage() { return "https://gitlab.gnome.org/World/fractal"; }
|
get homepage() { return "https://gitlab.gnome.org/GNOME/fractal"; }
|
||||||
get platforms() { return [Platform.Linux]; }
|
get platforms() { return [Platform.Linux]; }
|
||||||
get description() { return 'GNOME client, suitable for desktop and mobile. Written in Rust.'; }
|
get description() { return 'Fractal is a Matrix Client written in Rust.'; }
|
||||||
getMaturity(platform) { return Maturity.Beta; }
|
getMaturity(platform) { return Maturity.Beta; }
|
||||||
|
getDeepLink(platform, link) {}
|
||||||
|
canInterceptMatrixToLinks(platform) { return false; }
|
||||||
|
|
||||||
getDeepLink(platform, link) {
|
getLinkInstructions(platform, link) {
|
||||||
if (platform === Platform.Linux) {
|
|
||||||
let identifier = encodeURIComponent(link.identifier.substring(1));
|
|
||||||
let isRoomid = link.identifier.substring(0, 1) === '!';
|
|
||||||
let fragmentPath;
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User:
|
|
||||||
fragmentPath = `u/${identifier}?action=chat`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Room:
|
|
||||||
case LinkKind.Event:
|
|
||||||
if (isRoomid)
|
|
||||||
fragmentPath = `roomid/${identifier}`;
|
|
||||||
else
|
|
||||||
fragmentPath = `r/${identifier}`;
|
|
||||||
|
|
||||||
if (link.kind === LinkKind.Event)
|
|
||||||
fragmentPath += `/e/${encodeURIComponent(link.eventId.substring(1))}`;
|
|
||||||
fragmentPath += '?action=join';
|
|
||||||
fragmentPath += link.servers.map(server => `&via=${encodeURIComponent(server)}`).join('');
|
|
||||||
break;
|
|
||||||
case LinkKind.Group:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return `matrix:${fragmentPath}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canInterceptMatrixToLinks(platform) { return false; }
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {
|
|
||||||
if (link.kind === LinkKind.User || link.kind === LinkKind.Room) {
|
if (link.kind === LinkKind.User || link.kind === LinkKind.Room) {
|
||||||
return "Click the menu button above the list of rooms, select the Join Room entry, and paste the identifier";
|
return "Click the '+' button in the top right and paste the identifier";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCopyString(platform, link) {
|
getCopyString(platform, link) {
|
||||||
if (link.kind === LinkKind.User || link.kind === LinkKind.Room) {
|
if (link.kind === LinkKind.User || link.kind === LinkKind.Room) {
|
||||||
|
@ -71,11 +43,9 @@ export class Fractal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getInstallLinks(platform) {
|
getInstallLinks(platform) {
|
||||||
if (platform === Platform.Linux) {
|
if (platform === Platform.Linux) {
|
||||||
return [new FlathubLink("org.gnome.Fractal")];
|
return [new FlathubLink("org.gnome.Fractal")];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
Copyright 2021 Carl Schwan <carl@carlschwan.eu>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {Maturity, Platform, LinkKind, FlathubLink, style} from "../types.js";
|
|
||||||
|
|
||||||
export class NeoChat {
|
|
||||||
get id() { return "neochat"; }
|
|
||||||
get name() { return "NeoChat"; }
|
|
||||||
get icon() { return "images/client-icons/org.kde.neochat.svg"; }
|
|
||||||
get author() { return "Tobias Fella and Carl Schwan"; }
|
|
||||||
get homepage() { return "https://apps.kde.org/neochat/"; }
|
|
||||||
get platforms() { return [Platform.Linux]; }
|
|
||||||
get description() { return 'NeoChat is a convergent, cross-platform Matrix client.'; }
|
|
||||||
getMaturity(platform) { return Maturity.Beta; }
|
|
||||||
getDeepLink(platform, link) {
|
|
||||||
if (platform === Platform.Linux || platform === Platform.Windows) {
|
|
||||||
let identifier = encodeURIComponent(link.identifier.substring(1));
|
|
||||||
let isRoomid = link.identifier.substring(0, 1) === '!';
|
|
||||||
let fragmentPath;
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User:
|
|
||||||
fragmentPath = `u/${identifier}?action=chat`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Room:
|
|
||||||
case LinkKind.Event:
|
|
||||||
if (isRoomid)
|
|
||||||
fragmentPath = `roomid/${identifier}`;
|
|
||||||
else
|
|
||||||
fragmentPath = `r/${identifier}`;
|
|
||||||
|
|
||||||
if (link.kind === LinkKind.Event)
|
|
||||||
fragmentPath += `/e/${encodeURIComponent(link.eventId.substring(1))}`;
|
|
||||||
fragmentPath += '?action=join';
|
|
||||||
fragmentPath += link.servers.map(server => `&via=${encodeURIComponent(server)}`).join('');
|
|
||||||
break;
|
|
||||||
case LinkKind.Group:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return `matrix:${fragmentPath}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canInterceptMatrixToLinks(platform) { return false; }
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User: return [`Type `, style.code(`/invite ${link.identifier}`)];
|
|
||||||
case LinkKind.Room: return [`Type `, style.code(`/join ${link.identifier}`)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCopyString(platform, link) {
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User: return `/invite ${link.identifier}`;
|
|
||||||
case LinkKind.Room: return `/join ${link.identifier}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getInstallLinks(platform) {
|
|
||||||
if (platform === Platform.Linux) {
|
|
||||||
return [new FlathubLink("org.kde.neochat")];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
|
|
@ -14,55 +14,29 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Maturity, Platform, LinkKind, FlathubLink, WebsiteLink, style} from "../types.js";
|
import {Maturity, Platform, LinkKind, FlathubLink, style} from "../types.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information on how to deep link to a given matrix client.
|
* Information on how to deep link to a given matrix client.
|
||||||
*/
|
*/
|
||||||
export class Nheko {
|
export class Nheko {
|
||||||
get id() { return "nheko"; }
|
get id() { return "nheko"; }
|
||||||
get name() { return "Nheko"; }
|
get name() { return "Nheko"; }
|
||||||
get icon() { return "images/client-icons/nheko.svg"; }
|
get icon() { return "images/client-icons/nheko.svg"; }
|
||||||
get author() { return "mujx, red_sky, deepbluev7, Konstantinos Sideris"; }
|
get author() { return "mujx, red_sky, deepbluev7, Konstantinos Sideris"; }
|
||||||
get homepage() { return "https://github.com/Nheko-Reborn/nheko"; }
|
get homepage() { return "https://github.com/Nheko-Reborn/nheko"; }
|
||||||
get platforms() { return [Platform.Windows, Platform.macOS, Platform.Linux]; }
|
get platforms() { return [Platform.Windows, Platform.macOS, Platform.Linux]; }
|
||||||
get description() { return 'A native desktop app for Matrix that feels more like a mainstream chat app.'; }
|
get description() { return 'A native desktop app for Matrix that feels more like a mainstream chat app.'; }
|
||||||
getMaturity(platform) { return Maturity.Beta; }
|
getMaturity(platform) { return Maturity.Beta; }
|
||||||
getDeepLink(platform, link) {
|
getDeepLink(platform, link) {}
|
||||||
if (platform === Platform.Linux || platform === Platform.Windows) {
|
canInterceptMatrixToLinks(platform) { return false; }
|
||||||
let identifier = encodeURIComponent(link.identifier.substring(1));
|
|
||||||
let isRoomid = link.identifier.substring(0, 1) === '!';
|
|
||||||
let fragmentPath;
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User:
|
|
||||||
fragmentPath = `u/${identifier}?action=chat`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Room:
|
|
||||||
case LinkKind.Event:
|
|
||||||
if (isRoomid)
|
|
||||||
fragmentPath = `roomid/${identifier}`;
|
|
||||||
else
|
|
||||||
fragmentPath = `r/${identifier}`;
|
|
||||||
|
|
||||||
if (link.kind === LinkKind.Event)
|
getLinkInstructions(platform, link) {
|
||||||
fragmentPath += `/e/${encodeURIComponent(link.eventId.substring(1))}`;
|
switch (link.kind) {
|
||||||
fragmentPath += '?action=join';
|
case LinkKind.User: return [`Type `, style.code(`/invite ${link.identifier}`)];
|
||||||
fragmentPath += link.servers.map(server => `&via=${encodeURIComponent(server)}`).join('');
|
case LinkKind.Room: return [`Type `, style.code(`/join ${link.identifier}`)];
|
||||||
break;
|
}
|
||||||
case LinkKind.Group:
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
return `matrix:${fragmentPath}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canInterceptMatrixToLinks(platform) { return false; }
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User: return [`Type `, style.code(`/invite ${link.identifier}`)];
|
|
||||||
case LinkKind.Room: return [`Type `, style.code(`/join ${link.identifier}`)];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCopyString(platform, link) {
|
getCopyString(platform, link) {
|
||||||
switch (link.kind) {
|
switch (link.kind) {
|
||||||
|
@ -71,15 +45,9 @@ export class Nheko {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getInstallLinks(platform) {
|
getInstallLinks(platform) {
|
||||||
switch (platform) {
|
if (platform === Platform.Linux) {
|
||||||
case Platform.Linux: return [
|
return [new FlathubLink("io.github.NhekoReborn.Nheko")];
|
||||||
new FlathubLink("io.github.NhekoReborn.Nheko"),
|
|
||||||
new WebsiteLink("https://github.com/Nheko-Reborn/nheko/releases/latest"),
|
|
||||||
];
|
|
||||||
default: return [new WebsiteLink("https://github.com/Nheko-Reborn/nheko/releases/latest")];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Maturity, Platform, LinkKind, FlathubLink, WebsiteLink, style} from "../types.js";
|
import {Maturity, Platform, LinkKind, FlathubLink, style} from "../types.js";
|
||||||
|
|
||||||
export class Quaternion {
|
export class Quaternion {
|
||||||
get id() { return "quaternion"; }
|
get id() { return "quaternion"; }
|
||||||
get name() { return "Quaternion"; }
|
get name() { return "Quaternion"; }
|
||||||
get icon() { return "images/client-icons/quaternion.svg"; }
|
get icon() { return "images/client-icons/quaternion.svg"; }
|
||||||
get author() { return "The Quotient project"; }
|
get author() { return "Felix Rohrbach"; }
|
||||||
get homepage() { return "https://github.com/quotient-im/Quaternion"; }
|
get homepage() { return "https://github.com/Fxrh/Quaternion"; }
|
||||||
get platforms() { return [Platform.Windows, Platform.macOS, Platform.Linux]; }
|
get platforms() { return [Platform.Windows, Platform.macOS, Platform.Linux]; }
|
||||||
get description() { return 'Qt5 and C++ cross-platform desktop Matrix client.'; }
|
get description() { return 'Qt5 and C++ cross-platform desktop Matrix client.'; }
|
||||||
getMaturity(platform) { return Maturity.Beta; }
|
getMaturity(platform) { return Maturity.Beta; }
|
||||||
|
@ -43,14 +43,8 @@ export class Quaternion {
|
||||||
}
|
}
|
||||||
|
|
||||||
getInstallLinks(platform) {
|
getInstallLinks(platform) {
|
||||||
switch (platform) {
|
if (platform === Platform.Linux) {
|
||||||
case Platform.Linux: return [
|
return [new FlathubLink("com.github.quaternion")];
|
||||||
new FlathubLink("com.github.quaternion"),
|
|
||||||
new WebsiteLink("https://github.com/quotient-im/Quaternion/releases/latest"),
|
|
||||||
];
|
|
||||||
default: return [new WebsiteLink("https://github.com/quotient-im/Quaternion/releases/latest")];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,112 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {
|
|
||||||
Maturity, Platform, LinkKind,
|
|
||||||
FDroidLink, FlathubLink, PlayStoreLink, WebsiteLink
|
|
||||||
} from "../types.js";
|
|
||||||
|
|
||||||
const trustedWebInstances = [
|
|
||||||
"app.schildi.chat", // first one is the default one
|
|
||||||
"test.schildi.chat",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information on how to deep link to a given matrix client.
|
|
||||||
*/
|
|
||||||
export class SchildiChat {
|
|
||||||
get id() { return "schildi.chat"; }
|
|
||||||
|
|
||||||
get platforms() {
|
|
||||||
return [
|
|
||||||
Platform.Android,
|
|
||||||
Platform.Windows, Platform.macOS, Platform.Linux,
|
|
||||||
Platform.DesktopWeb
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
get icon() { return "images/client-icons/schildichat.svg"; }
|
|
||||||
get name() { return "SchildiChat"; }
|
|
||||||
get description() { return 'Feature-rich messenger for Matrix based on Element with some extras and tweaks.'; }
|
|
||||||
get homepage() { return "https://schildi.chat"; }
|
|
||||||
get author() { return "SchildiChat team"; }
|
|
||||||
getMaturity(platform) { return Maturity.Stable; }
|
|
||||||
|
|
||||||
getDeepLink(platform, link) {
|
|
||||||
let fragmentPath;
|
|
||||||
switch (link.kind) {
|
|
||||||
case LinkKind.User:
|
|
||||||
fragmentPath = `user/${encodeURIComponent(link.identifier)}`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Room:
|
|
||||||
fragmentPath = `room/${encodeURIComponent(link.identifier)}`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Group:
|
|
||||||
fragmentPath = `group/${encodeURIComponent(link.identifier)}`;
|
|
||||||
break;
|
|
||||||
case LinkKind.Event:
|
|
||||||
fragmentPath = `room/${encodeURIComponent(link.identifier)}/${encodeURIComponent(link.eventId)}`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((link.kind === LinkKind.Event || link.kind === LinkKind.Room) && link.servers.length > 0) {
|
|
||||||
fragmentPath += '?' + link.servers.map(server => `via=${encodeURIComponent(server)}`).join('&');
|
|
||||||
}
|
|
||||||
|
|
||||||
const isWebPlatform = platform === Platform.DesktopWeb || platform === Platform.MobileWeb;
|
|
||||||
if (isWebPlatform) {
|
|
||||||
let instanceHost = trustedWebInstances[0];
|
|
||||||
if (isWebPlatform && trustedWebInstances.includes(link.webInstances[this.id])) {
|
|
||||||
instanceHost = link.webInstances[this.id];
|
|
||||||
}
|
|
||||||
return `https://${instanceHost}/#/${fragmentPath}`;
|
|
||||||
} else if (platform === Platform.Linux || platform === Platform.Windows || platform === Platform.macOS) {
|
|
||||||
return `schildichat://vector/webapp/#/${fragmentPath}`;
|
|
||||||
} else {
|
|
||||||
return `schildichat://${fragmentPath}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) { }
|
|
||||||
getCopyString(platform, link) { }
|
|
||||||
getInstallLinks(platform) {
|
|
||||||
switch (platform) {
|
|
||||||
case Platform.Linux:
|
|
||||||
return [
|
|
||||||
new FlathubLink("chat.schildi.desktop"),
|
|
||||||
new WebsiteLink("https://schildi.chat/desktop/"),
|
|
||||||
]
|
|
||||||
case Platform.Windows || Platform.macOS:
|
|
||||||
return [new WebsiteLink("https://schildi.chat/desktop/")];
|
|
||||||
case Platform.Android:
|
|
||||||
return [
|
|
||||||
new PlayStoreLink('de.spiritcroc.riotx'),
|
|
||||||
new FDroidLink('de.spiritcroc.riotx'),
|
|
||||||
new WebsiteLink("https://schildi.chat/android/"),
|
|
||||||
];
|
|
||||||
default: return [new WebsiteLink("https://schildi.chat")];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canInterceptMatrixToLinks(platform) {
|
|
||||||
return platform === Platform.Android;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreferredWebInstance(link) {
|
|
||||||
const idx = trustedWebInstances.indexOf(link.webInstances[this.id])
|
|
||||||
return idx === -1 ? undefined : trustedWebInstances[idx];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
Copyright 2022 0x1a8510f2 <admin@0x1a8510f2.space>
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Maturity, Platform, LinkKind, FlathubLink, AppleStoreLink, PlayStoreLink, FDroidLink, WebsiteLink } from "../types.js";
|
|
||||||
|
|
||||||
export class Syphon {
|
|
||||||
get id() { return "org.syphon.syphon"; }
|
|
||||||
get name() { return "Syphon"; }
|
|
||||||
get icon() { return "images/client-icons/syphon.svg"; }
|
|
||||||
get author() { return "Taylor Ereio"; }
|
|
||||||
get homepage() { return "https://syphon.org"; }
|
|
||||||
get platforms() {
|
|
||||||
return [
|
|
||||||
Platform.Android,
|
|
||||||
Platform.iOS,
|
|
||||||
Platform.Linux,
|
|
||||||
Platform.Windows,
|
|
||||||
Platform.macOS,
|
|
||||||
//Platform.DesktopWeb, // Supported by flutter but no builds yet
|
|
||||||
];
|
|
||||||
}
|
|
||||||
get description() {
|
|
||||||
return "chat with your privacy and freedom intact";
|
|
||||||
}
|
|
||||||
|
|
||||||
getMaturity(platform) {
|
|
||||||
return Maturity.Alpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
getInstallLinks(platform) {
|
|
||||||
switch (platform) {
|
|
||||||
case Platform.Android: return [
|
|
||||||
new PlayStoreLink("org.tether.tether"),
|
|
||||||
new FDroidLink("org.tether.tether"),
|
|
||||||
];
|
|
||||||
case Platform.iOS: return [
|
|
||||||
new AppleStoreLink("syphon", "id1496285352")
|
|
||||||
];
|
|
||||||
case Platform.Linux: return [
|
|
||||||
new FlathubLink("org.syphon.Syphon"),
|
|
||||||
new WebsiteLink("https://syphon.org"),
|
|
||||||
];
|
|
||||||
default: return [new WebsiteLink("https://syphon.org")];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {
|
|
||||||
if (link.kind === LinkKind.User) {
|
|
||||||
return "Open the app, click on the direct message button (inside the floating button \
|
|
||||||
at the bottom), then paste the identifier.";
|
|
||||||
}
|
|
||||||
if (link.kind === LinkKind.Room) {
|
|
||||||
return "Open the app, click on the search public rooms button (inside the floating button \
|
|
||||||
at the bottom), then paste the identifier.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCopyString(platform, link) {
|
|
||||||
if (link.kind === LinkKind.User || link.kind === LinkKind.Room) {
|
|
||||||
return link.identifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getDeepLink(platform, link) {
|
|
||||||
/*switch (platform) {
|
|
||||||
case Platform.Android: return `org.tether.tether://chat/${link.identifier}`;
|
|
||||||
case Platform.iOS: return `org.tether.tether://chat/${link.identifier}`;
|
|
||||||
default: break;
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
canInterceptMatrixToLinks(platform) {
|
|
||||||
return platform === Platform.Android;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
|
|
@ -47,6 +47,4 @@ export class Tensor {
|
||||||
return [new FDroidLink("io.davidar.tensor")];
|
return [new FDroidLink("io.davidar.tensor")];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Maturity, Platform, LinkKind, FlathubLink, WebsiteLink, style} from "../types.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information on how to deep link to a given matrix client.
|
|
||||||
*/
|
|
||||||
export class Thunderbird {
|
|
||||||
get id() { return "thunderbird"; }
|
|
||||||
get name() { return "Thunderbird"; }
|
|
||||||
get icon() { return "images/client-icons/thunderbird.svg"; }
|
|
||||||
get author() { return "MZLA Technologies Corporation"; }
|
|
||||||
get homepage() { return "https://www.thunderbird.net"; }
|
|
||||||
get platforms() {
|
|
||||||
return [
|
|
||||||
Platform.Windows, Platform.macOS, Platform.Linux,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
get description() { return "Thunderbird is a free open-source email, calendar & chat app."; }
|
|
||||||
getMaturity(platform) {
|
|
||||||
return Maturity.Beta;
|
|
||||||
}
|
|
||||||
|
|
||||||
getInstallLinks(platform) {
|
|
||||||
const links = [];
|
|
||||||
if (platform === Platform.Linux) {
|
|
||||||
links.push(new FlathubLink("org.mozilla.Thunderbird"));
|
|
||||||
}
|
|
||||||
links.push(new WebsiteLink(this.homepage));
|
|
||||||
return links;
|
|
||||||
}
|
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {
|
|
||||||
if (link.kind === LinkKind.User) {
|
|
||||||
return "Open the Chat tab, click on 'Add Contact' and paste the username.";
|
|
||||||
}
|
|
||||||
if (link.kind === LinkKind.Room) {
|
|
||||||
return [
|
|
||||||
"Open the Chat tab, click on 'Join Chat' and paste the identifier or type ",
|
|
||||||
style.code(`/join ${link.identifier}`),
|
|
||||||
" in an existing Matrix conversation."
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCopyString(platform, link) {
|
|
||||||
if (link.kind === LinkKind.User || link.kind === LinkKind.Room) {
|
|
||||||
return link.identifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getDeepLink(platform, link) {}
|
|
||||||
|
|
||||||
canInterceptMatrixToLinks(platform) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
|
|
@ -20,23 +20,23 @@ import {Maturity, Platform, LinkKind, WebsiteLink, style} from "../types.js";
|
||||||
* Information on how to deep link to a given matrix client.
|
* Information on how to deep link to a given matrix client.
|
||||||
*/
|
*/
|
||||||
export class Weechat {
|
export class Weechat {
|
||||||
get id() { return "weechat"; }
|
get id() { return "weechat"; }
|
||||||
get name() { return "Weechat"; }
|
get name() { return "Weechat"; }
|
||||||
get icon() { return "images/client-icons/weechat.svg"; }
|
get icon() { return "images/client-icons/weechat.svg"; }
|
||||||
get author() { return "Poljar"; }
|
get author() { return "Poljar"; }
|
||||||
get homepage() { return "https://github.com/poljar/weechat-matrix"; }
|
get homepage() { return "https://github.com/poljar/weechat-matrix"; }
|
||||||
get platforms() { return [Platform.Windows, Platform.macOS, Platform.Linux]; }
|
get platforms() { return [Platform.Windows, Platform.macOS, Platform.Linux]; }
|
||||||
get description() { return 'Command-line Matrix interface using Weechat.'; }
|
get description() { return 'Command-line Matrix interface using Weechat'; }
|
||||||
getMaturity(platform) { return Maturity.Beta; }
|
getMaturity(platform) { return Maturity.Beta; }
|
||||||
getDeepLink(platform, link) {}
|
getDeepLink(platform, link) {}
|
||||||
canInterceptMatrixToLinks(platform) { return false; }
|
canInterceptMatrixToLinks(platform) { return false; }
|
||||||
|
|
||||||
getLinkInstructions(platform, link) {
|
getLinkInstructions(platform, link) {
|
||||||
switch (link.kind) {
|
switch (link.kind) {
|
||||||
case LinkKind.User: return [`Type `, style.code(`/invite ${link.identifier}`)];
|
case LinkKind.User: return [`Type `, style.code(`/invite ${link.identifier}`)];
|
||||||
case LinkKind.Room: return [`Type `, style.code(`/join ${link.identifier}`)];
|
case LinkKind.Room: return [`Type `, style.code(`/join ${link.identifier}`)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCopyString(platform, link) {
|
getCopyString(platform, link) {
|
||||||
switch (link.kind) {
|
switch (link.kind) {
|
||||||
|
@ -45,7 +45,5 @@ export class Weechat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getInstallLinks(platform) {}
|
getInstallLinks(platform) {}
|
||||||
|
|
||||||
getPreferredWebInstance(link) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,31 +15,18 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Element} from "./Element.js";
|
import {Element} from "./Element.js";
|
||||||
import {SchildiChat} from "./SchildiChat.js";
|
|
||||||
import {Weechat} from "./Weechat.js";
|
import {Weechat} from "./Weechat.js";
|
||||||
import {Nheko} from "./Nheko.js";
|
import {Nheko} from "./Nheko.js";
|
||||||
import {Fractal} from "./Fractal.js";
|
import {Fractal} from "./Fractal.js";
|
||||||
import {Quaternion} from "./Quaternion.js";
|
import {Quaternion} from "./Quaternion.js";
|
||||||
import {Tensor} from "./Tensor.js";
|
import {Tensor} from "./Tensor.js";
|
||||||
import {Fluffychat} from "./Fluffychat.js";
|
|
||||||
import {NeoChat} from "./NeoChat.js";
|
|
||||||
import {Syphon} from "./Syphon.js";
|
|
||||||
import {Thunderbird} from "./Thunderbird.js";
|
|
||||||
import {Cinny} from "./Cinny.js"
|
|
||||||
|
|
||||||
export function createClients() {
|
export function createClients() {
|
||||||
return [
|
return [
|
||||||
new Element(),
|
new Element(),
|
||||||
new SchildiChat(),
|
new Weechat(),
|
||||||
new Weechat(),
|
|
||||||
new Nheko(),
|
new Nheko(),
|
||||||
new Fractal(),
|
|
||||||
new Quaternion(),
|
new Quaternion(),
|
||||||
new Tensor(),
|
new Tensor(),
|
||||||
new Fluffychat(),
|
];
|
||||||
new NeoChat(),
|
|
||||||
new Syphon(),
|
|
||||||
new Thunderbird(),
|
|
||||||
new Cinny(),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ export {Platform} from "../Platform.js";
|
||||||
|
|
||||||
export class AppleStoreLink {
|
export class AppleStoreLink {
|
||||||
constructor(org, appId) {
|
constructor(org, appId) {
|
||||||
this._org = org;
|
this._org = org;
|
||||||
this._appId = appId;
|
this._appId = appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
createInstallURL(link) {
|
createInstallURL(link) {
|
||||||
|
@ -40,7 +40,7 @@ export class AppleStoreLink {
|
||||||
|
|
||||||
export class PlayStoreLink {
|
export class PlayStoreLink {
|
||||||
constructor(appId) {
|
constructor(appId) {
|
||||||
this._appId = appId;
|
this._appId = appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
createInstallURL(link) {
|
createInstallURL(link) {
|
||||||
|
@ -58,7 +58,7 @@ export class PlayStoreLink {
|
||||||
|
|
||||||
export class FDroidLink {
|
export class FDroidLink {
|
||||||
constructor(appId) {
|
constructor(appId) {
|
||||||
this._appId = appId;
|
this._appId = appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
createInstallURL(link) {
|
createInstallURL(link) {
|
||||||
|
@ -94,7 +94,7 @@ export class FlathubLink {
|
||||||
|
|
||||||
export class WebsiteLink {
|
export class WebsiteLink {
|
||||||
constructor(url) {
|
constructor(url) {
|
||||||
this._url = url;
|
this._url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
createInstallURL(link) {
|
createInstallURL(link) {
|
||||||
|
|
|
@ -17,10 +17,10 @@ limitations under the License.
|
||||||
import {TemplateView} from "../utils/TemplateView.js";
|
import {TemplateView} from "../utils/TemplateView.js";
|
||||||
|
|
||||||
export class LoadServerPolicyView extends TemplateView {
|
export class LoadServerPolicyView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
return t.div({className: "LoadServerPolicyView card"}, [
|
return t.div({className: "LoadServerPolicyView card"}, [
|
||||||
t.div({className: {spinner: true, hidden: vm => !vm.loading}}),
|
t.div({className: {spinner: true, hidden: vm => !vm.loading}}),
|
||||||
t.h2(vm => vm.message)
|
t.h2(vm => vm.message)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,12 @@ import {ViewModel} from "../utils/ViewModel.js";
|
||||||
import {resolveServer} from "../preview/HomeServer.js";
|
import {resolveServer} from "../preview/HomeServer.js";
|
||||||
|
|
||||||
export class LoadServerPolicyViewModel extends ViewModel {
|
export class LoadServerPolicyViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
this.server = options.server;
|
this.server = options.server;
|
||||||
this.message = `Looking up ${this.server} privacy policy…`;
|
this.message = `Looking up ${this.server} privacy policy…`;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
|
@ -14,82 +14,62 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function noTrailingSlash(url) {
|
|
||||||
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function resolveServer(request, baseURL) {
|
export async function resolveServer(request, baseURL) {
|
||||||
baseURL = noTrailingSlash(baseURL);
|
if (!baseURL.startsWith("http://") && !baseURL.startsWith("https://")) {
|
||||||
if (!baseURL.startsWith("http://") && !baseURL.startsWith("https://")) {
|
baseURL = `https://${baseURL}`;
|
||||||
baseURL = `https://${baseURL}`;
|
}
|
||||||
}
|
{
|
||||||
{
|
const {status, body} = await request(`${baseURL}/.well-known/matrix/client`, {method: "GET"}).response();
|
||||||
try {
|
if (status === 200) {
|
||||||
const {status, body} = await request(`${baseURL}/.well-known/matrix/client`, {method: "GET"}).response();
|
const proposedBaseURL = body?.['m.homeserver']?.base_url;
|
||||||
if (status === 200) {
|
if (typeof proposedBaseURL === "string") {
|
||||||
const proposedBaseURL = body?.['m.homeserver']?.base_url;
|
baseURL = proposedBaseURL;
|
||||||
if (typeof proposedBaseURL === "string") {
|
}
|
||||||
baseURL = noTrailingSlash(proposedBaseURL);
|
}
|
||||||
}
|
}
|
||||||
}
|
{
|
||||||
} catch (e) {
|
const {status} = await request(`${baseURL}/_matrix/client/versions`, {method: "GET"}).response();
|
||||||
console.warn("Failed to fetch ${baseURL}/.well-known/matrix/client", e);
|
if (status !== 200) {
|
||||||
}
|
throw new Error(`Invalid versions response from ${baseURL}`);
|
||||||
}
|
}
|
||||||
{
|
}
|
||||||
const {status} = await request(`${baseURL}/_matrix/client/versions`, {method: "GET"}).response();
|
return new HomeServer(request, baseURL);
|
||||||
if (status !== 200) {
|
|
||||||
throw new Error(`Invalid versions response from ${baseURL}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new HomeServer(request, baseURL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HomeServer {
|
export class HomeServer {
|
||||||
constructor(request, baseURL) {
|
constructor(request, baseURL) {
|
||||||
this._request = request;
|
this._request = request;
|
||||||
this.baseURL = baseURL;
|
this.baseURL = baseURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getUserProfile(userId) {
|
async getUserProfile(userId) {
|
||||||
const {body} = await this._request(`${this.baseURL}/_matrix/client/r0/profile/${encodeURIComponent(userId)}`).response();
|
const {body} = await this._request(`${this.baseURL}/_matrix/client/r0/profile/${encodeURIComponent(userId)}`).response();
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MSC3266 implementation
|
async findPublicRoomById(roomId) {
|
||||||
async getRoomSummary(roomIdOrAlias, viaServers) {
|
const {body, status} = await this._request(`${this.baseURL}/_matrix/client/r0/directory/list/room/${encodeURIComponent(roomId)}`).response();
|
||||||
let query;
|
if (status !== 200 || body.visibility !== "public") {
|
||||||
if (viaServers.length > 0) {
|
return;
|
||||||
query = "?" + viaServers.map(server => `via=${encodeURIComponent(server)}`).join('&');
|
}
|
||||||
}
|
let nextBatch;
|
||||||
const {body, status} = await this._request(`${this.baseURL}/_matrix/client/unstable/im.nheko.summary/rooms/${encodeURIComponent(roomIdOrAlias)}/summary${query}`).response();
|
do {
|
||||||
if (status !== 200) return;
|
const queryParams = encodeQueryParams({limit: 10000, since: nextBatch});
|
||||||
return body;
|
const {body, status} = await this._request(`${this.baseURL}/_matrix/client/r0/publicRooms?${queryParams}`).response();
|
||||||
}
|
nextBatch = body.next_batch;
|
||||||
|
const publicRoom = body.chunk.find(c => c.room_id === roomId);
|
||||||
|
if (publicRoom) {
|
||||||
|
return publicRoom;
|
||||||
|
}
|
||||||
|
} while (nextBatch);
|
||||||
|
}
|
||||||
|
|
||||||
async findPublicRoomById(roomId) {
|
async getRoomIdFromAlias(alias) {
|
||||||
const {body, status} = await this._request(`${this.baseURL}/_matrix/client/r0/directory/list/room/${encodeURIComponent(roomId)}`).response();
|
const {status, body} = await this._request(`${this.baseURL}/_matrix/client/r0/directory/room/${encodeURIComponent(alias)}`).response();
|
||||||
if (status !== 200 || body.visibility !== "public") {
|
if (status === 200) {
|
||||||
return;
|
return body.room_id;
|
||||||
}
|
}
|
||||||
let nextBatch;
|
}
|
||||||
do {
|
|
||||||
const queryParams = encodeQueryParams({limit: 10000, since: nextBatch});
|
|
||||||
const {body, status} = await this._request(`${this.baseURL}/_matrix/client/r0/publicRooms?${queryParams}`).response();
|
|
||||||
nextBatch = body.next_batch;
|
|
||||||
const publicRoom = body.chunk.find(c => c.room_id === roomId);
|
|
||||||
if (publicRoom) {
|
|
||||||
return publicRoom;
|
|
||||||
}
|
|
||||||
} while (nextBatch);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRoomIdFromAlias(alias) {
|
|
||||||
const {status, body} = await this._request(`${this.baseURL}/_matrix/client/r0/directory/room/${encodeURIComponent(alias)}`).response();
|
|
||||||
if (status === 200) {
|
|
||||||
return body.room_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getPrivacyPolicyUrl(lang = "en") {
|
async getPrivacyPolicyUrl(lang = "en") {
|
||||||
const headers = new Map();
|
const headers = new Map();
|
||||||
|
@ -109,7 +89,7 @@ export class HomeServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mxcUrlThumbnail(url, width, height, method) {
|
mxcUrlThumbnail(url, width, height, method) {
|
||||||
const parts = parseMxcUrl(url);
|
const parts = parseMxcUrl(url);
|
||||||
if (parts) {
|
if (parts) {
|
||||||
const [serverName, mediaId] = parts;
|
const [serverName, mediaId] = parts;
|
||||||
|
@ -123,7 +103,7 @@ export class HomeServer {
|
||||||
function parseMxcUrl(url) {
|
function parseMxcUrl(url) {
|
||||||
const prefix = "mxc://";
|
const prefix = "mxc://";
|
||||||
if (url.startsWith(prefix)) {
|
if (url.startsWith(prefix)) {
|
||||||
return url.slice(prefix.length).split("/", 2);
|
return url.substr(prefix.length).split("/", 2);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,20 +43,20 @@ class LoadingPreviewView extends TemplateView {
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadedPreviewView extends TemplateView {
|
class LoadedPreviewView extends TemplateView {
|
||||||
render(t, vm) {
|
render(t, vm) {
|
||||||
const avatar = t.map(vm => vm.avatarUrl, (avatarUrl, t) => {
|
const avatar = t.mapView(vm => vm.avatarUrl, avatarUrl => {
|
||||||
if (avatarUrl) {
|
if (avatarUrl) {
|
||||||
return t.img({className: "avatar", src: avatarUrl});
|
return new TemplateView(avatarUrl, (t, src) => t.img({className: "avatar", src}));
|
||||||
} else {
|
} else {
|
||||||
return t.div({className: "defaultAvatar"});
|
return new TemplateView(null, t => t.div({className: "defaultAvatar"}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return t.div({className: vm.isSpaceRoom ? "mxSpace" : undefined}, [
|
return t.div([
|
||||||
t.div({className: "avatarContainer"}, avatar),
|
t.div({className: "avatarContainer"}, avatar),
|
||||||
t.h1(vm => vm.name),
|
t.h1(vm => vm.name),
|
||||||
t.p({className: {identifier: true, hidden: vm => !vm.identifier}}, vm => vm.identifier),
|
t.p({className: {identifier: true, hidden: vm => !vm.identifier}}, vm => vm.identifier),
|
||||||
t.div({className: {memberCount: true, hidden: vm => !vm.memberCount}}, t.p([vm => vm.memberCount, " members"])),
|
t.div({className: {memberCount: true, hidden: vm => !vm.memberCount}}, t.p([vm => vm.memberCount, " members"])),
|
||||||
t.p({className: {topic: true, hidden: vm => !vm.topic}}, [vm => vm.topic]),
|
t.p({className: {topic: true, hidden: vm => !vm.topic}}, [vm => vm.topic]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,101 +21,92 @@ import {ClientListViewModel} from "../open/ClientListViewModel.js";
|
||||||
import {ClientViewModel} from "../open/ClientViewModel.js";
|
import {ClientViewModel} from "../open/ClientViewModel.js";
|
||||||
|
|
||||||
export class PreviewViewModel extends ViewModel {
|
export class PreviewViewModel extends ViewModel {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
super(options);
|
super(options);
|
||||||
const { link, consentedServers } = options;
|
const { link, consentedServers } = options;
|
||||||
this._link = link;
|
this._link = link;
|
||||||
this._consentedServers = consentedServers;
|
this._consentedServers = consentedServers;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.name = this._link.identifier;
|
this.name = this._link.identifier;
|
||||||
this.avatarUrl = null;
|
this.avatarUrl = null;
|
||||||
this.identifier = null;
|
this.identifier = null;
|
||||||
this.memberCount = null;
|
this.memberCount = null;
|
||||||
this.topic = null;
|
this.topic = null;
|
||||||
this.domain = null;
|
this.domain = null;
|
||||||
this.failed = false;
|
this.failed = false;
|
||||||
this.isSpaceRoom = false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
const {kind} = this._link;
|
const {kind} = this._link;
|
||||||
const supportsPreview = kind === LinkKind.User || kind === LinkKind.Room || kind === LinkKind.Event;
|
const supportsPreview = kind === LinkKind.User || kind === LinkKind.Room || kind === LinkKind.Event;
|
||||||
if (supportsPreview) {
|
if (supportsPreview) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
for (const server of this._consentedServers) {
|
for (const server of this._consentedServers) {
|
||||||
try {
|
try {
|
||||||
const homeserver = await resolveServer(this.request, server);
|
const homeserver = await resolveServer(this.request, server);
|
||||||
switch (this._link.kind) {
|
switch (this._link.kind) {
|
||||||
case LinkKind.User:
|
case LinkKind.User:
|
||||||
await this._loadUserPreview(homeserver, this._link.identifier);
|
await this._loadUserPreview(homeserver, this._link.identifier);
|
||||||
break;
|
break;
|
||||||
case LinkKind.Room:
|
case LinkKind.Room:
|
||||||
case LinkKind.Event:
|
case LinkKind.Event:
|
||||||
await this._loadRoomPreview(homeserver, this._link);
|
await this._loadRoomPreview(homeserver, this._link);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// assume we're done if nothing threw
|
// assume we're done if nothing threw
|
||||||
this.domain = server;
|
this.domain = server;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
return;
|
return;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this._setNoPreview(this._link);
|
this._setNoPreview(this._link);
|
||||||
if (this._consentedServers.length && supportsPreview) {
|
if (this._consentedServers.length && supportsPreview) {
|
||||||
this.domain = this._consentedServers[this._consentedServers.length - 1];
|
this.domain = this._consentedServers[this._consentedServers.length - 1];
|
||||||
this.failed = true;
|
this.failed = true;
|
||||||
}
|
}
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasTopic() { return this._link.kind === LinkKind.Room; }
|
get hasTopic() { return this._link.kind === LinkKind.Room; }
|
||||||
get hasMemberCount() { return this.hasTopic; }
|
get hasMemberCount() { return this.hasTopic; }
|
||||||
|
|
||||||
async _loadUserPreview(homeserver, userId) {
|
async _loadUserPreview(homeserver, userId) {
|
||||||
const profile = await homeserver.getUserProfile(userId);
|
const profile = await homeserver.getUserProfile(userId);
|
||||||
this.name = profile.displayname || userId;
|
this.name = profile.displayname || userId;
|
||||||
this.avatarUrl = profile.avatar_url ?
|
this.avatarUrl = profile.avatar_url ?
|
||||||
homeserver.mxcUrlThumbnail(profile.avatar_url, 64, 64, "crop") :
|
homeserver.mxcUrlThumbnail(profile.avatar_url, 64, 64, "crop") :
|
||||||
null;
|
null;
|
||||||
this.identifier = userId;
|
this.identifier = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
async _loadRoomPreview(homeserver, link) {
|
async _loadRoomPreview(homeserver, link) {
|
||||||
let publicRoom;
|
let publicRoom;
|
||||||
if (link.identifierKind === IdentifierKind.RoomId || link.identifierKind === IdentifierKind.RoomAlias) {
|
if (link.identifierKind === IdentifierKind.RoomId) {
|
||||||
publicRoom = await homeserver.getRoomSummary(link.identifier, link.servers);
|
publicRoom = await homeserver.findPublicRoomById(link.identifier);
|
||||||
}
|
} else if (link.identifierKind === IdentifierKind.RoomAlias) {
|
||||||
|
const roomId = await homeserver.getRoomIdFromAlias(link.identifier);
|
||||||
if (!publicRoom) {
|
if (roomId) {
|
||||||
if (link.identifierKind === IdentifierKind.RoomId) {
|
publicRoom = await homeserver.findPublicRoomById(roomId);
|
||||||
publicRoom = await homeserver.findPublicRoomById(link.identifier);
|
}
|
||||||
} else if (link.identifierKind === IdentifierKind.RoomAlias) {
|
}
|
||||||
const roomId = await homeserver.getRoomIdFromAlias(link.identifier);
|
this.name = publicRoom?.name || publicRoom?.canonical_alias || link.identifier;
|
||||||
if (roomId) {
|
this.avatarUrl = publicRoom?.avatar_url ?
|
||||||
publicRoom = await homeserver.findPublicRoomById(roomId);
|
homeserver.mxcUrlThumbnail(publicRoom.avatar_url, 64, 64, "crop") :
|
||||||
}
|
null;
|
||||||
}
|
this.memberCount = publicRoom?.num_joined_members;
|
||||||
}
|
this.topic = publicRoom?.topic;
|
||||||
|
this.identifier = publicRoom?.canonical_alias || link.identifier;
|
||||||
this.name = publicRoom?.name || publicRoom?.canonical_alias || link.identifier;
|
|
||||||
this.avatarUrl = publicRoom?.avatar_url ?
|
|
||||||
homeserver.mxcUrlThumbnail(publicRoom.avatar_url, 64, 64, "crop") :
|
|
||||||
null;
|
|
||||||
this.memberCount = publicRoom?.num_joined_members;
|
|
||||||
this.topic = publicRoom?.topic;
|
|
||||||
this.identifier = publicRoom?.canonical_alias || link.identifier;
|
|
||||||
this.isSpaceRoom = publicRoom?.room_type === "m.space";
|
|
||||||
if (this.identifier === this.name) {
|
if (this.identifier === this.name) {
|
||||||
this.identifier = null;
|
this.identifier = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setNoPreview(link) {
|
_setNoPreview(link) {
|
||||||
this.name = link.identifier;
|
this.name = link.identifier;
|
||||||
|
|
|
@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { setAttribute, text, isChildren, classNames, TAG_NAMES, HTML_NS } from "./html.js";
|
import { setAttribute, text, isChildren, classNames, TAG_NAMES, HTML_NS, tag } from "./html.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Bindable template. Renders once, and allows bindings for given nodes. If you need
|
Bindable template. Renders once, and allows bindings for given nodes. If you need
|
||||||
|
@ -33,13 +33,11 @@ import { setAttribute, text, isChildren, classNames, TAG_NAMES, HTML_NS } from "
|
||||||
export class TemplateView {
|
export class TemplateView {
|
||||||
constructor(value, render = undefined) {
|
constructor(value, render = undefined) {
|
||||||
this._value = value;
|
this._value = value;
|
||||||
// TODO: can avoid this if we have a separate class for inline templates vs class template views
|
|
||||||
this._render = render;
|
this._render = render;
|
||||||
this._eventListeners = null;
|
this._eventListeners = null;
|
||||||
this._bindings = null;
|
this._bindings = null;
|
||||||
this._subViews = null;
|
this._subViews = null;
|
||||||
this._root = null;
|
this._root = null;
|
||||||
// TODO: can avoid this if we adopt the handleEvent pattern in our EventListener
|
|
||||||
this._boundUpdateFromValue = null;
|
this._boundUpdateFromValue = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,10 +108,6 @@ export class TemplateView {
|
||||||
return this._root;
|
return this._root;
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateFromValue(changedProps) {
|
|
||||||
this.update(this._value, changedProps);
|
|
||||||
}
|
|
||||||
|
|
||||||
update(value) {
|
update(value) {
|
||||||
this._value = value;
|
this._value = value;
|
||||||
if (this._bindings) {
|
if (this._bindings) {
|
||||||
|
@ -123,6 +117,10 @@ export class TemplateView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateFromValue(changedProps) {
|
||||||
|
this.update(this._value, changedProps);
|
||||||
|
}
|
||||||
|
|
||||||
_addEventListener(node, name, fn, useCapture = false) {
|
_addEventListener(node, name, fn, useCapture = false) {
|
||||||
if (!this._eventListeners) {
|
if (!this._eventListeners) {
|
||||||
this._eventListeners = [];
|
this._eventListeners = [];
|
||||||
|
@ -137,19 +135,12 @@ export class TemplateView {
|
||||||
this._bindings.push(bindingFn);
|
this._bindings.push(bindingFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
addSubView(view) {
|
_addSubView(view) {
|
||||||
if (!this._subViews) {
|
if (!this._subViews) {
|
||||||
this._subViews = [];
|
this._subViews = [];
|
||||||
}
|
}
|
||||||
this._subViews.push(view);
|
this._subViews.push(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
removeSubView(view) {
|
|
||||||
const idx = this._subViews.indexOf(view);
|
|
||||||
if (idx !== -1) {
|
|
||||||
this._subViews.splice(idx, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// what is passed to render
|
// what is passed to render
|
||||||
|
@ -210,7 +201,7 @@ class TemplateBuilder {
|
||||||
setAttribute(node, key, classNames(value));
|
setAttribute(node, key, classNames(value));
|
||||||
}
|
}
|
||||||
} else if (key.startsWith("on") && key.length > 2 && isFn) {
|
} else if (key.startsWith("on") && key.length > 2 && isFn) {
|
||||||
const eventName = key.slice(2, 3).toLowerCase() + key.slice(3);
|
const eventName = key.substr(2, 1).toLowerCase() + key.substr(3);
|
||||||
const handler = value;
|
const handler = value;
|
||||||
this._templateView._addEventListener(node, eventName, handler);
|
this._templateView._addEventListener(node, eventName, handler);
|
||||||
} else if (isFn) {
|
} else if (isFn) {
|
||||||
|
@ -247,6 +238,8 @@ class TemplateBuilder {
|
||||||
const newNode = renderNode(node);
|
const newNode = renderNode(node);
|
||||||
if (node.parentNode) {
|
if (node.parentNode) {
|
||||||
node.parentNode.replaceChild(newNode, node);
|
node.parentNode.replaceChild(newNode, node);
|
||||||
|
} else {
|
||||||
|
console.warn("Could not update parent of node binding");
|
||||||
}
|
}
|
||||||
node = newNode;
|
node = newNode;
|
||||||
}
|
}
|
||||||
|
@ -286,10 +279,15 @@ class TemplateBuilder {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return errorToDOM(err);
|
return errorToDOM(err);
|
||||||
}
|
}
|
||||||
this._templateView.addSubView(view);
|
this._templateView._addSubView(view);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sugar
|
||||||
|
createTemplate(render) {
|
||||||
|
return vm => new TemplateView(vm, render);
|
||||||
|
}
|
||||||
|
|
||||||
// map a value to a view, every time the value changes
|
// map a value to a view, every time the value changes
|
||||||
mapView(mapFn, viewCreator) {
|
mapView(mapFn, viewCreator) {
|
||||||
return this._addReplaceNodeBinding(mapFn, (prevNode) => {
|
return this._addReplaceNodeBinding(mapFn, (prevNode) => {
|
||||||
|
@ -310,37 +308,16 @@ class TemplateBuilder {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case of mapView for a TemplateView.
|
// creates a conditional subtemplate
|
||||||
// Always creates a TemplateView, if this is optional depending
|
if(fn, viewCreator) {
|
||||||
// on mappedValue, use `if` or `mapView`
|
|
||||||
map(mapFn, renderFn) {
|
|
||||||
return this.mapView(mapFn, mappedValue => {
|
|
||||||
return new TemplateView(this._value, (t, vm) => {
|
|
||||||
const rootNode = renderFn(mappedValue, t, vm);
|
|
||||||
if (!rootNode) {
|
|
||||||
// TODO: this will confuse mapView which assumes that
|
|
||||||
// a comment node means there is no view to clean up
|
|
||||||
return document.createComment("map placeholder");
|
|
||||||
}
|
|
||||||
return rootNode;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ifView(predicate, viewCreator) {
|
|
||||||
return this.mapView(
|
return this.mapView(
|
||||||
value => !!predicate(value),
|
value => !!fn(value),
|
||||||
enabled => enabled ? viewCreator(this._value) : null
|
enabled => enabled ? viewCreator(this._value) : null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// creates a conditional subtemplate
|
|
||||||
// use mapView if you need to map to a different view class
|
|
||||||
if(predicate, renderFn) {
|
|
||||||
return this.ifView(predicate, vm => new TemplateView(vm, renderFn));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function errorToDOM(error) {
|
function errorToDOM(error) {
|
||||||
const stack = new Error().stack;
|
const stack = new Error().stack;
|
||||||
const callee = stack.split("\n")[1];
|
const callee = stack.split("\n")[1];
|
||||||
|
|
384
yarn.lock
|
@ -9,14 +9,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.10.4"
|
"@babel/highlight" "^7.10.4"
|
||||||
|
|
||||||
"@babel/code-frame@^7.22.13":
|
|
||||||
version "7.22.13"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
|
|
||||||
integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
|
|
||||||
dependencies:
|
|
||||||
"@babel/highlight" "^7.22.13"
|
|
||||||
chalk "^2.4.2"
|
|
||||||
|
|
||||||
"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7":
|
"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7":
|
||||||
version "7.12.7"
|
version "7.12.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41"
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41"
|
||||||
|
@ -53,16 +45,6 @@
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
source-map "^0.5.0"
|
source-map "^0.5.0"
|
||||||
|
|
||||||
"@babel/generator@^7.23.0":
|
|
||||||
version "7.23.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
|
|
||||||
integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
|
|
||||||
dependencies:
|
|
||||||
"@babel/types" "^7.23.0"
|
|
||||||
"@jridgewell/gen-mapping" "^0.3.2"
|
|
||||||
"@jridgewell/trace-mapping" "^0.3.17"
|
|
||||||
jsesc "^2.5.1"
|
|
||||||
|
|
||||||
"@babel/helper-annotate-as-pure@^7.10.4":
|
"@babel/helper-annotate-as-pure@^7.10.4":
|
||||||
version "7.10.4"
|
version "7.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3"
|
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3"
|
||||||
|
@ -116,11 +98,6 @@
|
||||||
"@babel/types" "^7.10.5"
|
"@babel/types" "^7.10.5"
|
||||||
lodash "^4.17.19"
|
lodash "^4.17.19"
|
||||||
|
|
||||||
"@babel/helper-environment-visitor@^7.22.20":
|
|
||||||
version "7.22.20"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
|
|
||||||
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
|
|
||||||
|
|
||||||
"@babel/helper-explode-assignable-expression@^7.10.4":
|
"@babel/helper-explode-assignable-expression@^7.10.4":
|
||||||
version "7.12.1"
|
version "7.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633"
|
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633"
|
||||||
|
@ -137,14 +114,6 @@
|
||||||
"@babel/template" "^7.10.4"
|
"@babel/template" "^7.10.4"
|
||||||
"@babel/types" "^7.10.4"
|
"@babel/types" "^7.10.4"
|
||||||
|
|
||||||
"@babel/helper-function-name@^7.23.0":
|
|
||||||
version "7.23.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
|
|
||||||
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
|
|
||||||
dependencies:
|
|
||||||
"@babel/template" "^7.22.15"
|
|
||||||
"@babel/types" "^7.23.0"
|
|
||||||
|
|
||||||
"@babel/helper-get-function-arity@^7.10.4":
|
"@babel/helper-get-function-arity@^7.10.4":
|
||||||
version "7.10.4"
|
version "7.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2"
|
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2"
|
||||||
|
@ -159,13 +128,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.10.4"
|
"@babel/types" "^7.10.4"
|
||||||
|
|
||||||
"@babel/helper-hoist-variables@^7.22.5":
|
|
||||||
version "7.22.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
|
|
||||||
integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
|
|
||||||
dependencies:
|
|
||||||
"@babel/types" "^7.22.5"
|
|
||||||
|
|
||||||
"@babel/helper-member-expression-to-functions@^7.12.1":
|
"@babel/helper-member-expression-to-functions@^7.12.1":
|
||||||
version "7.12.7"
|
version "7.12.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855"
|
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855"
|
||||||
|
@ -247,28 +209,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.11.0"
|
"@babel/types" "^7.11.0"
|
||||||
|
|
||||||
"@babel/helper-split-export-declaration@^7.22.6":
|
|
||||||
version "7.22.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
|
|
||||||
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
|
|
||||||
dependencies:
|
|
||||||
"@babel/types" "^7.22.5"
|
|
||||||
|
|
||||||
"@babel/helper-string-parser@^7.22.5":
|
|
||||||
version "7.22.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
|
|
||||||
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
|
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.10.4":
|
"@babel/helper-validator-identifier@^7.10.4":
|
||||||
version "7.10.4"
|
version "7.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
|
||||||
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
|
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
|
||||||
|
|
||||||
"@babel/helper-validator-identifier@^7.22.20":
|
|
||||||
version "7.22.20"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
|
||||||
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
|
||||||
|
|
||||||
"@babel/helper-validator-option@^7.12.1":
|
"@babel/helper-validator-option@^7.12.1":
|
||||||
version "7.12.1"
|
version "7.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9"
|
||||||
|
@ -302,25 +247,11 @@
|
||||||
chalk "^2.0.0"
|
chalk "^2.0.0"
|
||||||
js-tokens "^4.0.0"
|
js-tokens "^4.0.0"
|
||||||
|
|
||||||
"@babel/highlight@^7.22.13":
|
|
||||||
version "7.22.20"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
|
|
||||||
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-validator-identifier" "^7.22.20"
|
|
||||||
chalk "^2.4.2"
|
|
||||||
js-tokens "^4.0.0"
|
|
||||||
|
|
||||||
"@babel/parser@^7.12.7":
|
"@babel/parser@^7.12.7":
|
||||||
version "7.12.7"
|
version "7.12.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056"
|
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056"
|
||||||
integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==
|
integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==
|
||||||
|
|
||||||
"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
|
|
||||||
version "7.23.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
|
|
||||||
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
|
|
||||||
|
|
||||||
"@babel/plugin-proposal-async-generator-functions@^7.12.1":
|
"@babel/plugin-proposal-async-generator-functions@^7.12.1":
|
||||||
version "7.12.1"
|
version "7.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e"
|
||||||
|
@ -860,30 +791,20 @@
|
||||||
"@babel/parser" "^7.12.7"
|
"@babel/parser" "^7.12.7"
|
||||||
"@babel/types" "^7.12.7"
|
"@babel/types" "^7.12.7"
|
||||||
|
|
||||||
"@babel/template@^7.22.15":
|
|
||||||
version "7.22.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
|
||||||
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
|
|
||||||
dependencies:
|
|
||||||
"@babel/code-frame" "^7.22.13"
|
|
||||||
"@babel/parser" "^7.22.15"
|
|
||||||
"@babel/types" "^7.22.15"
|
|
||||||
|
|
||||||
"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9":
|
"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9":
|
||||||
version "7.23.2"
|
version "7.12.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.9.tgz#fad26c972eabbc11350e0b695978de6cc8e8596f"
|
||||||
integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
|
integrity sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.22.13"
|
"@babel/code-frame" "^7.10.4"
|
||||||
"@babel/generator" "^7.23.0"
|
"@babel/generator" "^7.12.5"
|
||||||
"@babel/helper-environment-visitor" "^7.22.20"
|
"@babel/helper-function-name" "^7.10.4"
|
||||||
"@babel/helper-function-name" "^7.23.0"
|
"@babel/helper-split-export-declaration" "^7.11.0"
|
||||||
"@babel/helper-hoist-variables" "^7.22.5"
|
"@babel/parser" "^7.12.7"
|
||||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
"@babel/types" "^7.12.7"
|
||||||
"@babel/parser" "^7.23.0"
|
|
||||||
"@babel/types" "^7.23.0"
|
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
|
lodash "^4.17.19"
|
||||||
|
|
||||||
"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4":
|
"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4":
|
||||||
version "7.12.7"
|
version "7.12.7"
|
||||||
|
@ -894,82 +815,6 @@
|
||||||
lodash "^4.17.19"
|
lodash "^4.17.19"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0":
|
|
||||||
version "7.23.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
|
|
||||||
integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
|
|
||||||
dependencies:
|
|
||||||
"@babel/helper-string-parser" "^7.22.5"
|
|
||||||
"@babel/helper-validator-identifier" "^7.22.20"
|
|
||||||
to-fast-properties "^2.0.0"
|
|
||||||
|
|
||||||
"@jridgewell/gen-mapping@^0.3.0":
|
|
||||||
version "0.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
|
||||||
integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
|
|
||||||
dependencies:
|
|
||||||
"@jridgewell/set-array" "^1.0.1"
|
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
|
||||||
"@jridgewell/trace-mapping" "^0.3.9"
|
|
||||||
|
|
||||||
"@jridgewell/gen-mapping@^0.3.2":
|
|
||||||
version "0.3.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
|
|
||||||
integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
|
|
||||||
dependencies:
|
|
||||||
"@jridgewell/set-array" "^1.0.1"
|
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
|
||||||
"@jridgewell/trace-mapping" "^0.3.9"
|
|
||||||
|
|
||||||
"@jridgewell/resolve-uri@^3.0.3":
|
|
||||||
version "3.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
|
||||||
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
|
||||||
|
|
||||||
"@jridgewell/resolve-uri@^3.1.0":
|
|
||||||
version "3.1.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
|
|
||||||
integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
|
|
||||||
|
|
||||||
"@jridgewell/set-array@^1.0.1":
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
|
||||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
|
||||||
|
|
||||||
"@jridgewell/source-map@^0.3.2":
|
|
||||||
version "0.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
|
|
||||||
integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==
|
|
||||||
dependencies:
|
|
||||||
"@jridgewell/gen-mapping" "^0.3.0"
|
|
||||||
"@jridgewell/trace-mapping" "^0.3.9"
|
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec@^1.4.10":
|
|
||||||
version "1.4.14"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
|
||||||
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec@^1.4.14":
|
|
||||||
version "1.4.15"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
|
|
||||||
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
|
|
||||||
|
|
||||||
"@jridgewell/trace-mapping@^0.3.17":
|
|
||||||
version "0.3.19"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811"
|
|
||||||
integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==
|
|
||||||
dependencies:
|
|
||||||
"@jridgewell/resolve-uri" "^3.1.0"
|
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
|
||||||
|
|
||||||
"@jridgewell/trace-mapping@^0.3.9":
|
|
||||||
version "0.3.14"
|
|
||||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
|
|
||||||
integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
|
|
||||||
dependencies:
|
|
||||||
"@jridgewell/resolve-uri" "^3.0.3"
|
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
|
||||||
|
|
||||||
"@rollup/plugin-babel@^5.1.0":
|
"@rollup/plugin-babel@^5.1.0":
|
||||||
version "5.2.2"
|
version "5.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz#e5623a01dd8e37e004ba87f2de218c611727d9b2"
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.2.2.tgz#e5623a01dd8e37e004ba87f2de218c611727d9b2"
|
||||||
|
@ -1055,11 +900,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
acorn@^8.5.0:
|
|
||||||
version "8.7.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
|
|
||||||
integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
|
|
||||||
|
|
||||||
ansi-styles@^3.2.1:
|
ansi-styles@^3.2.1:
|
||||||
version "3.2.1"
|
version "3.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
|
||||||
|
@ -1068,15 +908,15 @@ ansi-styles@^3.2.1:
|
||||||
color-convert "^1.9.0"
|
color-convert "^1.9.0"
|
||||||
|
|
||||||
autoprefixer@^10.0.1:
|
autoprefixer@^10.0.1:
|
||||||
version "10.1.0"
|
version "10.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.1.0.tgz#b19fd8524edef8c85c9db3bdb0c998de84e172fb"
|
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.0.4.tgz#f87ac6105d7861e31af794b8ebb1c6d4390d3d55"
|
||||||
integrity sha512-0/lBNwN+ZUnb5su18NZo5MBIjDaq6boQKZcxwy86Gip/CmXA2zZqUoFQLCNAGI5P25ZWSP2RWdhDJ8osfKEjoQ==
|
integrity sha512-hmjYejN/WTyPP9cdNmiwtwqM8/ACVJPD5ExtwoOceQohNbgnFNiwpL2+U4bXS8aXozBL00WvH6WhqbuHf0Fgfg==
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist "^4.15.0"
|
browserslist "^4.14.7"
|
||||||
caniuse-lite "^1.0.30001165"
|
caniuse-lite "^1.0.30001161"
|
||||||
colorette "^1.2.1"
|
colorette "^1.2.1"
|
||||||
fraction.js "^4.0.12"
|
|
||||||
normalize-range "^0.1.2"
|
normalize-range "^0.1.2"
|
||||||
|
num2fraction "^1.2.2"
|
||||||
postcss-value-parser "^4.1.0"
|
postcss-value-parser "^4.1.0"
|
||||||
|
|
||||||
babel-plugin-dynamic-import-node@^2.3.3:
|
babel-plugin-dynamic-import-node@^2.3.3:
|
||||||
|
@ -1087,9 +927,9 @@ babel-plugin-dynamic-import-node@^2.3.3:
|
||||||
object.assign "^4.1.0"
|
object.assign "^4.1.0"
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||||
|
|
||||||
boolbase@~1.0.0:
|
boolbase@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
|
@ -1104,21 +944,21 @@ brace-expansion@^1.1.7:
|
||||||
balanced-match "^1.0.0"
|
balanced-match "^1.0.0"
|
||||||
concat-map "0.0.1"
|
concat-map "0.0.1"
|
||||||
|
|
||||||
browserslist@^4.14.5, browserslist@^4.15.0:
|
browserslist@^4.14.5, browserslist@^4.14.7:
|
||||||
version "4.16.6"
|
version "4.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.15.0.tgz#3d48bbca6a3f378e86102ffd017d9a03f122bdb0"
|
||||||
integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==
|
integrity sha512-IJ1iysdMkGmjjYeRlDU8PQejVwxvVO5QOfXH7ylW31GO6LwNRSmm/SgRXtNsEXqMLl2e+2H5eEJ7sfynF8TCaQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite "^1.0.30001219"
|
caniuse-lite "^1.0.30001164"
|
||||||
colorette "^1.2.2"
|
colorette "^1.2.1"
|
||||||
electron-to-chromium "^1.3.723"
|
electron-to-chromium "^1.3.612"
|
||||||
escalade "^3.1.1"
|
escalade "^3.1.1"
|
||||||
node-releases "^1.1.71"
|
node-releases "^1.1.67"
|
||||||
|
|
||||||
buffer-from@^1.0.0:
|
buffer-from@^1.0.0:
|
||||||
version "1.1.2"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||||
|
|
||||||
builtin-modules@^3.1.0:
|
builtin-modules@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
|
@ -1133,10 +973,10 @@ call-bind@^1.0.0:
|
||||||
function-bind "^1.1.1"
|
function-bind "^1.1.1"
|
||||||
get-intrinsic "^1.0.0"
|
get-intrinsic "^1.0.0"
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001165, caniuse-lite@^1.0.30001219:
|
caniuse-lite@^1.0.30001161, caniuse-lite@^1.0.30001164:
|
||||||
version "1.0.30001230"
|
version "1.0.30001164"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001164.tgz#5bbfd64ca605d43132f13cc7fdabb17c3036bfdc"
|
||||||
integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ==
|
integrity sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg==
|
||||||
|
|
||||||
chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
|
chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
|
@ -1171,10 +1011,10 @@ color-name@1.1.3:
|
||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||||
|
|
||||||
colorette@^1.2.1, colorette@^1.2.2:
|
colorette@^1.2.1:
|
||||||
version "1.2.2"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
|
||||||
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
|
||||||
|
|
||||||
commander@^2.20.0:
|
commander@^2.20.0:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
|
@ -1189,7 +1029,7 @@ commondir@^1.0.1:
|
||||||
concat-map@0.0.1:
|
concat-map@0.0.1:
|
||||||
version "0.0.1"
|
version "0.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
convert-source-map@^1.7.0:
|
convert-source-map@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
|
@ -1199,17 +1039,17 @@ convert-source-map@^1.7.0:
|
||||||
safe-buffer "~5.1.1"
|
safe-buffer "~5.1.1"
|
||||||
|
|
||||||
core-js-compat@^3.7.0:
|
core-js-compat@^3.7.0:
|
||||||
version "3.8.1"
|
version "3.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.1.tgz#8d1ddd341d660ba6194cbe0ce60f4c794c87a36e"
|
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.8.0.tgz#3248c6826f4006793bd637db608bca6e4cd688b1"
|
||||||
integrity sha512-a16TLmy9NVD1rkjUGbwuyWkiDoN0FDpAwrfLONvHFQx0D9k7J9y0srwMT8QP/Z6HE3MIFaVynEeYwZwPX1o5RQ==
|
integrity sha512-o9QKelQSxQMYWHXc/Gc4L8bx/4F7TTraE5rhuN8I7mKBt5dBIUpXpIR3omv70ebr8ST5R3PqbDQr+ZI3+Tt1FQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
browserslist "^4.15.0"
|
browserslist "^4.14.7"
|
||||||
semver "7.0.0"
|
semver "7.0.0"
|
||||||
|
|
||||||
core-js@^3.6.5:
|
core-js@^3.6.5:
|
||||||
version "3.8.1"
|
version "3.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.1.tgz#f51523668ac8a294d1285c3b9db44025fda66d47"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.0.tgz#0fc2d4941cadf80538b030648bb64d230b4da0ce"
|
||||||
integrity sha512-9Id2xHY1W7m8hCl8NkhQn5CufmF/WuR30BTRewvCXc1aZd3kMECwNZ69ndLbekKfakw9Rf2Xyc+QR6E7Gg+obg==
|
integrity sha512-W2VYNB0nwQQE7tKS7HzXd7r2y/y2SVJl4ga6oH/dnaLFzM0o2lB2P3zCkWj5Wc/zyMYjtgd5Hmhk0ObkQFZOIA==
|
||||||
|
|
||||||
css-select@~1.2.0:
|
css-select@~1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
|
@ -1321,10 +1161,10 @@ ee-first@1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||||
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
|
||||||
|
|
||||||
electron-to-chromium@^1.3.723:
|
electron-to-chromium@^1.3.612:
|
||||||
version "1.3.739"
|
version "1.3.613"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.739.tgz#f07756aa92cabd5a6eec6f491525a64fe62f98b9"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.613.tgz#5ad7ec1e19d28c81edb6d61b9d4990d1c9716182"
|
||||||
integrity sha512-+LPJVRsN7hGZ9EIUUiWCpO7l4E3qBYHNadazlucBfsXBbccDFNKUBAgzE68FnkWGJPwD/AfKhSzL+G+Iqb8A4A==
|
integrity sha512-c3gkahddiUalk7HLhTC7PsKzPZmovYFtgh+g3rZJ+dGokk4n4dzEoOBnoV8VU8ptvnGJMhrjM/lyXKSltqf2hQ==
|
||||||
|
|
||||||
encodeurl@~1.0.2:
|
encodeurl@~1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
|
@ -1394,11 +1234,6 @@ finalhandler@^1.1.2:
|
||||||
statuses "~1.5.0"
|
statuses "~1.5.0"
|
||||||
unpipe "~1.0.0"
|
unpipe "~1.0.0"
|
||||||
|
|
||||||
fraction.js@^4.0.12:
|
|
||||||
version "4.0.12"
|
|
||||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.0.12.tgz#0526d47c65a5fb4854df78bc77f7bec708d7b8c3"
|
|
||||||
integrity sha512-8Z1K0VTG4hzYY7kA/1sj4/r1/RWLBD3xwReT/RCrUCbzPszjNQCCsy3ktkU/eaEqX3MYa4pY37a52eiBlPMlhA==
|
|
||||||
|
|
||||||
fresh@0.5.2:
|
fresh@0.5.2:
|
||||||
version "0.5.2"
|
version "0.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||||
|
@ -1552,14 +1387,16 @@ jsesc@~0.5.0:
|
||||||
integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
|
integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
|
||||||
|
|
||||||
json5@^2.1.2:
|
json5@^2.1.2:
|
||||||
version "2.2.3"
|
version "2.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
|
||||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
|
||||||
|
dependencies:
|
||||||
|
minimist "^1.2.5"
|
||||||
|
|
||||||
lodash@^4.15.0, lodash@^4.17.19:
|
lodash@^4.15.0, lodash@^4.17.19:
|
||||||
version "4.17.21"
|
version "4.17.20"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||||
|
|
||||||
magic-string@^0.25.7:
|
magic-string@^0.25.7:
|
||||||
version "0.25.7"
|
version "0.25.7"
|
||||||
|
@ -1597,16 +1434,16 @@ mime@^2.3.1:
|
||||||
integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
|
integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==
|
||||||
|
|
||||||
minimatch@^3.0.4:
|
minimatch@^3.0.4:
|
||||||
version "3.1.2"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
minimist@^1.2.5:
|
minimist@^1.2.5:
|
||||||
version "1.2.7"
|
version "1.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
|
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||||
|
|
||||||
mkdirp@^0.5.0:
|
mkdirp@^0.5.0:
|
||||||
version "0.5.5"
|
version "0.5.5"
|
||||||
|
@ -1630,15 +1467,15 @@ ms@2.1.2:
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
nanoid@^3.3.6:
|
nanoid@^3.1.18:
|
||||||
version "3.3.7"
|
version "3.1.20"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
|
||||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
|
||||||
|
|
||||||
node-releases@^1.1.71:
|
node-releases@^1.1.67:
|
||||||
version "1.1.72"
|
version "1.1.67"
|
||||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe"
|
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12"
|
||||||
integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==
|
integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==
|
||||||
|
|
||||||
normalize-range@^0.1.2:
|
normalize-range@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
|
@ -1652,6 +1489,11 @@ nth-check@~1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
boolbase "~1.0.0"
|
boolbase "~1.0.0"
|
||||||
|
|
||||||
|
num2fraction@^1.2.2:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||||
|
integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
|
||||||
|
|
||||||
object-keys@^1.0.12, object-keys@^1.1.1:
|
object-keys@^1.0.12, object-keys@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||||
|
@ -1699,14 +1541,9 @@ path-is-absolute@^1.0.0:
|
||||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||||
|
|
||||||
path-parse@^1.0.6:
|
path-parse@^1.0.6:
|
||||||
version "1.0.7"
|
version "1.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
||||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
||||||
|
|
||||||
picocolors@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
|
||||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
|
||||||
|
|
||||||
picomatch@^2.2.1, picomatch@^2.2.2:
|
picomatch@^2.2.1, picomatch@^2.2.2:
|
||||||
version "2.2.2"
|
version "2.2.2"
|
||||||
|
@ -1784,14 +1621,15 @@ postcss@^7.0.1, postcss@^7.0.2, postcss@^7.0.26:
|
||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
supports-color "^6.1.0"
|
supports-color "^6.1.0"
|
||||||
|
|
||||||
postcss@^8.4.31:
|
postcss@^8.1.1:
|
||||||
version "8.4.31"
|
version "8.1.10"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.10.tgz#129834f94c720554d2cfdaeb27d5542ac4a026ea"
|
||||||
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
integrity sha512-iBXEV5VTTYaRRdxiFYzTtuv2lGMQBExqkZKSzkJe+Fl6rvQrA/49UVGKqB+LG54hpW/TtDBMGds8j33GFNW7pg==
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid "^3.3.6"
|
colorette "^1.2.1"
|
||||||
picocolors "^1.0.0"
|
nanoid "^3.1.18"
|
||||||
source-map-js "^1.0.2"
|
source-map "^0.6.1"
|
||||||
|
vfile-location "^3.2.0"
|
||||||
|
|
||||||
randombytes@^2.1.0:
|
randombytes@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
|
@ -1888,9 +1726,9 @@ rollup-plugin-terser@^7.0.2:
|
||||||
terser "^5.0.0"
|
terser "^5.0.0"
|
||||||
|
|
||||||
rollup@^2.26.4:
|
rollup@^2.26.4:
|
||||||
version "2.34.2"
|
version "2.34.0"
|
||||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.34.2.tgz#fa73e05c64df587e9ed4dc80d7d4e7d4a43f8908"
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.34.0.tgz#ecc7f1d4ce2cb88bb51bec2f56b984f3c35b8271"
|
||||||
integrity sha512-mvtQLqu3cNeoctS+kZ09iOPxrc1P1/Bt1z15enuQ5feyKOdM3MJAVFjjsygurDpSWn530xB4AlA83TWIzRstXA==
|
integrity sha512-dW5iLvttZzdVehjEuNJ1bWvuMEJjOWGmnuFS82WeKHTGXDkRHQeq/ExdifkSyJv9dLcR86ysKRmrIDyR6O0X8g==
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.1.2"
|
fsevents "~2.1.2"
|
||||||
|
|
||||||
|
@ -1910,9 +1748,9 @@ semver@7.0.0:
|
||||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||||
|
|
||||||
semver@^5.4.1, semver@^5.5.0:
|
semver@^5.4.1, semver@^5.5.0:
|
||||||
version "5.7.2"
|
version "5.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
|
|
||||||
send@0.17.1:
|
send@0.17.1:
|
||||||
version "0.17.1"
|
version "0.17.1"
|
||||||
|
@ -1955,15 +1793,10 @@ setprototypeof@1.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
|
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
|
||||||
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
|
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
|
||||||
|
|
||||||
source-map-js@^1.0.2:
|
source-map-support@~0.5.19:
|
||||||
version "1.0.2"
|
version "0.5.19"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
||||||
|
|
||||||
source-map-support@~0.5.20:
|
|
||||||
version "0.5.21"
|
|
||||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
|
||||||
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer-from "^1.0.0"
|
buffer-from "^1.0.0"
|
||||||
source-map "^0.6.0"
|
source-map "^0.6.0"
|
||||||
|
@ -1978,6 +1811,11 @@ source-map@^0.6.0, source-map@^0.6.1:
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
|
||||||
|
source-map@~0.7.2:
|
||||||
|
version "0.7.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||||
|
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||||
|
|
||||||
sourcemap-codec@^1.4.4:
|
sourcemap-codec@^1.4.4:
|
||||||
version "1.4.8"
|
version "1.4.8"
|
||||||
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
|
||||||
|
@ -2017,14 +1855,13 @@ supports-color@^7.0.0:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
terser@^5.0.0:
|
terser@^5.0.0:
|
||||||
version "5.14.2"
|
version "5.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10"
|
resolved "https://registry.yarnpkg.com/terser/-/terser-5.5.1.tgz#540caa25139d6f496fdea056e414284886fb2289"
|
||||||
integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==
|
integrity sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jridgewell/source-map" "^0.3.2"
|
|
||||||
acorn "^8.5.0"
|
|
||||||
commander "^2.20.0"
|
commander "^2.20.0"
|
||||||
source-map-support "~0.5.20"
|
source-map "~0.7.2"
|
||||||
|
source-map-support "~0.5.19"
|
||||||
|
|
||||||
to-fast-properties@^2.0.0:
|
to-fast-properties@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
|
@ -2069,6 +1906,11 @@ util-deprecate@^1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||||
|
|
||||||
|
vfile-location@^3.2.0:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c"
|
||||||
|
integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==
|
||||||
|
|
||||||
wrappy@1:
|
wrappy@1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
|