Giter Club home page Giter Club logo

syncthing-android's Introduction

syncthing-android

License: MPLv2

A wrapper of Syncthing for Android.

screenshot 1 screenshot 2 screenshot 3

Get it on Google Play Get it on F-Droid

Status: "Maintenance mode" - Co-maintainers welcome

tl;dr: The app is still kept up to date, and contributions are still welcome - however even reviews for those can take a long time. Co-maintainers are very welcome - get in touch if you are interested.

No-one is dedicating significant time into development or reviews. It's still kept up to date with Syncthing, Android and dependencies under the wider Syncthing project umbrella on a best effort basis. Contributions are reviewed, however available time for that is scarce so it will take a while. And obviously it depends both on the size/clarity of the change and (admittedly subjective) relevance of it - chance of successful and speedier reviews is higher if your change is targeted and small.

No feature request taken (feature contributions case-by-case)

Handling feature requests use up the little time that is present to keep the app up-to-date, and there is no feature development happening. So unless you are opening a feature request to discuss your own contribution before jumping into coding, the request will be closed directly with some template answer pointing at this section.

Translations

The project is translated on Hosted Weblate.

Dev

Language codes are usually mapped correctly by Weblate itself. The supported set is different between Google Play and Android apps. The latter can be deduced by what the Android core framework itself supports. New languages need to be added in the repository first, then appear automatically in Weblate.

Building

These dependencies and instructions are necessary for building from the command line. If you build using Docker or Android Studio, you don't need to set up and follow them separately.

