Code Monkey home page Code Monkey logo

ignition's People

Contributors

abdyer avatar michaelengland avatar mlc avatar mttkay 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

ignition's Issues

Gradle: duplicate files during packaging of APK

This is reproducible with versions 0.1 to 0.3-SNAPSHOT.

Using Android Studio Preview 130 and Gradle.

When I include ignition-core as a dependency as a dependency:
dependencies {
compile 'com.github.ignition:ignition-core:0.1@apklib'
}

Gradle: Execution failed for task ':App:packageDebug'.

Duplicate files copied in APK AndroidManifest.xml
File 1: /home/user/github/android/AppProject/App/build/libs/App-debug.ap_
File 2: /home/user/github/android/AppProject/App/build/libs/App-debug.ap_

Extracting ignition-core-0.2.apklib shows an AndroidManifest.xml:
image

Does ignition-core-0.1.apklib need the AndroidManifest.xml? I am assuming the Android Gradle plugin is trying to flatten the jars into an apk.

Thanks

Issue on RemoteImageView used together with HorizontalListView (http://www.dev-smart.com/archives/34)

I can't get any web image to load, not even progress spinner showed up (i only see the spinner for brief moment when doing quick scroll), no errordrawable showed up either. I think there is internal issues here. Can you enlighten me on how to fix this.

gallery_layout:

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:paddingBottom="4dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"
    android:paddingTop="4dp" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="5dp"
        android:paddingLeft="8dp"
        android:paddingTop="5dp"
        android:text="Foods around here:"
        android:textSize="16dp" />

    <com.devsmart.android.ui.HorizontalListView 
        android:id="@+id/gallery_list"
        android:layout_width="fill_parent"
        android:layout_height="400dp" />

 </LinearLayout>

gallery_listentry:

    <com.github.ignition.core.widgets.RemoteImageView
        android:id="@+id/img"
        android:layout_width="400dp"
        android:layout_height="280dp"
        android:background="@color/dark_brown"
        android:padding="2dp"
        ignition:progressDrawable="@drawable/ic_launcher"
        ignition:autoLoad="false"
        ignition:errorDrawable="@drawable/icon"
        ignition:defaultDrawable="@drawable/place_snacks"
        android:scaleType="fitXY"/>

package com.test;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.devsmart.android.ui.HorizontialListView;
import com.github.ignition.core;

public class HorizontalListViewDemo extends Activity {

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  

    setContentView(R.layout.gallery_layout);  

    HorizontialListView listview = (HorizontialListView) findViewById(R.id.gallery_list);  
    listview.setAdapter(mAdapter);  

}  

private static String[] url = new String[]{ "http://www.google.com.sg/logos/2012/vday12-res.png",  
    "http://www.google.com.sg/logos/2012/vday12-res.png",  
    "http://www.google.com.sg/logos/2012/vday12-res.png" };   

private BaseAdapter mAdapter = new BaseAdapter() {  

    @Override  
    public int getCount() {  
        return url.length;  
    }  

    @Override  
    public Object getItem(int position) {  
        return null;  
    }  

    @Override  
    public long getItemId(int position) {  
        return 0;  
    }  

    @Override  
    public View getView(int position, View convertView, ViewGroup parent) {  
        View retval = LayoutInflater.from(parent.getContext()).inflate(R.layout.gallery_listentry, null);  
        RemoteImageView img = (RemoteImageView) retval.findViewById(R.id.img);  
        img.setImageUrl(url[position]);
        img.loadImage();

        return retval;  
    }  

};  

}

RemoteImageView should not apply attributes

