Skip to content
Snippets Groups Projects
HomePage.js 18.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
    Copyright 2016 OpenMarket Ltd
    
    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 React from 'react'
    
    var linkable_clients = [
        {
    
            name: "Element",
    
    Jorik Schellekens's avatar
    Jorik Schellekens committed
                width: "48px",
                src: "img/element.svg",
    
            author: "Element",
            homepage: "https://element.io",
            room_url(alias)  { return "https://app.element.io/#/room/" + alias },
            room_id_url(id)  { return "https://app.element.io/#/room/" + id },
            user_url(userId) { return "https://app.element.io/#/user/" + userId },
            msg_url(msg)     { return "https://app.element.io/#/room/" + msg },
            group_url(group)     { return "https://app.element.io/#/group/" + group },
    
            maturity: "Stable",
    
            comments: "Fully-featured Matrix client for Web, iOS & Android",
        },
    
        {
            name: "Matrix-Static",
            logo: "img/matrix-static-48px.png",
            author: "Michael Telatynski",
            homepage: "https://github.com/t3chguy/matrix-static",
    
            room_url(alias) { return "https://view.matrix.org/alias/" + alias.replace(/#/g, '%23') },
    
            room_id_url(id) { return "https://view.matrix.org/room/" + id },
            maturity: "Stable",
            comments: "A static golang generated preview of public world readable Matrix rooms.",
        },
    
    ];
    
    var unlinkable_clients = [
        {
            name: "Weechat",
    
            logo: "img/weechat-48px.png",
    
            author: "Poljar",
            homepage: "https://github.com/poljar/weechat-matrix",
    
            maturity: "Late beta",
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
            room_instructions(alias)  { return <span>Type <code>/join <b>{ alias }</b></code></span> },
            user_instructions(userId) { return <span>Type <code>/invite <b>{ userId }</b></code></span> },
    
            comments: "Commandline Matrix interface using Weechat",
        },
        {
            name: "Quaternion",
    
            logo: "img/quaternion-48px.png",
    
            author: "Felix Rohrbach",
            homepage: "https://github.com/Fxrh/Quaternion",
            maturity: "Late alpha",
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
            room_instructions(alias)  { return <span>Type <code>/join <b>{ alias }</b></code></span> },
            user_instructions(userId) { return <span>Type <code>/invite <b>{ userId }</b></code></span> },
    
            comments: "Qt5 and C++ cross-platform desktop Matrix client",
        },
        {
            name: "Tensor",
    
            logo: "img/tensor-48px.png",
    
            author: "David A Roberts",
            homepage: "https://github.com/davidar/tensor",
            maturity: "Late alpha",
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
            room_instructions(alias)  { return <span>Type <code>/join <b>{ alias }</b></code></span> },
            user_instructions(userId) { return <span>Type <code>/invite <b>{ userId }</b></code></span> },
    
            comments: "QML and JS cross-platform desktop Matrix client",
        },
    
        {
            name: "Nheko",
            logo: "img/nheko.png",
            author: "Konstantinos Sideris",
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
            homepage: "https://github.com/Nheko-Reborn/nheko",
            maturity: "Beta",
    
            room_instructions(alias)  { return <span>Type <code>/join <b>{ alias }</b></code></span> },
            comments: "Qt5 and C++ desktop client",
        },
    
        {
            name: "Mclient.el",
            logo: "",
            author: "Ryan Rix",
            homepage: "http://fort.kickass.systems:10082/cgit/personal/rrix/pub/matrix.el.git/",
            maturity: "Alpha",
            comments: "Matrix client for Gnu Emacs",
    
    lub's avatar
    lub committed
        },
    
    BrainBlasted's avatar
    BrainBlasted committed
        {
            name: "Fractal",
            logo: "img/org.gnome.Fractal.svg",
            author: "Daniel Garcia Moreno",
            maturity: "Alpha",
            comments: "Matrix messaging app for GNOME written in Rust"
    
    matrixsite's avatar
    matrixsite committed
        },
    
    lub's avatar
    lub committed
        {
            name: "Matrix IRCd",
            logo: "img/ircd-48px.png",
            author: "matrix.org",
            homepage: "https://github.com/matrix-org/matrix-ircd",
            room_instructions(alias)  { return <span>Type <code>/join <b>{ alias }</b></code></span> },
            maturity: "Alpha",
            comments: "Access any room anywhere in Matrix via good old IRC!",
    
    lub's avatar
    lub committed
        }
    
    ];
    
    export default React.createClass({
    
        getInitialState() {
            return {
                error: null,
                entity: null,
                showLink: false,
            }
        },
    
        onHashChange() {
    
            var entity = unescape(window.location.hash.substr(2)); // strip off #/ prefix
    
            if (!entity) {
                this.setState({
                    entity: null,
                    showLink: false,
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                    error: null,
    
    lub's avatar
    lub committed
            if (!this.isAliasValid(entity) && !this.isUserIdValid(entity) && !this.isMsglinkValid(entity) && !this.isRoomIdValid(entity) && !this.isGroupValid(entity)) {
    
                this.setState({
                    entity: entity,
    
    lub's avatar
    lub committed
                    error: "Invalid room alias, user ID, message permalink or group '" + entity + "'",
    
                });
                return;
            }
            this.setState({
                entity: entity,
                showLink: true,
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                error: null,
    
            });
        },
    
        componentWillMount() {
            if (window.location.hash) {
                this.onHashChange();
            }
        },
    
        componentDidMount() {
            window.addEventListener("hashchange", this.onHashChange);
        },
    
        componentWillUnmount() {
            window.removeEventListener("hashchange", this.onHashChange);
        },
    
        onSubmit(ev) {
            ev.preventDefault();
    
            var entity = this.refs.prompt.value.trim();
    
    lub's avatar
    lub committed
            if (!this.isAliasValid(entity) && !this.isUserIdValid(entity) && !this.isGroupValid(entity)) {
                this.setState({ error: "Invalid room alias, user ID or group" });
    
                return;
            }
            var loc = window.location;
            loc.hash = "#/" + entity;
            window.location.assign(loc.href);
            this.setState({
                showLink: true,
                entity: entity,
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                error: null,
    
            });
        },
    
        // XXX: cargo-culted from matrix-react-sdk
        isAliasValid(alias) {
            // XXX: FIXME SPEC-1
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
            return (alias.match(/^#([^\/:]+?):(.+)$/) && encodeURI(alias) === alias);
    
    David Baker's avatar
    David Baker committed
        isRoomIdValid(id) {
            // XXX: FIXME SPEC-1
            return (id.match(/^!([^\/:]+?):(.+)$/) && encodeURI(id) === id);
        },
    
    
        isUserIdValid(userId) {
            // XXX: FIXME SPEC-1
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
            return (userId.match(/^@([^\/:]+?):(.+)$/) && encodeURI(userId) === userId);
    
        },
    
        isMsglinkValid(msglink) {
            // XXX: FIXME SPEC-1
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
            console.log(msglink);
            console.log(encodeURI(msglink));
            return (msglink.match(/^[\!#]([^\/:]+?):(.+?)\/\$([^\/:]+?):(.+?)$/) && encodeURI(msglink) === msglink);
    
    lub's avatar
    lub committed
        isGroupValid(group) {
            console.log(group);
            console.log(encodeURI(group));
            return (group.match(/^\+([^\/:]+?):(.+)$/) && encodeURI(group) === group);
        },
    
    
        render() {
            var error;
            if (this.state.error) {
                error = <div className="mxt_HomePage_error">{ this.state.error }</div>
            }
    
            var prompt;
            if (this.state.showLink) {
                var link = "https://matrix.to/#/" + this.state.entity;
    
                var isRoom = this.isAliasValid(this.state.entity);
    
    David Baker's avatar
    David Baker committed
                var isRoomId = this.isRoomIdValid(this.state.entity);
    
                var isUser = this.isUserIdValid(this.state.entity);
                var isMsg = this.isMsglinkValid(this.state.entity);
    
    lub's avatar
    lub committed
                var isGroup = this.isGroupValid(this.state.entity);
    
    
                var links;
    
                // name: "Vector",
                // logo: "",
                // author: "Vector.im",
                // link: "https://vector.im",
                // room_url: "https://vector.im/beta/#/room/",
                // user_url: "https://vector.im/beta/#/user/",
                // maturity: "Late beta",
                // comments: "Fully-featured Matrix client for Web, iOS & Android",
    
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                var description;
                if (isRoom) {
                    description = <span>the <b>{ this.state.entity }</b> room</span>;
                }
                else if (isUser) {
                    description = <span>the user <b>{ this.state.entity }</b></span>;
                }
                else if (isMsg) {
                    description = <span><b>this message</b></span>;
                }
    
    lub's avatar
    lub committed
                else if (isGroup) {
                    description = <span>the <b>{ this.state.entity }</b> group</span>;
                }
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
    
    
                links = (
                    <div key="links" className="mxt_HomePage_links">
                        <div className="mxt_HomePage_links_intro">
                            <p>
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                <a href="https://matrix.org">Matrix</a> is an ecosystem for open and interoperable communication.
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                To connect to { description }, please select an app:
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                        <div className="mxt_HomePage_link mxt_HomePage_link_title">
                            <div className="mxt_HomePage_link_logo">
                            </div>
                            <div className="mxt_HomePage_link_name">
                                Name
                            </div>
                            <div className="mxt_HomePage_link_comments">
                                Description
                            </div>
                            <div className="mxt_HomePage_link_author">
                                Author
                            </div>
                            <div className="mxt_HomePage_link_maturity">
                                Maturity
                            </div>
                            <div className="mxt_HomePage_link_link">
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                Access { isMsg ? "message" : <b>{ this.state.entity }</b> }
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                            </div>
                        </div>
    
    
                        { linkable_clients.map((client) => {
                            var link;
                            if (isRoom && client.room_url) {
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                link = client.room_url(this.state.entity);
    
    David Baker's avatar
    David Baker committed
                            else if (isRoomId && client.room_id_url) {
                                link = client.room_id_url(this.state.entity);
                            }
    
                            else if (isUser && client.user_url) {
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                link = client.user_url(this.state.entity);
    
                            }
                            else if (isMsg && client.msg_url) {
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                link = client.msg_url(this.state.entity);
    
    lub's avatar
    lub committed
                            else if (isGroup && client.group_url) {
                                link = client.group_url(this.state.entity);
                            }
    
                            if (!link) return null;
    
                            let logo;
                            if (typeof client.logo === "string") {
                                logo = <img src={client.logo} />;
                            } else {
                                logo = <img {...client.logo} />;
                            }
    
    
                            return (
                                <div key={ client.name } className="mxt_HomePage_link">
                                    <div className="mxt_HomePage_link_logo">
    
                                        <a href={ link }>{ logo }</a>
    
                                    </div>
                                    <div className="mxt_HomePage_link_name">
                                        <a href={ link }>{ client.name }</a>
                                        <div className="mxt_HomePage_link_homepage">
                                            <a href={ client.homepage }>{ client.homepage }</a>
                                        </div>
                                    </div>
                                    <div className="mxt_HomePage_link_comments">
                                        { client.comments }
                                    </div>
                                    <div className="mxt_HomePage_link_author">
                                        { client.author }
                                    </div>
                                    <div className="mxt_HomePage_link_maturity">
                                        { client.maturity }
                                    </div>
                                    <div className="mxt_HomePage_link_link">
                                        <a href={ link }>{ link }</a>
                                    </div>
                                </div>
                            );
                        })}
                        { unlinkable_clients.map((client) => {
                            var instructions;
                            if (isRoom && client.room_instructions) {
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                instructions = client.room_instructions(this.state.entity);
    
                            }
                            else if (isUser && client.user_instructions) {
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                instructions = client.user_instructions(this.state.entity);
    
                            }
                            else if (isMsg && client.msg_instructions) {
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                                instructions = client.msg_instructions(this.state.entity);
    
    lub's avatar
    lub committed
                            else if (isGroup && client.group_instructions) {
                                instructions = client.group_instructions(this.state.entity);
                            }
    
                            if (!instructions) return null;
    
    J. Ryan Stinnett's avatar
    J. Ryan Stinnett committed
                            let logo;
                            if (typeof client.logo === "string") {
                                logo = <img src={client.logo} />;
                            } else {
                                logo = <img {...client.logo} />;
                            }
    
    
                            return (
                                <div key={ client.name } className="mxt_HomePage_link">
                                    <div className="mxt_HomePage_link_logo">
    
    J. Ryan Stinnett's avatar
    J. Ryan Stinnett committed
                                        <a href={ client.homepage }>{ logo }</a>
    
                                    </div>
                                    <div className="mxt_HomePage_link_name">
                                        <a href={ client.homepage }>{ client.name }</a>
                                        <div className="mxt_HomePage_link_homepage">
                                            <a href={ client.homepage }>{ client.homepage }</a>
                                        </div>
                                    </div>
                                    <div className="mxt_HomePage_link_comments">
                                        { client.comments }
                                    </div>
                                    <div className="mxt_HomePage_link_author">
                                        { client.author }
                                    </div>
                                    <div className="mxt_HomePage_link_maturity">
                                        { client.maturity }
                                    </div>
                                    <div className="mxt_HomePage_link_instructions">
                                        { instructions }
                                    </div>
                                </div>
                            );
                        })}
    
                        <p>
                            To add clients to this list, <a href="https://matrix.to/#/#matrix-dev:matrix.org">please contact us</a> or
                            simply send us a pull request <a href="https://github.com/matrix-org/matrix.to">on github</a>!
                        </p>
                    </div>
                );
    
                prompt = [
                    <div key="inputbox" className="mxt_HomePage_inputBox">
                        <a href={ link } className="mxt_HomePage_inputBox_link">{ link }</a>
                        { error }
                    </div>,
                    links
                ];
            }
            else {
                prompt = [
                    <div key="inputBox" className="mxt_HomePage_inputBox">
                        <form onSubmit={ this.onSubmit }>
    
    lub's avatar
    lub committed
                            <input autoFocus className="mxt_HomePage_inputBox_prompt" value={ this.state.entity } ref="prompt" size="36" type="text" placeholder="#room:example.com, @user:example.com or +group:example.com" />
    
                            <input className="mxt_HomePage_inputBox_button" type="submit" value="Get link!" />
                        </form>
                        { error }
                    </div>,
                    <div key="cta" className="mxt_HomePage_cta">
                        Create shareable links to Matrix rooms, users or messages<br/>
                        without being tied to a specific app.
                    </div>
                ];
            }
    
            return (
                <div className="mxt_HomePage">
                    <a href="#">
    
    Matthew Hodgson's avatar
    Matthew Hodgson committed
                        <img className="mxt_HomePage_logo" src="img/matrix-logo.svg" width="352" height="150" alt="Matrix"/>
    
                    </a>
    
                    { prompt }
    
                    <div className="mxt_HomePage_info">
                        <h3>About</h3>
                        <p>
                            Matrix.to is a simple stateless URL redirecting service
                            which lets users share links to entities in the <a href="https://matrix.org">Matrix.org
                            </a> ecosystem without being tied to any specific app.  This lets users choose their own favourite
                            Matrix client to participate in conversations rather than being forced to use the same app as
                            whoever sent the link.
                        </p>
                        <p>
                            The service 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.
                        </p>
                        <p>
                            Links are designed to be human-friendly, both for reading and constructing, and are
                            essentially a compatibility step in the journey towards
    
                            a <a href="https://github.com/matrix-org/matrix-doc/issues/455">ubiquitous mx://</a> URL scheme.
    
                        <p>
                            As with all of Matrix, Matrix.to is released as open source under the terms of
                            the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License v2.0</a> - get the source
                            from <a href="https://github.com/matrix-org/matrix.to">Github</a>.
                        </p>