Dependencies

  1. Android SDK and NDK
    1. Download SDK command line tools from https://developer.android.com/studio#command-line-tools-only.

    2. Unpack the downloaded archive to an empty folder. This path is going to become your ANDROID_HOME folder.

    3. Inside the unpacked cmdline-tools folder, create yet another folder called latest, then move everything else inside it, so that the final folder hierarchy looks as follows.

      cmdline-tools/latest/bin
      cmdline-tools/latest/lib
      cmdline-tools/latest/source.properties
      cmdline-tools/latest/NOTICE.txt
      
    4. Navigate inside cmdline-tools/latest/bin, then execute

      ./sdkmanager "platform-tools" "build-tools;<version>" "platforms;android-<version>" "extras;android;m2repository" "ndk;<version>"
      

      The required tools and NDK will be downloaded automatically.

      NOTE: You should check Dockerfile for the specific version numbers to insert in the command above.

  2. Go (see https://docs.syncthing.net/dev/building#prerequisites for the required version)
  3. Java version 11 (if not present in $PATH, you might need to set $JAVA_HOME accordingly)
  4. Python version 3

Build instructions

  1. Clone the project with
    git clone https://github.com/syncthing/syncthing-android.git --recursive
    
    Alternatively, if already present on the disk, run
    git submodule init && git submodule update
    
    in the project folder.
  2. Make sure that the ANDROID_HOME environment variable is set to the path containing the Android SDK (see Dependecies).
  3. Navigate inside syncthing-android, then build the APK file with
    ./gradlew buildNative
    ./gradlew assembleDebug
    
  4. Once completed, app-debug.apk will be present inside app/build/outputs/apk/debug.

NOTE: On Windows, you must use the Command Prompt (and not PowerShell) to compile. When doing so, in the commands replace all forward slashes / with backslashes \.

License

The project is licensed under the MPLv2.

syncthing-android's People

Contributors

acolomb avatar adamszewe avatar audriusbutkevicius avatar bnyro avatar bt90 avatar calmh avatar capi avatar catfriend1 avatar dependabot-preview[bot] avatar dependabot[bot] avatar ermakov0 avatar flashsystems avatar flipreverse avatar fps avatar imsodin avatar jmintb avatar kdot avatar licaon-kter avatar lkwg82 avatar matthaiks avatar mscheidemann avatar mstrecke avatar nutomic avatar paulannekov avatar stoyandimitrov avatar unrud avatar weblate avatar wweich avatar ziem avatar zillode 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  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  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  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

syncthing-android's Issues

Shared folders are read-only on sd card (<29) and inaccessible on all ext. storage (>=29, ~November 2020)

SyncThing works great for repositories created on the internal SDCard. However if I try to create a rep on my external SDCard it doesn't complain. The other node attempts to sync & just shows sync progress set at 0%.
I'm running Android 4.4.2 on a GS4 & I know external SD card access for apps got restricted more since 4.4 but I think SyncThing is one of those apps where it makes complete sense to have ext SD access.
In the short term perhaps SyncThing for Android could complain if ext SD card access is not an option?

f/c on startup if repository path prefix doesn't exist

After I accidentally set my repo path to /external_sdcard/Sync (should have been /external_sd on my device) I get a force-close on every startup.

I sent a crash report with something like "crash after complete setup" as subject line but afterwards figured out it was because of the wrong path.

Thanks for your great work. This is the first bin-proprietary solution that works for me! I have another issue for you...

Waiting for GUI (indefinitely)

[Galaxy S+ running Android 2.3.5, Syncthing from June 15]

Syncthing service is running, I can browse to it with the native browser and Firefox/Aurora, and add nodes and repos. However, the Syncthing app gets stuck on "Waiting for GUI". There's nothing useful in the logs, unfortunately.

Sync never completes

I'm syncing a repository of music files between two linux hosts (a desktop and a laptop) and my cellphone. (Probably not relevant, but it's a directory of hardlinks to a git-annex repo, created with the script mentioned in https://github.com/calmh/syncthing/issues/262#issuecomment-44216939.)

The repository is set to "Master Repository: Yes" on desktop and to sync between laptop and phone.

On both phone and laptop, the repository is shared only with desktop.

Synchronisation on the laptop reaches 100% ("Out of Sync 0 files, 0 B").

Synchronisation on the phone never reaches 100%, even though all files are there.

"Out of Sync 129 files, 814MB". On the desktop the out-of-sync count is even higher: "Out of Sync 692 files, 3.09 GiB". (The repository has a total of "652 files, 3.45 GiB")

While syncthing is running on android, I see files named ".syncthing-01-Intro.mp3" in most subdirectories, which have identical content to their non-prefixed counterparts, e.g. "01-Intro.mp3" (md5sum, checked with ES-File-Explorer). Those files also appear in the media scan, which means I have duplicate titles in all albums while synchthing is running.

I also see a couple of error messages such as:

22:17:13 Restoring folder modtime: "/external_sd/Sync/Music/The Band/The Album": chtimes /external_sd/Sync/Music/The Band/The Album: operation not permitted

I'm running CM11 and have adb installed on the desktop, so if it helps I could send an error report via the powerbutton menu, or an adb logcat/bugreport whatever.

It seems a "workaround" for me is just to "exit" syncthing-android as soon as all required files are present. (I don't care about versioning since those are just media files.)

crashed after update...

The first start after a update from google store results in a crash. Second startup is ok.

Maybe the current running instance must be closed before doing a update?

Provide releases for different architectures

Right now, I only provide ARM releases. Android runs on armeabi, armeabi-v7a, MIPS, x86.

Edit: I currently just take the ARMv7 releases from syncthing. I'm not sure if this is the same as armeabi/armeabi-v7a, but I just got this crash report:

stdout: runtime: this CPU has no VFPv3 floating point hardware, so it cannot run
stdout: this GOARM=7 binary. Recompile using GOARM=6.

Edit: Arch on that one is build.cpu_abi: armeabi-v7a build.cpu_abi2: armeabi.

@calmh Do you maybe have some knowledge about these architectures and how to compile for them? (an "android" target for build.sh that gives these binaries (not zipped) would be absolutely perfect)

Config gets lost after phone reboot

Each time when I reboot my phone, my config is gone (identity, settings).

In another thread the position of the config file was given as /data/data/com.nutomic.syncthingandroid; however this path does not exist on my phone.

I'm using a Motorola Razr-I with Android 4.1.2
It has a build-in 5 GB SD card, and an external one (currently 32 GB).

(I'm using the ES Datei Explorer to view the directory structure).

The internal card can be accessed via /sdcard or /storage/sdcard0 .
The external one via /storage/sdcard1 .

There is a folder named /data, but it is empty.

The folder which contains persistent data (e.g. folder named ch.threema.app or com.android.browser) is located at: /sdcard/Android/data.

However, there is no subdir com.nutomic.syncthingandroid.

Which would explain why nothing is saved and I start ST from scratch each time I reboot the phone.

I hope there is a Android function that returns the path to data, because it seems to be different from other phones.

set ~ to /sdcard/ ???

In my case ~ would be set to /data/data/com.nutomic.syncthingandroid

syncthing v0.8.11

Crash at startup

I/SyncthingService( 6007): App started for the first time. Copying default config, keys will be generated automatically
I/SyncthingService( 6007): Checking for needed config updates
I/SyncthingService( 6007): Web GUI will be available at http://127.0.0.1:8080
W/dalvikvm( 6007): Exception Ljava/lang/RuntimeException; thrown while initializing Landroid/os/AsyncTask;
W/dalvikvm( 6007): threadid=8: thread exiting with uncaught exception (group=0x4001d570)
E/AndroidRuntime( 6007): FATAL EXCEPTION: Thread-9
E/AndroidRuntime( 6007): java.lang.ExceptionInInitializerError
E/AndroidRuntime( 6007):    at com.nutomic.syncthingandroid.syncthing.SyncthingService$2.run(SyncthingService.java:282)
E/AndroidRuntime( 6007):    at java.lang.Thread.run(Thread.java:1019)
E/AndroidRuntime( 6007): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
E/AndroidRuntime( 6007):    at android.os.Handler.<init>(Handler.java:121)
E/AndroidRuntime( 6007):    at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
E/AndroidRuntime( 6007):    at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
E/AndroidRuntime( 6007):    at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
E/AndroidRuntime( 6007):    ... 2 more

Android 2.3.4

Thanks for your hard work on this project!

Create repository - How?

Great to see the early stages of an Android port of Syncthing!

I am presently struggling with setting up the local repo on my device. The default format displayed in the app, ~/Folder isn't creating "Folder" on my device or SD card after I click Save.

I'm no expert on Android file formats - what am I missing?
Thanks.

Several minor issues/requests with newest update

First of all, thanks for this! Native GUI is much faster than the WebUI. I'll make several comments here and you can split them out into different issues, or track them here, whatever works best for you:

(Android 4.4 on stock non-rooted Verizon Motorola MAXX XT1080)

  1. Please add a pop-up notification when a restart is required instead of just adding an icon in the statusbar...it's not very noticeable.
  2. When I did restart it after deleting a repository, it froze at "Waiting for API..." and had to manually killed (force stop)
  3. After killing it, now it won't stay running longer than 10 seconds before it crashes. Had to reboot the phone to get it running again.
  4. On the Nodes view, the text on the bottom line is slightly cut off.
  5. The top 'back' button doesn't work on all screens. The phone's built it soft key back arrow does work.
  6. Is there a way to edit the repository name? It seems always to be grayed out.
  7. Can you please add the actual number of items to the repo view instead of just the size?
  8. When creating a repository, it's kind of unclear to put the 'Create' button up inside the menu to finish...I think a lot of people will just hit the back arrow instead (maybe that works too? I didn't try that...have to reboot again after the restart freeze.)

If you tell me where to find and the best way to send you logs (logcat??), I can certainly do so.

Thanks!
Scott

Edit: Sorry forgot one request...can you make the statusbar icon able to be toggled off (like btsync)?

Edit2: FYI, Syncthing could be restarted just fine from the WebGUI without freezing the app.

"Invalid Request"

Does not open anything or do anything, just shows the error "Invalid request".

Does the same with the version number in settings.

Out of sync master repo on the Windows side while the actual files are identical.

Master repo on the Windows side, synced to St-android. Android-side repo settings have the "Ignore permissions" flag enabled. St on Windows shows a number of files are out of sync [and status of the repo is "Idle (78%)"], while St-android shows all files are in sync and is at 100%.

Android-side repo has the "Ignore permissions" flag enabled. I pulled the files from the Android device and compared them to the files on the Windows machine with winmerge and they were all identical.

Make it possible to run any ST binary

I suggest to implement the possibility to (import to the app and) run any ST binary. In my eyes this makes sense when there is a newer binary as currently implemented in the Android app.

0.3.8 dosen`t start on Android 2.2

Ive installed 038 version from google play, but it dosent starts under android 2.2.2. I got 'com.nutomic app stops... Try later'

Luiz Augusto

Properly detect syncthing http server running

Right now, I just reload the GUI every second until it returns http status 200. I think this should be done better. Some ideas:

  • somehow wait until syncthing port is bound
  • have a .startup file that is deleted (from syncthing binary) once the GUI is up
  • any other way?

@calmh: What do you think?

Possibly introduce background service with very infrequent scanning.

The background service could rescan repos at a very low rate (once every half-hour) and since it has no ongoing notification it can be killed when needed (or it can kill itself after it performs a scan and syncs with other nodes), woken up again by AlarmManager when it needs to do another scan. Right now a 9000 file repo takes ~10 seconds to be rescanned (fast UHS-I SDCard, no changes to the files themselves) and this can decimate battery (edit:) since it happens every minute by default. When the user opens the St-android app you can switch to the fast rescan rate.

Keep syncthing permanently in background?

Right now, it only runs while the notification is shown (from app start until you press exit).

I could make it so that it starts on device boot and runs all the time. This might cause extra battery drain and network usage. I'm asking this especially to people with many/big repos and/or many nodes: would it be a problem if syncthing ran all the time? (Settings -> battery shows how much battery s-a uses).

I'd add an option to auto-pause syncing on mobile data before this).

Difficulty exiting app

When I want to shut down the app, I use the 3 vertical dots at the top right corner of the screen; and select "Exit". This works best - as the other option - "Edit > Shutdown" hangs, and I have to do a Forced stop in the Android settings to close out Syncthing.

A 2nd problem is that I don't always see the 3 vertical dots ... they seem to be intermittent. Can you help me understand what causes this app icon to appear and disappear? This could be by design, or it could be a bug - I am not sure.

I have v0.8.16 installed on Android 4.4 KitKat - although I experienced the same issue in the previous version as well.

Thank you.

Add node via QR code

Since the syncthing GUI displays the Node ID as a QR code, It would be nice if the app could photograph it instead of having to type it in.

Can not create new repo

Syncthing-android in the Play market from 04.06.2014 on Nexus 4 @ Android 4.4.2

Possibly duplicates #9.

I can not add repository in app, because "Repository ID" never validate right and "Save" button is always grayed.
screenshot_2014-06-07-11-39-48

Long running service, repos "Stopped"

I've found that when I leave the app running long term in the background, sync stops even though the node is still connected to my other nodes, and the other nodes register as up to date. On the UI, the repos turn red, and the detailed view lists "Synchronization: Stopped". See screenshots

dn6nrap
mzqirrl

REQUEST: Color consistency between Desktop and Android versions

Colors used in box headers seem to be inconsistent between the 2 versions:

                      DESKTOP VERSION       ANDROID VERSION

Local Repo Green Blue
Local Node Gray Gray
Remote Node Blue Green

There might be a good reason for this, but it's not obvious. I would prefer the local repo to be the same color on all devices (eg. Green), and the Remote node to also be the same color on all devices (lets say Purple, when disconnected, and Blue when connected).

Thanks - and if I am misunderstanding some intentional logic in the current color scheme, please explain :)

Turning on "Use HTTPS for GUI" in settings breaks the app GUI

All because I got curious (an in an effort to fully test the app), I decided to turn on https. This happened to break the app. I don't think there is any real big error here, the GUI just does not load anymore and syncthing crashes after a long enough time trying to load the GUI.

Either TLS needs to be supported in the interface or that setting needs to be removed on the android app. I honestly am not sure if using TLS on the android app interface is even something that you should be able to do.

First run should give more information

The first time syncthing-android is run, the "waiting for gui" dialog appears for a long time.

What about if s-a checks if no cert is present, and warns that because there is no cert, the first run may take a little while?

Crashes on Nexus 10

Right after "Waiting for API" message disappears. The crash info says it happens on line 185 of SyncthingService.java, https://github.com/Nutomic/syncthing-android/blob/master/src/main/java/com/nutomic/syncthingandroid/syncthing/SyncthingService.java#L185

Stack trace says that Syncthing binary returned error code 3. I guess it's not the wrapper's problem so I've tried to reinstall the app to no avail. Just in case some settings were broken or so. Worth noting that on Nexus 4 it works fine and it worked fine on N10, too, before the latest update with the native GUI. Too bad the logs of the binary aren't stored somewhere.

Setting to run when plugged in?

SyncThing seems to burn through quite a bit of battery on my phone; it might be useful to have a "sync when plugged in" setting, so the service launches when the phone is plugged in, then shuts down when unplugged.

An option to be able to sync files on rooted phones

Hi,
I hope it is already possible, but I guess it's not.
It would be really useful to be able to sync files in protected directories (like /data ) for rooted phones.
To make the app ask for sudo authorization when the option is activated.

Playstore update: no syncthing v0.8.13

Installed the update via playstore. The syncthing library is not updated to ..13 as referred in changelog.
Doublechecked with i9300 & n8010 (both running omnirom with android v 4.4.2)

App crash while adding Nodes or Repos

App crashes when pressing
"Add Node" or "Add Repo" or trying to open a already added Repo.

adding Nodes and Repos via the menu "Web GUI" works.

Android: 4.4.2
Samsung Note 8 - GT-N5110
Syncthing Android Version: 0.4.0 - 29.06.2014
Synthing Version: v0.8.17

Data loss on non-phone node when switching wifi<->celluar with phone

I don't have logs for you yet...please let me know what/how to collect from the phone and computer.

Setup

1 linux server running Syncthing 0.8.17, 1 Verizon Razr MAXX stock Android 4.4, latest version 0.4 (also happened with previous version). Server is on wired ethernet through a consumer router with Comcast cable connection. 1 shared repository with about 2100 files and 1.45 GB, mostly wallpaper images.

I also have another node on a Linux laptop with the same repository but only connected to the server, not the phone. It works fine syncing with the server no matter what combination of VPN and wifi changes I subject it to. It doesn't appear to be relevant to the problem (problem happens even with the laptop disconnected)

Problem

The phone, mostly when switching back to wifi after being on celluar data for some time, will apparently communicate somehow with the server node, leaving the server node with the impression that it needs to delete a whole bunch of files. The repo on the phone stays correct, and the server will start re-syncing it's repo from the phone after a time. There doesn't seem to be any pattern as to which or how many files get deleted before it stops. It appears that the global repository for the server somehow becomes incorrect and causes the file deletions. It sometimes happens while just sitting there with no change in network status, and sometimes I can switch from 4G to Wifi and back again on the phone with no problems at all.

Troubleshooting

  1. Took the laptop node out of the picture. No effect
  2. Tried increasing the sync time on the phone from 60 to 120 seconds. No effect
  3. Tried changing ownership of the files on the server (there was a mix of two different UIDs). No effect
  4. Upgraded to 0.4 from the 0.3.8 version on the phone. No effect
  5. Ran just the server and laptop nodes without the phone node for over 24 hours, with numerous wifi/VPN changes on the laptop and files added/deleted for testing. Worked great.

Like I said at the top, I'd love to help debug this, but I really don't know what logs you need and how to acquire them (from the phone, at least). Also let me know any other info I can provide.

Thanks,
Scott

Camera upload support

It'd be nice if syncthing for Android prompted the user about setting up a Camera Uploads repo on first run. It'd need to be called something else though, because the sync will be in two directions.

config data erased after adding repo

Trying todays version (0.3.3)...

After creating a repository and save the information, the built-in webserver does not respond anymore.

Trying to restart the app results in "Waiting for Gui" - which does not appear - and finally "Syncthing does not respond".

After rebooting the phone Syncthing is generating new keys.

Perhaps the config file is not closed properly?

Version 3.0 - UI rendering issues

In portrait mode, UI boxes are truncated, and not showing complete information:

(1) The green path box at the top - 2nd line (status) is cut off from view.
(2) In both the localhost and remote node boxes, the information on the right side of the boxes is cut off.

When I flip the device into landscape, all information is correctly rendered.

Device: Motorola RAZR M - Android Kitkat

Thanks!

Support for older devices

I am trying to run syncthing on an Acer Liquid E with CyanogenMod 7.
It crashes after showing the "first start" window, even without me pressing the button.

Logcat shows this:

E/AndroidRuntime( 3857): FATAL EXCEPTION: Thread-13
E/AndroidRuntime( 3857): com.nutomic.syncthingandroid.syncthing.SyncthingService$NativeExecutionException: Syncthing binary returned error code 1
E/AndroidRuntime( 3857):
E/AndroidRuntime( 3857): runtime: this CPU has no VFPv3 floating point hardware, so it cannot run
E/AndroidRuntime( 3857): this GOARM=7 binary. Recompile using GOARM=6.
E/AndroidRuntime( 3857):
E/AndroidRuntime( 3857):
E/AndroidRuntime( 3857):        at com.nutomic.syncthingandroid.syncthing.SyncthingService.runNative(SyncthingService.java:163)
E/AndroidRuntime( 3857):        at com.nutomic.syncthingandroid.syncthing.SyncthingService.access$1000(SyncthingService.java:53)
E/AndroidRuntime( 3857):        at com.nutomic.syncthingandroid.syncthing.SyncthingService$3.run(SyncthingService.java:332)
E/AndroidRuntime( 3857):        at java.lang.Thread.run(Thread.java:1019)

Is it possible to have a build for older devices, or am I on my own in building syncthing?

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.