In addImageView the given attributes are applied which causes any paddings, etc be applied to both the ViewSwitcher(from RemoteImageView) as well as to the ImageView itself. The same is true for background brushes, which looks particularly bad if you use a 9 patch brush.

    private void addImageView(Context context, AttributeSet attributes) {
        // when the view has paddings, then it will be displaced
//        if (attributes != null) {
//            // pass along any view attribtues inflated from XML to the image view
//            imageView = new ImageView(context, attributes);
//        } else {
            imageView =

isApplicationBroughtToBackground doesn't work as advertised

Hi there. I ran across this method on Stackoverflow, and decided to use it. But it turns out it doesn't always work as advertised. Specifically, in the case where I have defined an extra Activity in my Application with a different package than the Application. Because you are comparing packages, isApplicationBroughtToBackground() will return true when I launch this child Activity. My solution checks to see if the new topActivity is defined in the current Application. If not, returns true:

public static boolean isApplicationBroughtToBackground(final Activity activity) {
  ActivityManager activityManager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
  List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
  if (!tasks.isEmpty()) {
    ComponentName topActivity = tasks.get(0).topActivity;
    try {
      PackageInfo pi = activity.getPackageManager().getPackageInfo(activity.getPackageName(), PackageManager.GET_ACTIVITIES);
      for (ActivityInfo activityInfo : pi.activities) {
        if(topActivity.getClassName().equals(activityInfo.name)) {
          return false;
        }
      }
    } catch( PackageManager.NameNotFoundException e) {
      return false; // Never happens.
    }
  }
  return true;
}

If you want this, I'd be happy to submit a pull request.

Load-spinner placed beside image (RemoteImageView)

Hi,

I have a problem with the load-spinner getting placed on the side of the image when using RemoteImageView from the latest version of the master bransch. This leads to that the View takes up twice the space it should.

I use the following code to initiate the image in my layout.

<com.github.ignition.core.widgets.RemoteImageView
            android:layout_width="64dip"
            android:layout_height="64dip"
            ignition:autoLoad="false"/>

I assign the url programmatically when the activity is created.

I use the latest version of the Android SDK and the problem seams to manifestate it self on all android versions (Tried it on 4.0, 2.2 and 2.3)

Regards
Peter

Error upon build test: "Failed to execute goal..."

I am running Windows 7 with Android SDK v. 4.0.3 (API 15).

Failed to execute goal com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.0.2:generation-sources (default-generate-sources) on project ignition-core: Execution default-generate-sources of goal com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.0.2:generate-sources failed: Invalid SDK: Platform/API level 4 not available.
This command should give you all you need:
C:/Program Files (x86)\Android\android-sdk\tools\android update sdk --no-ui --obsolete --force

Why do you I need to install obsolete version of the Android SDK just to get ignition to work?

Basic Authentication for Image URL

I don't know if you would want to consider this or not but basic authentication capabilities for the RemoteImageLoader could be handy in some cases.

Multiple instance of RemoteImageLoader are passed to RemoteImageView.setSharedImageLoader

Here is how to reproduce the issue.

  1. Install remote-image-gallery-sample on a device using android-7/ 2.1. I have just try this on the emulator. I could not reproduce it on newer versions but the problem is still there.
  2. Start rotating the emulator back and forth.
  3. You will get a OutOfMemoryError

The cause of the the problem is that we are initializing a static variable -- that depends of the context -- every time the activity is created.

The way I bypass this problem is by having my own static variable on my activity and just creating it once, but this is ugly, unintuitive and is not documented.

What I propose is to create a helper function on RemoteImageView that let you know if the sharedImageLoader has been initialized. And log a warning message if setSharedImageLoader is called twice.

RemoteImageView should behave like an ImageView

Since RemoteImageView is a ViewSwitcher, and not an ImageView, it doesn't accept ImageView attributes such as scaleType. We should fix that by redirecting any ImageView specific attributes to the underlying ImageView in the view switcher.

RemoteImageView uses only disk cache

I'm using the RemoteImageView multiple times inside of ListView. It's working properly, except that its a bit viscous / slow. It actually is acceptable, but I think it can be much more smooth. The log states constantly that the image is retrieved from the disk and sometimes from memory (1 of the 10 times). I think this is causing the scrolling to be slow as also mentioned in the documentation.

Currently I'm trying to figure out what is causing the RemoteImageView from not getting the image from memory. I tried to increase the buffer size but that is not working. I also tried to use the new Guava cache classes because the expiration method of the MapMaker is deprecated. Still no luck.

Do you have any idea to fix this?

Qype dependencies for distribution

@mttkay given this is an open source project, shouldn't the releases be pushed to maven central or sonatype oss instead of qype's nexus repo?

Right now I have an issue given qype's repo is down (not sure if decommissioned) and we can fetch the latest releases or snapshots.

NullPointerException in RemoteImageView

I'm using the RemoteImageView in a ListView. It works fine for one list but for another it gives the following error in Logcat.

12-28 14:25:44.843: E/AndroidRuntime(2617): FATAL EXCEPTION: main
12-28 14:25:44.843: E/AndroidRuntime(2617): java.lang.NullPointerException
12-28 14:25:44.843: E/AndroidRuntime(2617): at com.github.ignition.support.images.remote.RemoteImageLoaderHandler.handleImageLoaded(RemoteImageLoaderHandler.java:73)
12-28 14:25:44.843: E/AndroidRuntime(2617): at com.github.ignition.core.widgets.RemoteImageView$DefaultImageLoaderHandler.handleImageLoaded(RemoteImageView.java:228)
12-28 14:25:44.843: E/AndroidRuntime(2617): at com.github.ignition.support.images.remote.RemoteImageLoaderHandler.handleImageLoadedMessage(RemoteImageLoaderHandler.java:52)
12-28 14:25:44.843: E/AndroidRuntime(2617): at com.github.ignition.support.images.remote.RemoteImageLoaderHandler.handleMessage(RemoteImageLoaderHandler.java:45)
12-28 14:25:44.843: E/AndroidRuntime(2617): at android.os.Handler.dispatchMessage(Handler.java:99)
12-28 14:25:44.843: E/AndroidRuntime(2617): at android.os.Looper.loop(Looper.java:123)
12-28 14:25:44.843: E/AndroidRuntime(2617): at android.app.ActivityThread.main(ActivityThread.java:3687)
12-28 14:25:44.843: E/AndroidRuntime(2617): at java.lang.reflect.Method.invokeNative(Native Method)
12-28 14:25:44.843: E/AndroidRuntime(2617): at java.lang.reflect.Method.invoke(Method.java:507)
12-28 14:25:44.843: E/AndroidRuntime(2617): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
12-28 14:25:44.843: E/AndroidRuntime(2617): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
12-28 14:25:44.843: E/AndroidRuntime(2617): at dalvik.system.NativeStart.main(Native Method)

NOTE: the actual line number for the exception in RemoteImageLoaderHandler.java is 71. I added lines to see where the exact problem was.

It seems that a null Bitmap is passed to the RemoteImageLoaderHandler and because I get the RemoteImageView from a findViewById(), I don't have an errorDrawable so the NullPointerException is passed.

I believe the problem is initiated at line 51 in RemoteImageHandler.java

Bitmap bitmap = data.getParcelable(BITMAP_EXTRA);

Maybe I'm doing something wrong. Any ideas ?

Image is blank after download is finished

I found a bug in ignition-support library when using RemoteImageLoader to downloading images. Some images will not download correctly after finished downloading, especially on some mobile networks.

The root cause is in these lines in RemoteImageLoaderJob.java:
int fileSize = connection.getContentLength();
...
byte[] imageData = new byte[fileSize];

            int bytesRead = 0;
            int offset = 0;
            while (bytesRead != -1 && offset < fileSize) {
                bytesRead = istream.read(imageData, offset, fileSize - offset);
                offset += bytesRead;
            }

According to Android documentation of HttpURLConnection, "By default, this implementation of HttpURLConnection requests that servers use gzip compression. Since getContentLength() returns the number of bytes transmitted, you cannot use that method to predict how many bytes can be read from getInputStream().".

So when compression in use, getContentLength() will return bytes less than the total size of image data.

RemoteImageView has extra space to the right

I have a RemoteImageView that I'm using inside a LinearLayout as the thumbnail for each item in a list view.

The urls for the image files are set after the list adapter initializes, then loadImage is called to start loading the image. For some reason, the images are being rendered with an extra 80dp to the right.

Here's a screenshot of the problem: http://i.imgur.com/JWmSD.png

The relevant layout template:

     <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:background="#ffffffff"
        android:baselineAligned="false"
        android:orientation="horizontal" >

        <com.github.ignition.core.widgets.RemoteImageView
            android:id="@+id/thumbnail"
            android:layout_width="80dp"
            android:layout_height="60dp"
            android:layout_weight="0"
            ignition:autoLoad="false"
            android:background="#fff6f6f6"
            ignition:errorDrawable="@android:color/transparent"
            android:indeterminateDrawable="@android:color/transparent"
            android:scaleType="fitXY" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:orientation="vertical"
            android:paddingLeft="8dp"
            android:paddingRight="8dp" >
           ...
        </LinearLayout>
    </LinearLayout>

and excerpt from the list adapter

viewHolder.thumbnail.setImageUrl(lesson.video_thumbnail_hdpi_url);
viewHolder.thumbnail.loadImage();

Any ideas on what might be causing this?

How can i show a picture from cache?

Hello i try to show the picture from the iginition support sample in an ImageView,
but cant get this working.. i am not sure why..?

image = (ImageView)findViewById(R.id.imageView1);
HttpResponseCache cache = http.getResponseCache();
        if (cache != null) {
            List<File> cachedFiles = cache.getCachedFiles();
            for (File file : cachedFiles) {
                Bitmap myB = BitmapFactory.decodeFile(file.getAbsolutePath());
                image.setImageBitmap(myBitmap);
            }
        }

The problem is, that my BitmapFactory gives back: null
What is wrong in my code??

Missing class MapMaker

E/dalvikvm: Could not find class 'com.google.common.collect.MapMaker', referenced from method com.github.ignition.support.cache.AbstractCache.

Because of the missing Project I can't compile any proeject.

Warning: Cookie Rejected

I am getting 3 "Cookie Rejected" errors during the build test (Building ignition-location-tests 0.1-SNAPSHOT)...this doesn't seem to effect the final result because I am getting a clear SUCCESS summary, but I do think it's strange. Should I post the full error messages here?

No clear instructions on using it as a library for an Android project

I'm trying to use ignition-core as a library for my Android app. I tried following instructions, and got as far as gradle eclipse, and having the .project files imported into eclipse from /ignition/ignition-core, but it seems that the Android project does not find the classes, despite having it added as a project requirement in the build path settings.

I looked deeper at your project struction, and realised that ignition-core-lib is an android app project of which I believe I should be including, and in there, lies a build.gradle too. I am however unable to use that gradle build path. Perhaps it would be better if clearer instructions could be posted on this? Thanks!

PS: There are some dead links in the readme too. Cheers! PS: Nice work btw.

Guava Required

Classes within ignition-support (e.g., AbstractCache) are dependent upon Guava (AKA Google Collections library). This should be documented/communicated.

StrictMode complains about InputStream not closed when using Gzip encoding

If I enable gzip encoding as follow with StrictMode enabled:

ignitedHttp.setGzipEncodingEnabled(true);

I see errors in LogCat:

08-21 16:09:14.158: E/StrictMode(2083): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
08-21 16:09:14.158: E/StrictMode(2083): java.lang.Throwable: Explicit termination method 'end' not called
08-21 16:09:14.158: E/StrictMode(2083): at dalvik.system.CloseGuard.open(CloseGuard.java:184)
08-21 16:09:14.158: E/StrictMode(2083): at java.util.zip.Inflater.(Inflater.java:82)
08-21 16:09:14.158: E/StrictMode(2083): at java.util.zip.GZIPInputStream.(GZIPInputStream.java:96)
08-21 16:09:14.158: E/StrictMode(2083): at java.util.zip.GZIPInputStream.(GZIPInputStream.java:81)
08-21 16:09:14.158: E/StrictMode(2083): at com.github.ignition.support.http.gzip.GzipInflatingEntity.getContent(GzipInflatingEntity.java:21)
08-21 16:09:14.158: E/StrictMode(2083): at org.apache.http.conn.BasicManagedEntity.getContent(BasicManagedEntity.java:100)
08-21 16:09:14.158: E/StrictMode(2083): at org.apache.http.util.EntityUtils.toByteArray(EntityUtils.java:64)
08-21 16:09:14.158: E/StrictMode(2083): at org.apache.http.entity.BufferedHttpEntity.(BufferedHttpEntity.java:62)
08-21 16:09:14.158: E/StrictMode(2083): at com.github.ignition.support.http.IgnitedHttpResponseImpl.(IgnitedHttpResponseImpl.java:35)
08-21 16:09:14.158: E/StrictMode(2083): at com.github.ignition.support.http.IgnitedHttpRequestBase.handleResponse(IgnitedHttpRequestBase.java:81)
08-21 16:09:14.158: E/StrictMode(2083): at com.github.ignition.support.http.IgnitedHttpRequestBase.handleResponse(IgnitedHttpRequestBase.java:1)
08-21 16:09:14.158: E/StrictMode(2083): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
08-21 16:09:14.158: E/StrictMode(2083): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
08-21 16:09:14.158: E/StrictMode(2083): at com.github.ignition.support.http.IgnitedHttpRequestBase.send(IgnitedHttpRequestBase.java:118)

Somehow the input stream wrapped into a GZIPInputStream is never closed. I tried looking into the IgnitedHttp code and everything looks fine to me. So it's probably an issue with the Apache implementation and StrictMode.

Any thought?

RemoteImageView's initialize leads to poor performance of RemoteImageGalleryAdapter

Currently in the initialize of RemoteImageView if "sharedImageLoader" is null then a new instance of RemoteImageLoader is created. This will call "enableDiskCache" which in turn calls "sanatizeDiskCache", which is a costly method.

In the getView of the RemoteImageGalleryAdapter, if convertView is null then a new instance of RemoteImageView is created, which following the flow of the above paragraph will call "sanatizeDiskCache".

This means that"sanatizeDiskCache" will be called frequently when scrolling through a gallery, and will really takes a lot of cpu time and can causes the frame rate to really slow down.

A simple work around is to set a "sharedImageLoader", stopping new instances of "RemoteImageLoader" and preventing the "sanatizeDiskCache" calls. This is an easy step, but one that was not obvious to me when setting up my gallery, and so i would presume that it would not be obvious to others doing the same.

IgnitedHttpResponseImpl relies on BufferedHttpEntity which blows up memory limits for large entities

When trying to consume a large entity via IgnitedHttpResponseImpl it seems like the replacement of the original entity by a BufferedHttpEntity in its implementation seems to allocate memory for the the entire length of the entity you're trying to download.

So say you have a 100MB file for instance, it will try to allocate that much memory to fetch the InputStream of the HttpEntity (which by the name - buffered - you'd expect it to stream the contents via an internal buffer or sorts rather than cache the entire stream).

Do you guys have any suggestions to overcoming this issue given AbstractHttpClient seems to call entity.consumeContent() right after the initialization of the response by IgnitedHttpRequestBase.handleResponse()?

jUnit Tests (with Robolectric/Mockito) - possible?

Hi, I'm using your lib for some of my Android projects and would love to be able to mock IgnitedHttp calls on some of my unit tests.

I haven't found any tests in the project or external projects so was wondering if you guys had any luck stubbing the classes to avoid having it delegate to HttpClient during testing given Robolectric doesn't go that far in shadowing the stub implementations provided with the Android SDK.

RemoteImageView subview no longer scales correctly

After downloading a recent update to the Android SDK, enabling the Google APIs, I find that images I load using RemoteImageView are no longer scaling as specified in the layout XML. Instead, the ImageView subview is centered within the RemoteImageView. (My images are smaller than the space I would like them to fill.)

App design question: Reconnectable dialogs?

I'm in the process of adapting my existing code to work with IgnitedAsyncTask (you deprecated android-fu already?) and I'm running into a potential design issue in that most of my asyncTasks are involved in some form of ProgressDialog or AlertDialog, which is tied to the Context object and likely should not survive a reconfiguration.

Is there value in developing a ProgressDialog-like and/or AlertDialog-like object "in the style" of IgnitedAsyncTask that supports .connect() and .disconnect(), recreating the "real" dialog object as-needed (and hooking all the events into itself) ? Or is there a better way to look at this issue that I'm not seeing?

This is not a request for development or a pull request (yet), just a query as to whether this is a good direction to go in, as an issue on a project that seems to deal with these issues as one of its central purposes.

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.