Giter Club home page Giter Club logo

friendlyeats-android's Introduction

friendlyeats-android's People

Contributors

dpebot avatar kroikie avatar marinacoelho avatar paulentine avatar samtstern avatar shoarai avatar thatfiredev 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

friendlyeats-android's Issues

Propagating onEvent errors of EventListener not handled

In the Step - "Display data from Firestore", the provided code does not handle the case of propagating the Listen errors to the protected method onError() of FirestoreAdapter. If propagated, then only the user will be able to see a Snackbar in case of any Listen errors occurring due to improper Query, in the onEvent() callback of EventListener. This onError() method is overidden by subclasses of FirestoreAdapter to provide their own implementation for handling the FirebaseFirestoreException error passed to it.

Add sample data - error: onAddItemsClicked()

Device: Android Studio/Emulator

Project: friendlyeats-android
compileSdkVersion 29
buildToolsVersion '29.0.2'
applicationId 'com.google.firebase.example.fireeats'
minSdkVersion 16
targetSdkVersion 29

Problem:
Tutorial Step 4: Write Data to Firestore
Adding the suggested code to MainActivity onAddItemsClicked() does not recognize the Restaurant class.

Error:
error: cannot find symbol
Restaurant restaurant = RestaurantUtil.getRandom(this);

What steps will reproduce the problem:

  1. Clone the repository, follow the tutorial
  2. Add the code in step 4: Write Data to Firestore
  3. Build the project

What is the expected result?
The app builds and runs on the emulator. Sample data is loaded into the restaurants collection in firestore.

What happens instead of that?

Build error:
error: cannot find symbol
Restaurant restaurant = RestaurantUtil.getRandom(this);
Screen Shot 2020-02-11 at 9 32 59 AM

Unable to sign in

Android beginner trying to learn FIrestore here.

When trying to run this app with all the dependencies updated to the latest available version, I am unable to to sign in. I enter my email and click on next but the home screen is only shown for a second and it immediately switches back to the Sign in screen asking me to enter my email. The tutorial says I should be able to sign in and see the home screen without changing any code. Please forgive me if this issue is because I did something wrong. Thanks!

P.S. I have tried running the app as is, with all the included outdated dependencies and I still face the same issue.

Step 8: Inaccurate Description

The description of step 8 states:

...updates to a restaurant document can only change the ratings, not the name or any other immutable data.

