Giter Club home page Giter Club logo

p2p-editor's Introduction

P2P Editor

codely.tv CodelyTV Courses

P2P code editor for live coding sessions that works in the browser.

This parallel P2P universe is still very dark. Create a Star if you want to make it brighter ๐ŸŒŸ

๐Ÿš€ Explore the universe ยป

Online demo ยท Roadmap ยท Contribute

๐Ÿ“œ Table of Contents

๐Ÿ’ก What does P2P Editor do?

P2P Editor is a code editor that works in the browser which lets you share live coding sessions. See it by yourself sharing a new session:

  1. Open a P2P Editor session in your browser
  2. Share your session URL with someone else (or even with yourself in another browser window ๐Ÿ˜ฌ)
  3. Start typing and enjoy the real time experience!

The functionalities are limited for now, but we have a roadmap and some good first issues to make P2P Editor awesome. Take a look to the Contributing section if you want to get involved ๐Ÿ™Œ.

๐Ÿค” Why P2P?

We have removed the need of having a centralized server where all the changes get saved. The communication is done from one peer (a connected user) to the other one. By doing this we have some benefits, but we also have to take into account the added complexity:

Benefits of P2P

  • Direct communication: reduce latency and bandwidth.
  • No servers: no cloud, no scaling, no deploy, no devops...
  • No SaaS:
    • Availability.
    • No usage restriction.
    • No unknown (malicious or not) usage of your data.

Added complexities of being fully distributed

  • Data consistency.
  • Network partition / topology.
  • Peer discovery and connection establishment.
  • Authentication / Authorization.
  • Security and privacy.

We have a particular interest in P2P application development. You can read more in the About section.

๐Ÿ—๏ธ Architecture

Architecture Diagram

P2P Editor building blocks:

  • Code editor: Ace
  • Database: append only log (hypercore)
  • Communication: WebRTC RTCDataChannel (webrtc-swarm)
  • Peer discovery: WebRTC signaling server (signalhub)
  • Storage: RAM

Workflow:

  1. Peers are discovered via signaling server.
  2. For each change made in the editor, a delta representing that change is appended to hypercore database.
  3. Hypercore database is constantly replicating between all peers via WebRTC RTCDataChannel.
  4. When a peer receives a delta it is applied to its editor instance.

๐Ÿš€ Environment setup

๐Ÿณ Needed tools

  1. Install Docker
  2. Clone this project: git clone https://github.com/CodelyTV/p2p-editor
  3. Move to the project folder: cd p2p-editor

๐Ÿ› ๏ธ Environment configuration

  1. Copy the default environment variables: cp .env.dist .env
  2. Modify the environment variables if needed: vim .env

๐ŸŒ Application execution

  1. Start the application with Docker Compose: docker-compose up
  2. Go to http://localhost:3617

โœ… Tests execution

  1. Execute Unit tests: docker-compose run p2p-editor test

๐Ÿ’ป Live demo

  1. To start a new live code session open http://p2p-editor.codely.tv.
  2. Share the URL with the users you want to join the session.
  3. Start editing the file.

That's all! All changes are instantly reflected in the connected peers editor.

Happy P2P coding!

โ„น๏ธ About

We started this project in the context of a learning process about P2P communications in a Web environment. The purpose of P2P editor is to apply a learn by doing approach where we can share our learnings with the community while building something useful.

We're publishing all the learning resources that we found useful in the Awesome P2P repository. Feel free to check it out and add your favourite links too!

The initial implementation of P2P Editor is based on Mathias Buus work. In case you read this, thank you very much for sharing so many free (libre) resources and knowledge ๐Ÿ˜Š

P2P Editor is a non profits free software supported by user contributions and CodelyTV.

๐Ÿค Contributing

How you can contribute?

You can get an idea of the roadmap of P2P Editor looking at the backlog and the wiki.

โš–๏ธ License

The MIT License (MIT). Please see License for more information.

p2p-editor's People

Contributors

davidlacarta avatar dependabot-preview[bot] avatar dependabot[bot] avatar javiercane avatar santakadev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

p2p-editor's Issues

Open existing session button

Other users should be able to click on an "Open external session" button in order to introduce a session ID and connect to it

Use UUIDs as session IDs

We have a restriction because we're using the same public key we use while communicating with all our peers.

We should refactor to have an execution flow like the following one:

  1. User A creates a new session: whatever.com/b3e2757a-d31f-41f7-ba3b-d0d18fd2fd46
  2. User B tries to connect to the user A session
  3. User A sends out his/her append only log public key to user B in order to replicate the DB

Improve UX for setting display name

From #40

When a second user opens the same session but before he introduces its nickname, it appears in the Users list as Anonymous. This could be confusing for the users already in the session because they could think that someone has joined and can actually see the contents of it (something not true yet).

However, I wouldn't vote for changing this behaviour grimacing. Instead, I would go for leaving the user land right in the editor of an existing session and letting him edit his preferences afterwards. That is, not asking his nickname before joining the session. The main reason would be to reduce the friction with the user to the bare minimum while joining a session. This is something similar to what http://zoom.us does while joining an existing conference session

If we go for this approach, it'll be definitely useful to list new session joiners as Anonymous until they set their nickname slightly_smiling_face

Don't allow to modify caret position while on read only mode

How to reproduce

  1. User A opens a new session
  2. User B joins the session and starts seeing how A type and following his/her careet
  3. B makes a click moving out the caret to another position
  4. A continue typing and moving out the caret
  5. B continues to see the new text modifications but s/he has missed the caret position of A

What would be expected

  • Ideally, the user B would recover the caret position once user A makes a modification after B has modified the caret position (4)
  • However, as a quick solution, we could make user B (and any other read only users) unable to set a new caret position

Responsive layout

Adapt UI size to mobile and tablet clients. Right now it's too small, and it allows to zoom-in and out.

Save session as GitHub Gist

Add a button in the UI in order to let the user save a snapshot of the current code as a GitHub Gist.

This way, we could do a future feature in order to start a session from a previously saved Gist.

Dockerfile for development

Current Dockerfile implementation is designed for production environments. Replace it with one for development.

Improve ReadMe