However, the update rule only makes sure the user is authenticated and the restaurant name is unchanged - any other change to the restaurant object would be possible.

  match /databases/{database}/documents {
        // Restaurants:
        //   - Authenticated user can read
        //   - Authenticated user can create/update (for demo)
        //   - Validate updates
        //   - Deletes are not allowed
    match /restaurants/{restaurantId} {
      allow read, create: if request.auth != null;
      allow update: if request.auth != null
                    && request.resource.data.name == resource.data.name
      allow delete: if false;
    `

[email protected]

نْحّـنُ الـنّْآر الصّْغّرى نْحّنُ منّ تَـحدَى أَعآلي الْجِبّـآل وجَبّروُتْ القِمّمْ

Step4: ButterKnife, AuthUI, ViewModel, MaterialRatingBar dependencies correction

For those of who have set up issue like dependencies and deprecated code. Change it as follows.

// FirebaseUI (for authentication) implementation 'com.firebaseui:firebase-ui-auth:4.0.0'

// ButterKnife (for sample code brevity) implementation "com.jakewharton:butterknife:8.8.0" annotationProcessor "com.jakewharton:butterknife-compiler:8.8.0"
...
// Android architecture components implementation 'android.arch.lifecycle:extensions:1.1.0' implementation 'android.arch.lifecycle:runtime:1.1.0' annotationProcessor 'android.arch.lifecycle:compiler:1.1.0'

implementation 'me.zhanghai.android.materialratingbar:library:1.3.1'

and change the AuthUI.EMAIL...
new AuthUI.IdpConfig.EmailBuilder().build()

I am not sure it works for those of who have same problem. But it works for me.

Limit to 1 review per user?

Not really a bug, but maybe a logical bug.
Logic allows for unlimited review submissions.
Would be nice to limit to 1 review per user.
I enjoyed this codelab!

Crash upon startup (Step 5)

Step 1: Describe your environment

  • Android device: Nexus 10 (AVD)
  • Android OS version: 10 (API 29)
  • Firebase Emulator version: 13.3.1
  • Android Studio version: Android Studio Hedgehog | 2023.1.1 Patch 2
    Build #AI-231.9392.1.2311.11330709, built on January 18, 2024
    Runtime version: 17.0.7+0-b2043.56-10550314 amd64
    VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
    Windows 11.0
    GC: G1 Young Generation, G1 Old Generation
    Memory: 4096M
    Cores: 16
    Registry:
    external.system.auto.import.disabled=true
    debugger.watches.in.variables=false
    ide.text.editor.with.preview.show.floating.toolbar=false

Step 2: Describe the problem: Upon startup, the app displays a white screen and then promptly crashes.

Steps to reproduce:

  1. Start firebase emulators
  2. Run app in android studio emulator
  3. App crashes withing 2 seconds with no user input

Observed Results:

  • What happened? This could be a description, logcat output, etc.
  • Main logcat error appears to be: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.auth.api.credentials.CredentialsOptions$Builder"
  • Here is the full logcat:
  • 2024-02-26 21:22:25.099 3858-3858 xample.fireeat com...gle.firebase.example.fireeats I Late-enabling -Xcheck:jni
    2024-02-26 21:22:25.110 3858-3858 xample.fireeat com...gle.firebase.example.fireeats E Unknown bits set in runtime_flags: 0x8000
    2024-02-26 21:22:25.110 3858-3858 xample.fireeat com...gle.firebase.example.fireeats W Unexpected CPU variant for X86 using defaults: x86
    2024-02-26 21:22:25.547 3858-3858 MultiDex com...gle.firebase.example.fireeats I VM with version 2.1.0 has multidex support
    2024-02-26 21:22:25.547 3858-3858 MultiDex com...gle.firebase.example.fireeats I Installing application
    2024-02-26 21:22:25.547 3858-3858 MultiDex com...gle.firebase.example.fireeats I VM has multidex support, MultiDex support library is disabled.
    2024-02-26 21:22:25.617 3858-3858 FirebaseApp com...gle.firebase.example.fireeats I Device unlocked: initializing all Firebase APIs for app [DEFAULT]
    2024-02-26 21:22:25.628 3858-3858 FirebaseInitProvider com...gle.firebase.example.fireeats I FirebaseApp initialization successful
    2024-02-26 21:22:25.749 3858-3902 libEGL com...gle.firebase.example.fireeats D Emulator has host GPU support, qemu.gles is set to 1.
    2024-02-26 21:22:25.750 3858-3902 libc com...gle.firebase.example.fireeats W Unable to set property "qemu.gles" to "1": connection failed; errno=13 (Permission denied)
    2024-02-26 21:22:25.735 3858-3858 RenderThread com...gle.firebase.example.fireeats W type=1400 audit(0.0:403419): avc: denied { write } for name="property_service" dev="tmpfs" ino=7845 scontext=u:r:untrusted_app:s0:c149,c256,c512,c768 tcontext=u:object_r:property_socket:s0 tclass=sock_file permissive=0 app=com.google.firebase.example.fireeats
    2024-02-26 21:22:25.770 3858-3902 libEGL com...gle.firebase.example.fireeats D loaded /vendor/lib/egl/libEGL_emulation.so
    2024-02-26 21:22:25.774 3858-3902 libEGL com...gle.firebase.example.fireeats D loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
    2024-02-26 21:22:25.778 3858-3902 libEGL com...gle.firebase.example.fireeats D loaded /vendor/lib/egl/libGLESv2_emulation.so
    2024-02-26 21:22:25.833 3858-3858 AppCompatDelegate com...gle.firebase.example.fireeats D Checking for metadata for AppLocalesMetadataHolderService : Service not found
    2024-02-26 21:22:25.899 3858-3858 xample.fireeat com...gle.firebase.example.fireeats W Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
    2024-02-26 21:22:25.899 3858-3858 xample.fireeat com...gle.firebase.example.fireeats W Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
    2024-02-26 21:22:26.299 3858-3858 Choreographer com...gle.firebase.example.fireeats I Skipped 33 frames! The application may be doing too much work on its main thread.
    2024-02-26 21:22:26.321 3858-3900 HostConnection com...gle.firebase.example.fireeats D HostConnection::get() New Host Connection established 0xd9c562d0, tid 3900
    2024-02-26 21:22:26.322 3858-3900 HostConnection com...gle.firebase.example.fireeats D HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2
    2024-02-26 21:22:26.327 3858-3900 OpenGLRenderer com...gle.firebase.example.fireeats W Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
    2024-02-26 21:22:26.333 3858-3858 RecyclerView com...gle.firebase.example.fireeats W No adapter attached; skipping layout
    2024-02-26 21:22:26.351 3858-3900 EGL_emulation com...gle.firebase.example.fireeats D eglCreateContext: 0xd9c1a1e0: maj 2 min 0 rcv 2
    2024-02-26 21:22:26.385 3858-3900 EGL_emulation com...gle.firebase.example.fireeats D eglMakeCurrent: 0xd9c1a1e0: ver 2 0 (tinfo 0xd9c0f760)
    2024-02-26 21:22:26.405 3858-3900 Gralloc3 com...gle.firebase.example.fireeats W mapper 3.x is not supported
    2024-02-26 21:22:26.406 3858-3900 HostConnection com...gle.firebase.example.fireeats D createUnique: call
    2024-02-26 21:22:26.406 3858-3900 HostConnection com...gle.firebase.example.fireeats D HostConnection::get() New Host Connection established 0xd9c56410, tid 3900
    2024-02-26 21:22:26.407 3858-3900 HostConnection com...gle.firebase.example.fireeats D HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_sync_buffer_data GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_2
    2024-02-26 21:22:26.408 3858-3900 eglCodecCommon com...gle.firebase.example.fireeats D allocate: Ask for block of size 0x1000
    2024-02-26 21:22:26.408 3858-3900 eglCodecCommon com...gle.firebase.example.fireeats D allocate: ioctl allocate returned offset 0x3fe0a4000 size 0x2000
    2024-02-26 21:22:26.431 3858-3900 EGL_emulation com...gle.firebase.example.fireeats D eglMakeCurrent: 0xd9c1a1e0: ver 2 0 (tinfo 0xd9c0f760)
    2024-02-26 21:22:26.477 3858-3900 OpenGLRenderer com...gle.firebase.example.fireeats I Davey! duration=722ms; Flags=1, IntendedVsync=201716567812486, Vsync=201717117812464, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=201717129780200, AnimationStart=201717129821500, PerformTraversalsStart=201717130112000, DrawStart=201717242406100, SyncQueued=201717244505300, SyncStart=201717262126900, IssueDrawCommandsStart=201717262235500, SwapBuffers=201717303333100, FrameCompleted=201717308256900, DequeueBufferDuration=36000, QueueBufferDuration=112000,
    2024-02-26 21:22:26.521 3858-3858 ActivityThread com...gle.firebase.example.fireeats W handleWindowVisibility: no activity for token android.os.BinderProxy@ef5c25e
    2024-02-26 21:22:26.562 3858-3858 AndroidRuntime com...gle.firebase.example.fireeats D Shutting down VM
    2024-02-26 21:22:26.562 3858-3858 AndroidRuntime com...gle.firebase.example.fireeats E FATAL EXCEPTION: main
    Process: com.google.firebase.example.fireeats, PID: 3858
    java.lang.NoClassDefFoundError: Failed resolution of: Lcom/google/android/gms/auth/api/credentials/CredentialsOptions$Builder;
    at com.firebase.ui.auth.util.GoogleApiUtils.getCredentialsClient(GoogleApiUtils.java:29)
    at com.firebase.ui.auth.viewmodel.AuthViewModelBase.onCreate(AuthViewModelBase.java:30)
    at com.firebase.ui.auth.viewmodel.ViewModelBase.init(ViewModelBase.java:24)
    at com.firebase.ui.auth.KickoffActivity.onCreate(KickoffActivity.java:38)
    at android.app.Activity.performCreate(Activity.java:7802)
    at android.app.Activity.performCreate(Activity.java:7791)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
    Caused by: java.lang.ClassNotFoundException: Didn't find class "com.google.android.gms.auth.api.credentials.CredentialsOptions$Builder" on path: DexPathList[[zip file "/data/app/com.google.firebase.example.fireeats-DP85ZDU3x4C6liKNVnCw0Q==/base.apk"],nativeLibraryDirectories=[/data/app/com.google.firebase.example.fireeats-DP85ZDU3x4C6liKNVnCw0Q==/lib/x86, /system/lib, /system/product/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    at com.firebase.ui.auth.util.GoogleApiUtils.getCredentialsClient(GoogleApiUtils.java:29) 
    at com.firebase.ui.auth.viewmodel.AuthViewModelBase.onCreate(AuthViewModelBase.java:30) 
    at com.firebase.ui.auth.viewmodel.ViewModelBase.init(ViewModelBase.java:24) 
    at com.firebase.ui.auth.KickoffActivity.onCreate(KickoffActivity.java:38) 
    at android.app.Activity.performCreate(Activity.java:7802) 
    at android.app.Activity.performCreate(Activity.java:7791) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
    at android.os.Handler.dispatchMessage(Handler.java:107) 
    at android.os.Looper.loop(Looper.java:214) 
    at android.app.ActivityThread.main(ActivityThread.java:7356) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

Expected Results:

  • What did you expect to happen?
  • I expected the app to prompt me to log in for authentication.

Relevant Code:

Unknown

Missing information

Thanks for the Code lab.
In step 5 "Sort and filter data" there´s a text: "In the logs you will notice some warnings:"
I think there should be an explanation on where this log is located?

Invalid data. Unsupported type: com.google.firebase.firestore.QueryDocumentSnapshot

ImageDataModel.kt

class ImageDataModel @Inject constructor(private val firebaseFirestore: FirebaseFirestore) : ViewModel() {


var isLoading  = MutableLiveData<Boolean>()
var isPagerLoading  = MutableLiveData<Boolean>()

var apiError = MutableLiveData<String>()

var imgResponse = MutableLiveData<QuerySnapshot>()


fun getPhotosByOrder(orderBy: String){
    isLoading.value = true
    var query: Query
    query = firebaseFirestore.collection(DBConstant.PHOTO.tableNm)
        .orderBy(orderBy)
        .limit(12)
    query.get()
        .addOnSuccessListener { documentSnapshots ->
            // Get the last visible document
            if(documentSnapshots != null){
                isLoading.value = false
                imgResponse.value = documentSnapshots
            }else{
                isLoading.value = false
                apiError.value = Constant.SERVER_CONNECTION_ERROR
            }
        }
        .addOnFailureListener {
            isLoading.value = false
            apiError.value = it.message
        }

}

fun getPhotosByOrderPagination(orderBy: String, lastVisible: DocumentSnapshot?){
    isPagerLoading.value = true
    var query: Query
    query = firebaseFirestore.collection(DBConstant.PHOTO.tableNm)
        .orderBy(orderBy)
        .startAfter(lastVisible)
        .limit(6)

    query.get()
        .addOnSuccessListener { documentSnapshots ->
            // Get the last visible document
            if(documentSnapshots != null){
                isPagerLoading.value = false
                imgResponse.value = documentSnapshots
            }else{
                isPagerLoading.value = false
                apiError.value = Constant.SERVER_CONNECTION_ERROR
            }
        }
        .addOnFailureListener {
            isPagerLoading.value = false
            apiError.value = it.message
        }

}

}

Activity class:

  private var lastVisible: DocumentSnapshot?= null

  private fun bindObservers(){
    imageDataModel.isLoading.observe(this, androidx.lifecycle.Observer {
        if(it){
            llPbLoading.visibility = View.VISIBLE
            rvListFragBrowse.visibility = View.GONE
        }else{
            llPbLoading.visibility = View.GONE
            rvListFragBrowse.visibility = View.VISIBLE
        }
    })

    imageDataModel.apiError.observe(this, androidx.lifecycle.Observer {
        toast(it, activity!!)
    })

    imageDataModel.imgResponse.observe(this, androidx.lifecycle.Observer {
        photosList.clear()
        if(it.size() > 0){
            lastVisible = it.documents[it.size() - 1]
            Log.e("BrowseFrag","Last Item Name: "+lastVisible!!)
            for(item in it){
                var photoData = item.toObject(PhotosData::class.java)
                photoData.id = item.id
                photosList.add(photoData)
                mAdapterBrowse.notifyDataSetChanged()

            }
        }
    })

}

private fun getPhotosByOrder(orderBy: String){
    if(lastVisible == null){
        imageDataModel.getPhotosByOrder(orderBy)
    }else{
        imageDataModel.getPhotosByOrderPagination(orderBy, lastVisible)
    }
}

I am getting below error log:
java.lang.IllegalArgumentException: Invalid data. Unsupported type: com.google.firebase.firestore.QueryDocumentSnapshot at com.google.firebase.firestore.core.UserData$ParseContext.createError(com.google.firebase:firebase-firestore@@17.1.5:293) at com.google.firebase.firestore.UserDataConverter.parseScalarValue(com.google.firebase:firebase-firestore@@17.1.5:405) at com.google.firebase.firestore.UserDataConverter.parseData(com.google.firebase:firebase-firestore@@17.1.5:254) at com.google.firebase.firestore.UserDataConverter.parseQueryValue(com.google.firebase:firebase-firestore@@17.1.5:186) at com.google.firebase.firestore.Query.boundFromFields(com.google.firebase:firebase-firestore@@17.1.5:669) at com.google.firebase.firestore.Query.startAfter(com.google.firebase:firebase-firestore@@17.1.5:517) at com.firestoredemo.viewmodel.ImageDataModel.getPhotosByOrderPagination(ImageDataModel.kt:64) at com.firestoredemo.ui.fragment.BrowseFragment.getPhotosByOrder(BrowseFragment.kt:228) at com.firestoredemo.ui.fragment.BrowseFragment.access$getPhotosByOrder(BrowseFragment.kt:44) at com.firestoredemo.ui.fragment.BrowseFragment$setListener$2.onLoadMore(BrowseFragment.kt:153) at com.firestoredemo.adapter.BrowseResultAdapter$1.onScrolled(BrowseResultAdapter.kt:57)

Query filter of cloud firestore does not work properly!?

I was trying to implement a filter for querying data from firebase firestore just like the one in the codelab but i could not have it work well , the only way to make that query is by concatenating whereEqaulTo into a single statement otherwise it will not work, in fact ,if you set many whereEqualTo on the query object each one in a separate statement only the first statement whereEqualTo method is applied . the rest are ignored.
Firebase database have limited abilities when it comes to fetching and filtering data that is because it is no-sql database , having such issue make it even worse for someone who is looking for flexible and complex queries. I hope that you firebase team will find a solution for this issue soon.

Clarification needed on index creation

Thanks for the Code lab.
In step 5 "Sort and filter data" user learns to create an index in the Firestore. The index talked about is price and numRating. However there is no explanation why in the demo app user can filer on food and city without creating this Firestore index?

Further explanation:
If I search for city Miami I get two hits. This does not require a Firestore index right.
There are two Miami one with coffee and one with pizza.
If I search for city Miami and food pizza I get one result. This should require a Firestore index or??

Firestore Query Warning with "price" equality filter and OrderBy set to the same "price" field

Following warning is reported by our custom FirestoreAdapter, when a user chooses to filter by a particular price and then sorts the results by price in the Filter Dialog-

2021-03-21 23:29:04.761 7574-7574/? W/FirestoreAdapter: onEvent:error
    com.google.firebase.firestore.o: INVALID_ARGUMENT: Order by clause cannot contain a field with an equality filter price
        at com.google.firebase.firestore.p0.b0.k(Unknown Source:22)
        at com.google.firebase.firestore.k0.o.b(Unknown Source:30)
        at com.google.firebase.firestore.k0.o0.r(Unknown Source:41)
        at com.google.firebase.firestore.k0.o0.c(Unknown Source:83)
        at com.google.firebase.firestore.k0.g0$b.c(Unknown Source:6)
        at com.google.firebase.firestore.o0.m0.D(Unknown Source:69)
        at com.google.firebase.firestore.o0.m0.s(Unknown Source:55)
        at com.google.firebase.firestore.o0.m0.d(Unknown Source:0)
        at com.google.firebase.firestore.o0.m0$a.e(Unknown Source:2)
        at com.google.firebase.firestore.o0.t0.u(Unknown Source:21)
        at com.google.firebase.firestore.o0.t0.n(Unknown Source:2)
        at com.google.firebase.firestore.o0.b$c.g(Unknown Source:42)
        at com.google.firebase.firestore.o0.d.run(Unknown Source:4)
        at com.google.firebase.firestore.o0.b$a.a(Unknown Source:21)
        at com.google.firebase.firestore.o0.b$c.d(Unknown Source:6)
        at com.google.firebase.firestore.o0.t$a.c(Unknown Source:2)
        at e.a.k1.p$e$b.b(Unknown Source:40)
        at e.a.k1.p$e$b.a(Unknown Source:18)
        at e.a.k1.x.run(Unknown Source:6)
        at e.a.k1.z1.run(Unknown Source:11)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at com.google.firebase.firestore.p0.g$c$b.run(Unknown Source:15)
        at java.lang.Thread.run(Thread.java:929)
     Caused by: e.a.e1: INVALID_ARGUMENT: Order by clause cannot contain a field with an equality filter price
        at e.a.d1.c(Unknown Source:2)
        at com.google.firebase.firestore.p0.b0.k(Unknown Source:0)
        at com.google.firebase.firestore.k0.o.b(Unknown Source:30) 
        at com.google.firebase.firestore.k0.o0.r(Unknown Source:41) 
        at com.google.firebase.firestore.k0.o0.c(Unknown Source:83) 
        at com.google.firebase.firestore.k0.g0$b.c(Unknown Source:6) 
        at com.google.firebase.firestore.o0.m0.D(Unknown Source:69) 
        at com.google.firebase.firestore.o0.m0.s(Unknown Source:55) 
        at com.google.firebase.firestore.o0.m0.d(Unknown Source:0) 
        at com.google.firebase.firestore.o0.m0$a.e(Unknown Source:2) 
        at com.google.firebase.firestore.o0.t0.u(Unknown Source:21) 
        at com.google.firebase.firestore.o0.t0.n(Unknown Source:2) 
        at com.google.firebase.firestore.o0.b$c.g(Unknown Source:42) 
        at com.google.firebase.firestore.o0.d.run(Unknown Source:4) 
        at com.google.firebase.firestore.o0.b$a.a(Unknown Source:21) 
        at com.google.firebase.firestore.o0.b$c.d(Unknown Source:6) 
        at com.google.firebase.firestore.o0.t$a.c(Unknown Source:2) 
        at e.a.k1.p$e$b.b(Unknown Source:40) 
        at e.a.k1.p$e$b.a(Unknown Source:18) 
        at e.a.k1.x.run(Unknown Source:6) 
        at e.a.k1.z1.run(Unknown Source:11) 
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462) 
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) 
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at com.google.firebase.firestore.p0.g$c$b.run(Unknown Source:15) 
        at java.lang.Thread.run(Thread.java:929) 

Looks like we need to disable the sort option on price when a particular price is selected by the user.

Hida

Step 1: Describe your environment

  • Android device: _____
  • Android OS version: _____

Step 2: Describe the problem:

Steps to reproduce:




Observed Results:

  • What happened? This could be a description, logcat output, etc.

Expected Results:

  • What did you expect to happen?

Relevant Code:

// TODO(you): code here to reproduce the problem

link is missing for instructions

There should be instruction link for this sentence: If you don't have npm or you experience an error, read the installation instructions to get a standalone binary for your platform.

Writing to Firestore

I have followed the steps up until Step 6, but none of the restaurant data is being stored in the Firestore. My user account gets stored in the Authentication tab, but nothing changes in Firestore.
The Emulator is running.
The Logcat shows no errors.
image
This is a snippet of the Logcat after clicking Add Random Items. The objects are created and they send off a com.google.firestore.v1.WriteRequest and there is a WriteResponse (the latter is in the picture above).

I have restarted this project a couple of times and I can't for the life of me figure out the issue

Question about the FirestoreAdapter DocumentSnapshot deserialized

Thanks for the codelab its fun to learn this coming from Firebase real time databas.

In the FirestoreAdapter class javadoc I read:

/**
 * RecyclerView adapter for displaying the results of a Firestore {@link Query}.
 *
 * Note that this class forgoes some efficiency to gain simplicity. For example, the result of
 * {@link DocumentSnapshot#toObject(Class)} is not cached so the same object may be deserialized
 * many times as the user scrolls.
 */

First I was thinking that efficiency explanation should be in the RestaurantAdapter but could you explain some more how this works if this is some Cloud Firestore feature or RecyclerView?

What about that all objects are cashed on Android and never read twice unless they are changed? What does this mean "many times as the user scrolls." scroll happens in RestaurantAdapter which read the already loaded DocumentSnapshot´s objects or??

Listener

Hi, I've been playing with the code and I was wondering why do you need the listener on the Restaurant collection? Let's say I want to remove the listener as there won't be any changes to my restaurant collection, how will you do that?

Rewrite your codelab

It's year 2024 and we have a modern Jetpack Compose available. It's time to rewrite this codelab in modern Jetpack Compose Kotlin language.

" Jibe SDK Service not available" when running app

2021-10-29 14:31:04.158 10248-10274/? E/Bugle: RcsUtils. Error getting default configuration value for fallback setting
2021-10-29 14:31:04.158 10248-10274/? E/Bugle: com.google.android.rcs.client.e: Jibe SDK Service not available. Is the Jibe SDK service running? Did you call connect() and wait for the notification before calling an API function?
at com.google.android.rcs.client.a.c(SourceFile:76)
at com.google.android.rcs.client.profile.RcsProfileService.getRcsConfig(SourceFile:67)
at com.google.android.apps.messaging.shared.sms.al.i(SourceFile:772)
at com.google.android.apps.messaging.shared.analytics.RecurringTelemetryUploaderAction.doBackgroundWork(SourceFile:208)
at com.google.android.apps.messaging.shared.datamodel.action.ActionExecutorImpl$BackgroundWorkerRunnable.run(SourceFile:12)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at com.google.android.apps.messaging.shared.datamodel.action.c.run(SourceFile:10)

How to Paginate the same list in this?

I am using this example, but am not able to paginate the data in this list according to the filters applied. I learn to paginate the list with filters in android. The other one I already know how to do it, by simply applying the FirestorePagingAdapter.

missing F in firestore word

Goals
In this codelab you will build a restaurant recommendation app on Android backed by Cloud # irestore. You will learn how to:

Cannot start the Storage emulator without rules file specified in firebase.json: run 'firebase init' and set up your Storage configuration

Step 1: Describe your environment

  • Android device: _____
  • Android OS version: _____

Step 2: Describe the problem:

I am having issue to start to Firebase Emulator UI. Firebase initialization complete! code appears but I face with a problem when try to start the emulators.

Could you please help me to solve the issue?
Thanks.

Steps to reproduce:

Please see the complete UI code like below:

###################################################################################################################################################################################################################

     Welcome to...
   ######## #### ########  ######## ########     ###     ######  ########  ##
   ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##        ##
   ######    ##  ########  ######   ########  #########  ######  ######    ##
   ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
   ##       #### ##     ## ######## ########  ##     ##  ######  ########  ##


###################################################################################################################################################################################################################

~ Let's make sure your Firebase CLI is ready...
~ Looks like your CLI needs to be set up.

~ This may take a moment
+ Alright, your CLI is set up!

Already logged in as **********@gmail.com

+ You can now use the 'firebase' or 'npm' commands!
~ For more help see https://firebase.google.com/docs/cli/

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

> firebase init emulators

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

You're about to initialize a Firebase project in this directory:

  C:\Users\******\AndroidStudioProjects\friendlyeats-android

Before we get started, keep in mind:

  * You are initializing within an existing Firebase project directory

? Are you ready to proceed? Yes

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

i  Using project friendly-eats-b308b (Friendly Eats)

=== Emulators Setup
? Which Firebase emulators do you want to set up? Press Space to select emulators, then Enter to confirm your choices. Authentication Emulator, Functions Emulator, Firestore Emulator, Database Emulator, Hosting
Emulator, Pub/Sub Emulator, Storage Emulator
i  Port for auth already configured: 9099
i  Port for functions already configured: 5001
i  Port for firestore already configured: 8080
i  Port for database already configured: 9000
i  Port for hosting already configured: 5000
i  Port for pubsub already configured: 8085
i  Port for storage already configured: 9199
i  Emulator UI already enabled with port: (automatic)
? Would you like to download the emulators now? Yes
i  firestore: downloading cloud-firestore-emulator-v1.14.3.jar...
Progress: ========================================================================================================================================================================================> (100% of 61MB)
i  database: downloading firebase-database-emulator-v4.8.0.jar...
Progress: ========================================================================================================================================================================================> (100% of 34MB)
i  pubsub: downloading pubsub-emulator-0.1.0.zip...
Progress: ========================================================================================================================================================================================> (100% of 37MB)
i  storage: downloading cloud-storage-rules-runtime-v1.0.2.jar...
Progress: ========================================================================================================================================================================================> (100% of 36MB)
i  ui: downloading ui-v1.7.0.zip...

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

+  Firebase initialization complete!

> firebase emulators:start
i  emulators: Starting emulators: auth, functions, firestore, database, hosting, pubsub, storage
!  functions: The functions emulator is configured but there is no functions source directory. Have you run firebase init functions?
i  firestore: Firestore Emulator logging to firestore-debug.log
!  database: Did not find a Realtime Database rules file specified in a firebase.json config file. The emulator will default to allowing all reads and writes. Learn more about this option: https://firebase.google.com/docs/emulator-suite/install_and_configure#security_rules_configuration.
i  database: Database Emulator logging to database-debug.log
i  pubsub: Pub/Sub Emulator logging to pubsub-debug.log
i  emulators: Shutting down emulators.
i  database: Stopping Database Emulator
!  Database Emulator has exited upon receiving signal: SIGINT
i  firestore: Stopping Firestore Emulator
!  Firestore Emulator has exited upon receiving signal: SIGINT
i  pubsub: Stopping Pub/Sub Emulator
!  Pub/Sub Emulator has exited upon receiving signal: SIGINT
i  auth: Stopping Authentication Emulator
i  hub: Stopping emulator hub

Error: Cannot start the Storage emulator without rules file specified in firebase.json: run 'firebase init' and set up your Storage configuration

>

Observed Results:

  • What happened? This could be a description, logcat output, etc.

image

The screen below also pops up when the error occurs.

image

Expected Results:

Could you please help me to solve this problem? Thanks.

Relevant Code:

firebase.json =>

{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "emulators": {
    "auth": {
      "port": 9099
    },
    "firestore": {
      "port": 8080
    },
    "ui": {
      "enabled": true
    },
    "functions": {
      "port": 5001
    },
    "database": {
      "port": 9000
    },
    "hosting": {
      "port": 5000
    },
    "pubsub": {
      "port": 8085
    },
    "storage": {
      "port": 9199
    }
  }
}

firestore.rules =>

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      //
      // WARNING: These rules are insecure! We will replace them with
      // more secure rules later in the codelab
      //
      allow read, write: if request.auth != null;
    }
  }
}

firestore.indexes.json =>

{
  "indexes": [
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "price", "mode": "ASCENDING" },
        { "fieldPath": "avgRating", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "price", "mode": "ASCENDING" },
        { "fieldPath": "numRatings", "mode": "DESCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "city", "mode": "ASCENDING" },
        { "fieldPath": "price", "mode": "ASCENDING" }
      ]
    },
    {
      "collectionId": "restaurants",
      "fields": [
        { "fieldPath": "category", "mode": "ASCENDING" },
        { "fieldPath": "price", "mode": "ASCENDING" }
      ]
    }
  ],
  "fieldOverrides": []
}

Gradle project sync fail.

The project is using an incompatible version (AGP 8.2.0) of the Android Gradle plugin. Latest supported version is AGP 8.1.4
See Android Studio & AGP compatibility options.

setQuery to load more documents

Hi,
I'm practicing with your FirebaseAdapter and I'm trying to implement the load more function, I mean, when you scroll down and you reach the end of the screen, the App should load more documents automatically.

This is called "pagination" according to the documentation here.

I have modified this:

public abstract class FirestoreAdapter..........  {
    .....
    ........
    private DocumentSnapshot mLastVisible;

    @Override
    public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
        ....
            ..
            ...
            ..
        ..

        ...............
        ...
        onDataChanged();

        // Get the last visible document
        mLastVisible = documentSnapshots.getDocuments().get(documentSnapshots.size() - 1);
    }

public void setQueryForLoadMore(Query query) {
        mQuery = query;
        notifyDataSetChanged();
    }

    public DocumentSnapshot getLastVisible() {
        return mLastVisible;
    }

MainActivity:

mAdapter.setQueryForLoadMore(loadMoreQuery());

private Query loadMoreQuery() {
        // Return ${LIMIT} documents after the last visible document from first query
        return mFirestore.collection("posts")
                .orderBy("timestamp", Query.Direction.DESCENDING)
                .startAfter(mAdapter.getLastVisible())
                .limit(LIMIT);
    }

The new documents seems to be inserted correctly but, is not showing it on the screen.

If I do this:

    public void setQueryForLoadMore(Query query) {
        // Stop listening
        //stopListening(); I commented this because this method is clearing mSnapshots

        // Clear existing data
        //mSnapshots.clear(); I commented this because I want to maintain the previous documents
        notifyDataSetChanged();

        // Listen to new query
        mQuery = query;
        startListening(); // If I comment this, still nothing appears after the previous documents
    }

Still the new documents are not showing up.

Any idea how can I get the new documents to be added right after the previous documents?

Fabio 13

Step 1: Describe your environment

  • Android device: _____
  • Android OS version: _____

Step 2: Describe the problem:

Steps to reproduce:




Observed Results:

  • What happened? This could be a description, logcat output, etc.

Expected Results:

  • What did you expect to happen?

Relevant Code:

// TODO(you): code here to reproduce the problem

Step 4:Error: (58, 56) - in the line mRegistration = mQuery.addSnapshotListener(this);

mRegistration = mQuery.addSnapshotListener(this);

"this" is getting me this error.

Error:(58, 56) error: incompatible types: FirestoreAdapter<VH> cannot be converted to EventListener<QuerySnapshot> where VH is a type-variable: VH extends ViewHolder declared in class FirestoreAdapter

NOTE: the interface EventLister is empty , so I just have to comment the
//@OverRide
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

Code bellow

/**
 * Copyright 2017 Google Inc. All Rights Reserved.
 *
 * 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.
 */
 package com.google.firebase.example.fireeats.adapter;

import android.support.v7.widget.RecyclerView;
import android.util.Log;

import com.google.firebase.firestore.DocumentChange;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.ListenerRegistration;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QuerySnapshot;

import java.util.ArrayList;
import java.util.EventListener;

/**
 * RecyclerView adapter for displaying the results of a Firestore {@link Query}.
 *
 * Note that this class forgoes some efficiency to gain simplicity. For example, the result of
 * {@link DocumentSnapshot#toObject(Class)} is not cached so the same object may be deserialized
 * many times as the user scrolls.
 * 
 * See the adapter classes in FirebaseUI (https://github.com/firebase/FirebaseUI-Android/tree/master/firestore) for a
 * more efficient implementation of a Firestore RecyclerView Adapter.
 */
public abstract class FirestoreAdapter<VH extends RecyclerView.ViewHolder>
        extends RecyclerView.Adapter<VH> implements EventListener {

    private static final String TAG = "Firestore Adapter";

    private Query mQuery;
    private ListenerRegistration mRegistration;

    private ArrayList<DocumentSnapshot> mSnapshots = new ArrayList<>();

    public FirestoreAdapter(Query query) {
        mQuery = query;
    }

    public void startListening() {
        // TODO(developer): Implement
        if (mQuery != null && mRegistration == null) {
            mRegistration = mQuery.addSnapshotListener(this);
        }
    }

    public void stopListening() {
        if (mRegistration != null) {
            mRegistration.remove();
            mRegistration = null;
        }

        mSnapshots.clear();
        notifyDataSetChanged();
    }


    public void setQuery(Query query) {
        // Stop listening
        stopListening();

        // Clear existinkodig data
        mSnapshots.clear();
        notifyDataSetChanged();

        // Listen to new query
        mQuery = query;
        startListening();
    }


    //@Override
    public void onEvent(QuerySnapshot documentSnapshots,  FirebaseFirestoreException e) {

        // Handle errors
        if (e != null) {
            Log.w(TAG, "onEvent:error", e);
            return;
        }

        // Dispatch the event
        for (DocumentChange change : documentSnapshots.getDocumentChanges()) {
            // Snapshot of the changed document
            DocumentSnapshot snapshot = change.getDocument();

            switch (change.getType()) {
                case ADDED:
                    // TODO: handle document added
                    onDocumentAdded(change);
                    break;
                case MODIFIED:
                    // TODO: handle document modified
                    onDocumentModified(change);
                    break;
                case REMOVED:
                    // TODO: handle document removed
                    onDocumentRemoved(change);
                    break;
            }
        }
        onDataChanged();
    }


    protected void onDocumentAdded(DocumentChange change){
        mSnapshots.add(change.getNewIndex(), change.getDocument());
        notifyItemInserted(change.getNewIndex());
    }

    protected void onDocumentModified(DocumentChange change){
        if (change.getOldIndex() == change.getNewIndex()) {
            mSnapshots.set(change.getOldIndex(), change.getDocument());
            notifyItemChanged(change.getOldIndex());
        } else {
            mSnapshots.remove(change.getOldIndex());
            mSnapshots.add(change.getNewIndex(), change.getDocument());
            notifyItemMoved(change.getOldIndex(), change.getNewIndex());
        }
    }

    protected void onDocumentRemoved(DocumentChange change){
        mSnapshots.remove(change.getOldIndex());
        notifyItemRemoved(change.getOldIndex());
    }

    @Override
    public int getItemCount() {
        return mSnapshots.size();
    }

    protected DocumentSnapshot getSnapshot(int index) {
        return mSnapshots.get(index);
    }

    protected void onError(FirebaseFirestoreException e) {};

    protected void onDataChanged() {}
}

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.