README.md sections (##)

  • ๐Ÿ“œ Table of Contents
  • ๐Ÿ’ก What does P2P Editor do?
  • ๐Ÿค” Why P2P?
  • ๐Ÿ—๏ธ Architecture
    • Communications (Swarm & WebRTC)
    • Append only DB (Hypercore & Merkel Tree)
    • Storage (RAM)
    • Signalhub (Distribute connections)
    • Ace (Editor)
  • ๐Ÿš€ Environment setup
    • ๐Ÿณ Docker environment
    • โœ… Run the tests
  • โ„น๏ธ About
  • ๐Ÿค Contributing
  • โš–๏ธ License

Inspiration

Programming language selector

  • Restrict the loaded assets to the main programming languages:
    • JavaScript
    • PHP
    • Java
    • Scala
    • Bash
    • Markdown
    • Kotlin
    • C
    • C++
    • C#
    • Go
    • SQL
    • CSS
    • HTML
    • ยฟ?
  • Add a selector in the UI in order to let the user specify which language s/he wants to write in

Change development server port

Didn't we changed the default port to something more random to avoid collisions with common local development environments?

Suggested port: 3617 (the closest numbers to the edit word I can think of right now xD)

This would imply also:

  • Modify the Docker Compose P2P Editor port mapping
  • Modify the Docker Compose Signalhub port mapping
  • Modify the default SIGNALHUB_URL environment variable value

Check browser WebRTC support

When a user opens P2P Editor in a browser that does not have WebRTC support, we need to tell him/her to upgrade his/her browser.

Message

P2P Editor can't run in your browser ๐Ÿ˜ž
Please, upgrade your browser or try it in another one.

Implementation suggestion

webrtc-swarm has a property for checking if browser supports WebRTC https://github.com/mafintosh/webrtc-swarm#swarmwebrtc_support

Browser support:

Standardize workflow

Context

The application is gaining traction in terms of stabilizing the codebase and we're close to the 1.0 milestone. Congrats! ๐Ÿ˜ฌ๐Ÿ™Œ

Because of that, I think we should do something in order to avoid losing the trace between issues and their corresponding changeset (Example: issue - changes) ๐Ÿ‘ผ

Why not to apply a classic PRs workflow yet

I understand that we're still in a very early stage of the application and we need to bootstrap the skeleton modifying a lot of times the very same lines of code.

If we apply a classic Pull Requests workflow (waiting for PR review and so on), we could make the experience a bit frustrating:

  • Conflicts: Having to wait until a PR is merged in order to have the modifications available so we avoid conflicts because of modifying the same code
  • Incremental changes: We wouldn't have the previous PR changes in order to develop further features based on that one.

Even if we could workaround that, for instance, concatenating PRs opening them based on the previous one; it could end up also being frustrating because of requesting changes on the first PR of the chain would make to apply it rebasing or merging all the concatenated PRs branches.

Proposal

For this reason, I would suggest to open a PR per issue even if we don't block the PR merge. That is, we wouldn't have to wait for a PR approval in order to merge it.

This way we'll only modify master through PRs merge commits (not pushing commits directly to it). That leads to exposing the different changes we're making (so anyone can actually see why we're making those changes), and be able to trace when and how an issue has been solved.

Furthermore, we'll allow to let anyone review the change set made due to a specific issue and provide feedback even if it has already been merged.

What do you think?

Missing static files version

When a new version of P2P Editor is deployed, changes are not visible until the browser's cache is cleared.

This is happening beacuse the name of the static files (main.js, main.css, etc.) is not modified in each new version.

Reactive P2P architecture with hypercore

Current architecture:

All write operations are performed by the peer initiating the session:

  • Single write database owned by session intiator.
  • Previous database is replicated to the rest of peers for reading.

We have some features that need all peers to be able to perform write operation like:

  • set its display name
  • set the position of its cursor
  • enable/disable peer audio
  • take edit control

Proposed architecture/solution:

Allow write operation to all peers:

  • Each peer has its own writable hypercore DB.
  • All write operations of a peer are stored in its own DB
  • When a connection to a peer is established via WebRTC, we perform DB replications:
    • we replicate our database to the connecting peer
    • connecting peer replicates its database to us

In summary, each peer has a write hypercore DB and a read hypercore DB for each connected peer.

In this architecture, when a peer performs an action that wants to publish (for example: CHANGE_DISPLAY_NAME action), he/she simply store the action in its own DB. This action will be recieved by all peers by replication, and they will react to this action.

After a lot of try, error and documentation, I have a working prototype of this architecture that uses WebRTC datachannel, that we can translate to P2P Editor.

This architecture can be plugged easily with Redux and any frontend framework like React and Vue.

Other options that I have try without success:

  • Use signalhub for nickname, cursor, etc. communication: discarted because is a non P2P solution
  • Use SimplePeer to send raw data (peer.send()) in the same DataChannel: discarted conflicts with hypercore replication
  • Create new DataChannel in SimplePeer to send raw data -> multiplexing already not available.

Follow other user activity

Allow to select a user from the connected users list and follow him/her

That is:

  • Enable Read only mode
  • Follow the caret movements
  • Show selected text as highlighted

Run the application locally

๐Ÿค” What

This will be the base feature in order to let us add further features in the next Milestones.

๐Ÿ‘ค User flow / UX

  • A user clones this repository
  • Run a Docker Compose in order to locally execute the web app (Example: localhost:8338)
  • The application generates a new document ID and redirects to it (Example: localhost:8338/0d69a7c0-e04d-4ffd-9490-f4901a0bdeba)
  • The user can share the unique ID and other users can access to the very same session through their local copy of the application

๐Ÿš€ Use already available JS libraries in order to communicate using WebRTC or WebSockets. We could keep the high level abstraction by the moment in order to simplify the project bootstrap

๐Ÿ’ก Centralized web apps used as inspiration

Setup ESLint

Connected users list

Add more "P2P eXperience" features:

  • Ask for a nickname while opening an existing session
  • Show the list of connected users to the current session

Blocks: #8

Setup dotenv

In order to modify configuration between different environments / installations, setup dotenv.

Replace hardcoded values with:

  • SIGNALHUB_URL

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.