<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thierry</title>
    <description>The latest articles on DEV Community by Thierry (@tschellenbach).</description>
    <link>https://dev.to/tschellenbach</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F70376%2Fc3b45cff-0334-4e64-bfe9-f97871c18027.jpeg</url>
      <title>DEV Community: Thierry</title>
      <link>https://dev.to/tschellenbach</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tschellenbach"/>
    <language>en</language>
    <item>
      <title>Free Maker accounts for Stream</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Wed, 17 Mar 2021 21:03:11 +0000</pubDate>
      <link>https://dev.to/tschellenbach/free-maker-accounts-for-stream-a0l</link>
      <guid>https://dev.to/tschellenbach/free-maker-accounts-for-stream-a0l</guid>
      <description>&lt;p&gt;As some of you know I've been working on my startup Stream for about 5 years now. We've just raised a large series B and it enabled us to make Stream free for hobby/side projects. We &lt;a href="https://getstream.io/blog/maker-account/"&gt;announced it&lt;/a&gt; today and I'm pretty excited to see what people will build :)&lt;/p&gt;

&lt;p&gt;Stream is available for iOS, Android, React, RN and Flutter. I think the &lt;a href="https://getstream.io/chat/flutter/tutorial/"&gt;Flutter SDK&lt;/a&gt; is especially interesting for side projects. It's been amazing to see what small teams can ship on that platform.&lt;/p&gt;

</description>
      <category>chat</category>
      <category>flutter</category>
      <category>go</category>
    </item>
    <item>
      <title>Pusher Chatkit Migration</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Mon, 23 Mar 2020 18:11:28 +0000</pubDate>
      <link>https://dev.to/tschellenbach/pusher-chatkit-migration-2nan</link>
      <guid>https://dev.to/tschellenbach/pusher-chatkit-migration-2nan</guid>
      <description>&lt;p&gt;I just read the news about &lt;a href="https://getstream.io/blog/pusher-shutting-down-chatkit/"&gt;Pusher Chatkit shutting down&lt;/a&gt;. They are only giving people 30 days to migrate their data so this is going to get a little hectic. &lt;/p&gt;

&lt;p&gt;Our &lt;a href="https://getstream.io/chat/"&gt;chat platform&lt;/a&gt; is a great &lt;a href="https://getstream.io/blog/stream-vs-pusher/"&gt;alternative to Chatkit&lt;/a&gt; so I've started creating a &lt;a href="https://github.com/GetStream/pusher-chatkit-migration"&gt;guide on how to migrate from Pusher Chatkit to Stream&lt;/a&gt;. It's not finished yet, bit of a WIP. If anyone needs help feel free to reach out. &lt;/p&gt;

</description>
      <category>chat</category>
      <category>pusher</category>
      <category>chatkit</category>
      <category>migration</category>
    </item>
    <item>
      <title>Corona projects?</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Sat, 14 Mar 2020 19:46:47 +0000</pubDate>
      <link>https://dev.to/tschellenbach/corona-projects-565p</link>
      <guid>https://dev.to/tschellenbach/corona-projects-565p</guid>
      <description>&lt;p&gt;I suspect that quite a few of us are working on projects related to corona virus. If you need chat or activity feed technology for a non-profit project that's helping to mitigate the coronavirus impact &lt;a href="https://twitter.com/tschellenbach"&gt;DM&lt;/a&gt; me and I'll set up a free Stream account. EDtech, telemedicine, DMV, groceries, social distancing, contact research. Anything goes #flattenthecurve&lt;/p&gt;

&lt;p&gt;There's quite a few cool projects popping up so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/mattroconnor/deep_learning_coronavirus_cure"&gt;https://github.com/mattroconnor/deep_learning_coronavirus_cure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MhdHejazi/CoronaTracker"&gt;https://github.com/MhdHejazi/CoronaTracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/JohnCoene/coronavirus"&gt;https://github.com/JohnCoene/coronavirus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/RamiKrispin/coronavirus"&gt;https://github.com/RamiKrispin/coronavirus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/alfianlosari/CoronaVirusTrackerSwiftUI"&gt;https://github.com/alfianlosari/CoronaVirusTrackerSwiftUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/AaronWard/covid-19-analysis"&gt;https://github.com/AaronWard/covid-19-analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.instructables.com/id/The-Pandemic-Ventilator/"&gt;https://www.instructables.com/id/The-Pandemic-Ventilator/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>corona</category>
    </item>
    <item>
      <title>Build a WhatsApp Clone on Android With Kotlin – Part 1</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Fri, 31 Jan 2020 15:07:01 +0000</pubDate>
      <link>https://dev.to/tschellenbach/build-a-whatsapp-clone-on-android-with-kotlin-part-1-mg</link>
      <guid>https://dev.to/tschellenbach/build-a-whatsapp-clone-on-android-with-kotlin-part-1-mg</guid>
      <description>&lt;p&gt;Android development has come a long way over the last few years. The &lt;a href="https://developer.android.com/jetpack" rel="noopener noreferrer"&gt;Jetpack&lt;/a&gt; components significantly speed up development. In this tutorial, we’ll &lt;strong&gt;build a functional clone of WhatsApp with &lt;a href="https://kotlinlang.org/" rel="noopener noreferrer"&gt;Kotlin&lt;/a&gt;&lt;/strong&gt;. Building a messaging app used to be difficult; in this tutorial, you’ll get a chat experience up and running in roughly 20 minutes. The first part of this tutorial focuses on the chat functionality of WhatsApp, and in part 2, we’ll cover audio and video calling. Time to get started!&lt;/p&gt;

&lt;p&gt;If you get lost during this tutorial you can have a look at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/GetStream/WhatsApp-Clone-Android" rel="noopener noreferrer"&gt;The WhatsApp clone Github repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getstream.io/tutorials/android-chat/#kotlin" rel="noopener noreferrer"&gt;Stream’s Kotlin Chat tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The end result will look similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F6691bb74896406c4a17f8e3b52fe8f07%2Fimage7.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F6691bb74896406c4a17f8e3b52fe8f07%2Fimage7.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Clone the WhatsApp Starter Repo
&lt;/h2&gt;

&lt;p&gt;Start by cloning the &lt;strong&gt;starter&lt;/strong&gt; branch of the &lt;a href="https://github.com/GetStream/WhatsApp-Clone-Android" rel="noopener noreferrer"&gt;WhatsApp Clone Github repo&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;-b&lt;/span&gt; starter git@github.com:GetStream/WhatsApp-Clone-Android.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The starter branch sets up a few simple things so you can skip the boilerplate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dependencies in the &lt;code&gt;build.gradle&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Colors&lt;/li&gt;
&lt;li&gt;Menu items&lt;/li&gt;
&lt;li&gt;Drawables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open the &lt;code&gt;WhatsApp-Clone-Android&lt;/code&gt; directory in &lt;a href="https://developer.android.com/studio" rel="noopener noreferrer"&gt;Android Studio&lt;/a&gt; and wait for the Gradle sync to complete. For this tutorial, you’ll want to use the &lt;strong&gt;Pixel 3 / API Level 29 Emulator&lt;/strong&gt; for testing. After you’ve got that setup run the application. You should now see this empty screen:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Feada364a1fbe9f64d54d63f16704f748%2Fimage10.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Feada364a1fbe9f64d54d63f16704f748%2Fimage10.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" alt="Empty chat screen"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setup the Home Screen
&lt;/h2&gt;

&lt;p&gt;As a first step, we’re going to create the home screen of your app. Which will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fd3ffce8b0bf12a74cdb6748c9d2908c9%2Fimage5.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fd3ffce8b0bf12a74cdb6748c9d2908c9%2Fimage5.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" alt="Example of the cloned homescreen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an experienced Android developer, you’ll see a few things in this screen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.android.com/reference/androidx/appcompat/widget/Toolbar" rel="noopener noreferrer"&gt;A Toolbar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://material.io/develop/android/components/tab-layout/" rel="noopener noreferrer"&gt;A Material UI Tab Layout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.android.com/jetpack/androidx/releases/viewpager2" rel="noopener noreferrer"&gt;ViewPager2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://material.io/develop/android/components/floating-action-button/" rel="noopener noreferrer"&gt;Material UI Floating Action Button&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/GetStream/stream-chat-android/blob/master/docs/ChannelList.md" rel="noopener noreferrer"&gt;A ChannelList View&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this tutorial, we’ll follow Google’s recommendation of having 1 activity and many fragments. We’ll connect the fragments using the &lt;a href="https://developer.android.com/guide/navigation/navigation-getting-started" rel="noopener noreferrer"&gt;navigation component&lt;/a&gt;. Let’s get started.&lt;/p&gt;

&lt;p&gt;Open up &lt;code&gt;activity_main.xml&lt;/code&gt; and replace the &lt;code&gt;TextView&lt;/code&gt; tag with a &lt;code&gt;NavHostFragment&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;app:navGraph&lt;/code&gt; property tells the navigation component to use your &lt;code&gt;navigation/nav_graph.xml&lt;/code&gt; file for navigation. Let’s take a moment to review the contents of &lt;code&gt;nav_graph.xml&lt;/code&gt;:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Note how &lt;code&gt;@id/nav_home&lt;/code&gt; is specified as the &lt;code&gt;startDestination&lt;/code&gt; in the navigation tag. This makes the navigation component automatically load the &lt;code&gt;homeFragment&lt;/code&gt;. As a next step, we’re going to make the &lt;code&gt;homeFragment&lt;/code&gt; look like WhatsApp.&lt;/p&gt;

&lt;p&gt;Open up &lt;code&gt;fragment_home.xml&lt;/code&gt; and replace the contents with this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;TabLayout&lt;/code&gt; provided by the material UI package combined with the &lt;code&gt;ViewPager2&lt;/code&gt; gives you the helpful swipeable tabs that you see in the WhatsApp interface. The &lt;code&gt;FloatingActionButton&lt;/code&gt; handles the UI for creating a new conversation. &lt;/p&gt;

&lt;p&gt;As a next step open up &lt;code&gt;com.example.whatsappclone.ui.home.HomeFragment.kt&lt;/code&gt;&lt;br&gt;
You’ll see an empty fragment class with a TODO. Let’s start by updating the constructor to point to the &lt;code&gt;R.layout.fragment_home&lt;/code&gt; layout. Update the &lt;code&gt;HomeFragment&lt;/code&gt; class to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HomeFragment&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;R&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fragment_home&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This short syntax for the fragment creation is enabled by the &lt;code&gt;androidx.navigation:navigation-fragment-ktx&lt;/code&gt; dependency. It's a nice improvement compared to overwriting the onCreate method. If you run your app, you’ll see the following UI:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F0f4cde77fcb3f1b479343cab70ca3b91%2Fimage12.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F0f4cde77fcb3f1b479343cab70ca3b91%2Fimage12.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tabs are working, but the &lt;code&gt;viewPager&lt;/code&gt; and the toolbar aren’t setup yet. Go back to &lt;code&gt;com.example.whatsappclone.ui.home.HomeFragment.kt&lt;/code&gt; and update it to match this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;This looks like much code, but it’s pretty simple once you take a moment to review. The &lt;code&gt;viewPager2&lt;/code&gt; requires an adapter. We’ve set up this adapter to return an &lt;code&gt;emptyFragment&lt;/code&gt; for tabs 0, 2, and 3 and return a &lt;code&gt;ChannelListFragment&lt;/code&gt; for tab number 1.&lt;/p&gt;

&lt;p&gt;The loop over the tabs just below &lt;code&gt;getColorStateList&lt;/code&gt; handles the tint for the camera icon. This makes sure that it looks gray when it’s not selected and white when active.&lt;/p&gt;

&lt;p&gt;The TabLayoutMediator connects the &lt;code&gt;viewpager&lt;/code&gt; 2 with the tab UI. Try rerunning the app, and you’ll see it now looks much closer to the WhatsApp interface. The toolbar is rendering, and you can swipe through the tabs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F392530bbbfec0f64c13c55a17a3e36c0%2Fimage6.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F392530bbbfec0f64c13c55a17a3e36c0%2Fimage6.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Channel List
&lt;/h2&gt;

&lt;p&gt;Next, we’re going to render a list of channels/conversations. First, open up the empty &lt;code&gt;fragment_channel_list.xml&lt;/code&gt; layout and replace it with this content:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We are using the &lt;a href="https://github.com/GetStream/stream-chat-android/blob/master/docs/ChannelList.md" rel="noopener noreferrer"&gt;ChannelListView&lt;/a&gt; which is a custom view provided by Stream. This view makes it easy to render a list of channels. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You can also build your channel list view using the underlying API client. (But that’s more work, so we’re not doing it in this tutorial).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next op up &lt;code&gt;ChannelListFragment.kt&lt;/code&gt;. You’ll see an empty fragment. Replace the file’s content with this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;A few things to note in the above &lt;code&gt;ChannelListFragment&lt;/code&gt;. We’re instantiating the Stream client and connecting a user. After that we configure the &lt;code&gt;channelList&lt;/code&gt; component using &lt;code&gt;viewModel.setChannelFilter(filter)&lt;/code&gt;. In the tutorial, we’re using the example API key provided by Stream. Note that this example account is wiped regularly. So if you’re building a production app, you’ll want to register to get your own &lt;a href="https://getstream.io/chat/trial" rel="noopener noreferrer"&gt;Stream Chat API key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’re also using the &lt;strong&gt;modern Kotlin syntax&lt;/strong&gt; for getting a viewModel which is pretty nifty:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;val viewModel: ChannelListViewModel by viewModels()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Last, observe how we’re using the navigation component and Kotlin safe args to navigate from the channel list to the channel. The &lt;code&gt;HomeFragmentDirections&lt;/code&gt; class is auto-generated from &lt;code&gt;nav_graph.xml&lt;/code&gt;, and Android knows how to navigate between the various views using the defined actions in &lt;code&gt;nav_graph.xml&lt;/code&gt;. The argument tags in &lt;code&gt;nav_graph.xml&lt;/code&gt; ensure type safety:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Time to run your application. The resulting code should render an app that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fde5a35095a7876947524f4cac6928abf%2Fimage8.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fde5a35095a7876947524f4cac6928abf%2Fimage8.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Channel UI
&lt;/h2&gt;

&lt;p&gt;You’ll notice that if you click on a channel, you see an empty page. In this next step, we’re going to implement the chat/channel interface. The channel UI will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Feb4b799010fe22a4f50361c90e2d0948%2Fimage4.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Feb4b799010fe22a4f50361c90e2d0948%2Fimage4.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This UI is a &lt;a href="https://github.com/GetStream/stream-chat-android/blob/master/docs/MessageList.md" rel="noopener noreferrer"&gt;MessageListView&lt;/a&gt; and a custom message input. For the message input view, we’ll use &lt;a href="https://developer.android.com/topic/libraries/data-binding/two-way" rel="noopener noreferrer"&gt;two-way databindings&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;As a first step, open up the empty &lt;code&gt;fragment_channel.xml&lt;/code&gt; and replace the content with:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Next, open up the &lt;code&gt;ChannelFragment.kt&lt;/code&gt; file and replace its contents with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package com.example.whatsappclone.ui.channel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;A few things to note in the above code. We are instantiating a Stream channel object using the safe args passed by the &lt;code&gt;Navigation Component&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var channel = client.channel(args.channelType, args.channelId)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And we are creating a &lt;code&gt;viewChannel&lt;/code&gt; based on that &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;If you run the app you’ll now see a channel list with a very minimalistic message input view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F2f8fe2fbdf705c843525665a5334bd40%2Fimage9.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F2f8fe2fbdf705c843525665a5334bd40%2Fimage9.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Message Input View &amp;amp; Data Binding
&lt;/h2&gt;

&lt;p&gt;In this section of the tutorial, we’ll build our message input view. This is a great use case for Google’s live data two-way data-binding feature. Note how the design changes slightly if the user has entered text. This first image shows the layout when no text is entered:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fe5f37a704e7e190411f2da52fe289c35%2Fimage1.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fe5f37a704e7e190411f2da52fe289c35%2Fimage1.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next image displays the layout when the user entered the text. Note how the icon changed from "record" into "send". Additionally, the camera icon disappeared:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fc2efcc3cb512e984051eec2334f0b1cc%2Fimage11.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fc2efcc3cb512e984051eec2334f0b1cc%2Fimage11.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open the empty &lt;code&gt;view_message_input.xml&lt;/code&gt; layout and update it to match this content:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Most of this layout will be familiar to you now. There is a floating action button (FAB) for the voice record icon and a constraint layout with a background for the message input and buttons. The most exciting bit is this tag on the &lt;code&gt;EditText&lt;/code&gt; view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"@={viewModel.messageInputText}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;@=&lt;/code&gt; syntax creates a double way binding between viewModel.messageInputText and the edit text element. As soon as one of the items changes, the other changes as well. Now that we have the double way binding setup, we can use it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change the voice icon into a send icon&lt;/li&gt;
&lt;li&gt;Remove the camera icon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note how we import two utility methods using the data’s import tag:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Next, we apply the view utility method on the take picture button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;visibility&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"@{TextUtils.isEmpty(viewModel.messageInputText) ? View.VISIBLE : View.GONE}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That line causes the android visibility to be set to GONE whenever the user types a message. For the floating action button, we switch the icon like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="n"&gt;android&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"@{TextUtils.isEmpty(viewModel.messageInputText) ? @drawable/ic_mic_black_24dp : @drawable/ic_send_black_24dp}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now that we have the layout ready let's create our own custom message input view. Open the file &lt;code&gt;com.example.whatsappclone.ui.views.MessageInputView.kt&lt;/code&gt; and update it to match this content:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Next, open up &lt;code&gt;fragment_channel.xml&lt;/code&gt; and replace the &lt;code&gt;EditText&lt;/code&gt; node with this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/nparsons08/df9da66e2dc467587849f716d9f36980" rel="noopener noreferrer"&gt;https://gist.github.com/nparsons08/df9da66e2dc467587849f716d9f36980&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last, open up &lt;code&gt;ChannelFragment.kt&lt;/code&gt; and uncomment this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;//binding.messageInputView.setViewModel(viewModel!!, this)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now when you run your app, you’ll see a functional and much better-looking message input. Data binding is a compelling concept. You can learn more about it in &lt;a href="https://www.vogella.com/tutorials/AndroidDatabinding/article.html" rel="noopener noreferrer"&gt;this tutorial&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F588f579bde865b44a5e2e2b41499f58c%2Fimage4.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F588f579bde865b44a5e2e2b41499f58c%2Fimage4.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Channel List ViewHolder
&lt;/h2&gt;

&lt;p&gt;The Channel List already looks quite good. Let’s see if we can give it a little upgrade though. We’re going to use a custom &lt;code&gt;viewHolder&lt;/code&gt; to customize the design.&lt;/p&gt;

&lt;p&gt;Open the file &lt;code&gt;CustomChannelListItemViewHolder.kt&lt;/code&gt; and replace the empty viewholder with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The above code updated the date format to be closer to WhatsApp’s layout. To use this &lt;code&gt;viewHolder&lt;/code&gt;, we need to create a viewHolderFactory and apply it to the &lt;code&gt;ChannelList&lt;/code&gt; view. &lt;/p&gt;

&lt;p&gt;Open the file &lt;code&gt;CustomViewHolderFactory.kt&lt;/code&gt; and replace it with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As the last step, we need to tell the &lt;code&gt;ChannelList&lt;/code&gt; view about the custom view holder. Open &lt;code&gt;ChannelListFragment.kt&lt;/code&gt; and uncomment this line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// adapter.setViewHolderFactory(CustomViewHolderFactory())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run the app, the date format of the channel list will now look like WhatsApp’s format. If you got stuck at any point during this tutorial, note that you can always find the full source code on &lt;a href="https://github.com/GetStream/WhatsApp-Clone-Android" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fe4b66f6c802d36d4b15940f7f6bc0b99%2Fimage2.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstream-blog-v2.imgix.net%2Fblog%2Fwp-content%2Fuploads%2Fe4b66f6c802d36d4b15940f7f6bc0b99%2Fimage2.png%3Fauto%3Dcompress%252Cformat%26ixlib%3Dphp-1.2.1%26h%3D500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing the Stream Chat Android SDK
&lt;/h2&gt;

&lt;p&gt;The Views and ViewModels provided by &lt;a href="https://github.com/GetStream/stream-chat-android" rel="noopener noreferrer"&gt;stream-chat-android&lt;/a&gt; make it extremely simple to &lt;a href="https://getstream.io/chat/" rel="noopener noreferrer"&gt;add chat to your application&lt;/a&gt;. Depending on your use case, there are several options available to customize the UI.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The most common tweaks are handled using properties. This allows you to, for instance, change the message colors. The tutorial used this approach in &lt;code&gt;fragment_channel.xml&lt;/code&gt; to customize the colors and background:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;com.getstream.sdk.chat.view.MessageListView&lt;/span&gt;
            &lt;span class="na"&gt;android:id=&lt;/span&gt;&lt;span class="s"&gt;"@+id/messageList"&lt;/span&gt;
            &lt;span class="na"&gt;android:layout_width=&lt;/span&gt;&lt;span class="s"&gt;"match_parent"&lt;/span&gt;
            &lt;span class="na"&gt;android:layout_height=&lt;/span&gt;&lt;span class="s"&gt;"0dp"&lt;/span&gt;
            &lt;span class="na"&gt;android:layout_marginBottom=&lt;/span&gt;&lt;span class="s"&gt;"10dp"&lt;/span&gt;
            &lt;span class="na"&gt;android:background=&lt;/span&gt;&lt;span class="s"&gt;"@color/channel_background"&lt;/span&gt;
            &lt;span class="na"&gt;app:layout_constraintBottom_toTopOf=&lt;/span&gt;&lt;span class="s"&gt;"@+id/messageInputView"&lt;/span&gt;
            &lt;span class="na"&gt;app:layout_constraintEnd_toEndOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
            &lt;span class="na"&gt;app:layout_constraintStart_toStartOf=&lt;/span&gt;&lt;span class="s"&gt;"parent"&lt;/span&gt;
            &lt;span class="na"&gt;app:layout_constraintTop_toBottomOf=&lt;/span&gt;&lt;span class="s"&gt;"@+id/toolbar"&lt;/span&gt;
            &lt;span class="na"&gt;app:streamMessageBackgroundColorMine=&lt;/span&gt;&lt;span class="s"&gt;"@color/message_yours"&lt;/span&gt;
            &lt;span class="na"&gt;app:streamMessageBackgroundColorTheirs=&lt;/span&gt;&lt;span class="s"&gt;"@color/message_theirs"&lt;/span&gt;
            &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The views allow you to specify your layout, enabling you to make simple layout changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For more considerable UI changes, you can use your &lt;code&gt;ViewHolder&lt;/code&gt;. In this tutorial, we used that approach for customizing the &lt;code&gt;ChannelListView&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alternatively, you can also use the low-level client to build your UI or your view models. In this tutorial, we did that for the &lt;code&gt;MessageInputView&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these 4 levels of customizations, you can build any chat or messaging experience. The &lt;a href="https://getstream.io/chat/docs/kotlin/" rel="noopener noreferrer"&gt;Android Chat Docs&lt;/a&gt; cover the chat SDK in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed this tutorial. It’s incredible how quickly you can build an app like WhatsApp these days. Kotlin and Android Jetpack have been a significant step forward for the Android ecosystem. Looking at a successful app like WhatsApp and trying to build it is a great way to learn. For a real app, you’ll, of course, want to come up with something new and different. You can use a similar approach to build any chat or messaging experience. Here are a few links to help out if you got stuck along the way or want to learn more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/GetStream/WhatsApp-Clone-Android" rel="noopener noreferrer"&gt;The WhatsApp Clone Github Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getstream.io/tutorials/android-chat/#java" rel="noopener noreferrer"&gt;Stream’s Android Chat Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.raywenderlich.com/6014-the-navigation-architecture-component-tutorial-getting-started" rel="noopener noreferrer"&gt;Navigation Component Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codelabs.developers.google.com/codelabs/advanced-android-kotlin-training-testing-basics/#0" rel="noopener noreferrer"&gt;Testing Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.android.com/topic/libraries/data-binding/two-way" rel="noopener noreferrer"&gt;Data binding Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://android.jlelse.eu/how-to-remove-all-from-your-kotlin-code-87dc2c9767fb" rel="noopener noreferrer"&gt;Kotlin tips for removing !!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stream also has tutorials available for &lt;a href="https://getstream.io/tutorials/ios-chat/" rel="noopener noreferrer"&gt;iOS Chat&lt;/a&gt;, &lt;a href="https://getstream.io/chat/react-chat/tutorial/" rel="noopener noreferrer"&gt;React Chat&lt;/a&gt;, and &lt;a href="https://getstream.io/chat/react-native-chat/tutorial/" rel="noopener noreferrer"&gt;React Native Chat&lt;/a&gt; in case you need to support multiple platforms. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Part 2 of this tutorial is expected to go live in February and will explain how to add video and voice calls to your app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Happy Chatting!&lt;/p&gt;

</description>
      <category>kotlin</category>
      <category>android</category>
      <category>chat</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Styled Components vs CSS</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Mon, 16 Dec 2019 18:44:13 +0000</pubDate>
      <link>https://dev.to/tschellenbach/styled-components-vs-css-58mf</link>
      <guid>https://dev.to/tschellenbach/styled-components-vs-css-58mf</guid>
      <description>&lt;p&gt;Trying to figure out the distribution between CSS fans and styled-components. Let us know which one you prefer:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GetStream/stream-chat-react/issues/100"&gt;https://github.com/GetStream/stream-chat-react/issues/100&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>react</category>
    </item>
    <item>
      <title>React Hooks</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Tue, 10 Dec 2019 22:24:10 +0000</pubDate>
      <link>https://dev.to/tschellenbach/react-hooks-1ogn</link>
      <guid>https://dev.to/tschellenbach/react-hooks-1ogn</guid>
      <description>&lt;p&gt;Curious how everyone's experiences have been using React Hooks. Do you prefer writing functional components instead of using classes? Are you still using Redux, or relying on custom hooks?&lt;/p&gt;

</description>
      <category>react</category>
    </item>
    <item>
      <title>A New Kind of Android Fragmentation</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Tue, 29 Oct 2019 13:44:58 +0000</pubDate>
      <link>https://dev.to/tschellenbach/a-new-kind-of-android-fragmentation-2hgp</link>
      <guid>https://dev.to/tschellenbach/a-new-kind-of-android-fragmentation-2hgp</guid>
      <description>&lt;p&gt;It has been about 5 years since I have been able to spend a dedicated chunk of time working solely on Android development. One of our competitors shut down their product a few months ago, causing a huge inflow of customers all asking for an &lt;a href="https://getstream.io/tutorials/android-chat/#java"&gt;Android Chat SDK&lt;/a&gt;. Unfortunately, our Android team was behind on schedule. #startuplife Long story short, I had the pleasure of doing some Android development again.&lt;/p&gt;

&lt;p&gt;It was cool to see how much the ecosystem improved. The constraint layout is really easy to work with and much more performant than the older layouts. The new livedata system reduces quite a bit of boilerplate code. Room is a nice abstraction over SQLlite and the concept of viewmodels (while simple) is quite elegant. &lt;/p&gt;

&lt;p&gt;One type of fragmentation became much worse though. If you’re a library author you now have to think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java or Kotlin&lt;/li&gt;
&lt;li&gt;Java Callbacks, Android RX observables and/or Kotlin Coroutines&lt;/li&gt;
&lt;li&gt;Architecture components: MVVM, MVI, MVP, MVP or MVC?&lt;/li&gt;
&lt;li&gt;Proguard&lt;/li&gt;
&lt;li&gt;AndroidX&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes, you can argue that Java and Kotlin are compatible. At the end of the day, you still have 2 sets of docs and halve the people that use your library won’t be happy with the language you choose. If you look at the stats Kotlin still seems much smaller for new apps than Java: &lt;a href="https://www.appbrain.com/stats/libraries/details/kotlin/kotlin"&gt;https://www.appbrain.com/stats/libraries/details/kotlin/kotlin&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;It’s cool to see how Room and Retrofit deal with the callback vs observable difference. If you look at iOS development though there is much less fragmentation. &lt;/p&gt;

&lt;p&gt;Android development has improved a lot over the last 5 years. For a library author fragmentation became worse though. I wonder why Google has this wait and see attitude instead of just ensuring that there is 1 best way to do all of these things...&lt;/p&gt;

</description>
      <category>android</category>
      <category>fragmentation</category>
      <category>kotlin</category>
      <category>java</category>
    </item>
    <item>
      <title>Thoughts on Layer’s API Shutdown</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Thu, 25 Jul 2019 21:38:43 +0000</pubDate>
      <link>https://dev.to/tschellenbach/thoughts-on-layer-s-api-shutdown-1fan</link>
      <guid>https://dev.to/tschellenbach/thoughts-on-layer-s-api-shutdown-1fan</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgetstream-blog.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F2019%2F07%2Fimage1.jpg%3Fw%3D1024%26h%3D1024" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgetstream-blog.imgix.net%2Fblog%2Fwp-content%2Fuploads%2F2019%2F07%2Fimage1.jpg%3Fw%3D1024%26h%3D1024" alt="Layer Chat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Over the past days, we’ve been happily &lt;a href="https://getstream.io/blog/layer-shutting-down-all-chat-operations/" rel="noopener noreferrer"&gt;migrating&lt;/a&gt; disgruntled &lt;a href="https://layer.com/" rel="noopener noreferrer"&gt;Layer&lt;/a&gt; customers over to &lt;a href="https://getstream.io/chat/" rel="noopener noreferrer"&gt;Stream&lt;/a&gt;. The surprising announcement of the shutdown of their API on October 30th has been pretty amazing for our growth.&lt;/p&gt;

&lt;p&gt;However, as a developer, it annoys me to see a company get bought up and then have their product shut down in such a short amount of time. All those customers placed their trust in a product, a team, and a vision. Shutting it down, especially so soon after acquiring it, seems and feels like a betrayal to those customers. I personally feel that by acquiring a company and customer base, you have an ethical obligation to do everything you can to continue to service those customers, or at least provide a nice exit strategy for them. &lt;/p&gt;

&lt;p&gt;For context, here’s the full email from Layer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We are Sunsetting the Layer Platform&lt;/p&gt;

&lt;p&gt;We will be sunsetting the Layer Platform and API on October 30th, 2019.&lt;/p&gt;

&lt;p&gt;The platform, features, and functionality of our service will continue with no change from what it is today until that date, including access to export your data.&lt;/p&gt;

&lt;p&gt;After October 30th, 2019, the Layer Platform and all services associated with Layer will be shut down in their entirety.&lt;/p&gt;

&lt;p&gt;Our priorities are to maintain system uptime and ensure you are able to move off the platform as seamlessly as possible. No features or updates to our SDKs will be published and bugs not related to service uptime or core functionality may not be resolved.&lt;/p&gt;

&lt;p&gt;There will be no part of Layer online past this date and no option to continue leveraging the Layer backend services. Similarly, there is no way to take the Layer backend service and self-host it or for us to provide it to you.&lt;/p&gt;

&lt;p&gt;Why are we sunsetting the Layer Platform?&lt;/p&gt;

&lt;p&gt;1) We do not have a team in place to properly diagnose and resolve the volume of bugs and issues that are arising from our customer base.&lt;/p&gt;

&lt;p&gt;2) We do not have a team in place to keep our SDKs up to date, the reality is that critical bugs and failures that we can not resolve are inevitable, sooner or later.&lt;/p&gt;

&lt;p&gt;3) While the security built into the Layer platform and organization very much persists, we do not have the team in place to adequately assist you in completing vendor audits or providing verifications as needed.&lt;/p&gt;

&lt;p&gt;4) Our key hire running all server operations and infrastructure passed away suddenly and unexpectedly very recently. While we have plans to get additional help there for the remainder of the Layer service, we do not have a sustainable path to ensure system uptime and reliability long term.&lt;/p&gt;

&lt;p&gt;5) Barring all of the above, Layer infrastructure costs are both very high and very fixed. We are currently operating the Layer platform at an unsustainable loss.&lt;/p&gt;

&lt;p&gt;Closing things Out&lt;/p&gt;

&lt;p&gt;On the business side, we definitely messed up and have learned a lot in the process. I know this likely puts you in an extremely tough position and I apologize that I did not have better news to share with you.&lt;/p&gt;

&lt;p&gt;I also recognize the timeline is very tight, but it is that way for our mutual safety. What I would not want to happen is that I say we can continue to support you for 6 months and then 4 months from now, we have a critical outage that we can just not resolve with our team. That would put us both in a much, much worse position.&lt;/p&gt;

&lt;p&gt;If I can assist in recommending a competitive service, please let me know the use-cases that are most relevant for you.&lt;/p&gt;

&lt;p&gt;Thank you,&lt;/p&gt;

&lt;p&gt;Shaun VanWeelden&lt;br&gt;
Head of Layer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Migrating from one chat provider to another is rather cumbersome. Stream is trying to make it as easy as possible and offers a fully automated import of Layer data. Have a look at this Github Repo that explains how to &lt;a href="https://github.com/GetStream/layer-migration" rel="noopener noreferrer"&gt;export your Layer data and migrate to Stream&lt;/a&gt;. So, in theory, you can migrate in a couple of days. Three months feels like an awfully short time though. The dev teams might be busy with other projects, and perhaps they aren’t even actively working on some of these apps.&lt;/p&gt;

&lt;p&gt;When Parse shutdown there was at least a clear migration path to competing services. They also provided an open-source solution. It makes sense that Layer doesn’t do that since their core product seems to have a lot of performance, cost and stability issues. Still, a prescribed path for migrating to other services would be ideal.&lt;/p&gt;

&lt;p&gt;From the outside you wonder if the shutdown of Layer is caused by chasing hypergrowth. Layer raised $29.5 million and initially started out selling their product to developers and product owners. Once they found out that they couldn’t create the hyper-growth that VCs look for, they pivoted towards a more customer support/marketing vertical. Perhaps many of the technical debt and cost issues with their infrastructure could have been avoided with a slightly less aggressive growth strategy.&lt;/p&gt;

&lt;p&gt;This shutdown reminded me a bit of the Parse story, or the Keen and Travis acquisition where most/all of the dev team were replaced. &lt;/p&gt;

&lt;p&gt;Here’s a pledge from Stream, as long as I can do something about it we will not:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Raise overly large funding rounds which put the sustainability of the company at risk if crazy growth targets are not hit&lt;/li&gt;
&lt;li&gt;Sell to companies that will shut down the product or strip down the development team&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, I don’t want to be overly harsh with these companies. Sometimes you just don’t have any good options on the table. Especially in this case with one of Layer's team members tragically passing away. There are always events that you can't anticipate. With that caveat in mind, my co-founder Tommaso and I will do our utmost to focus on sustainable growth and ensure that the APIs continue to be available.&lt;/p&gt;

</description>
      <category>chat</category>
    </item>
    <item>
      <title>The best dev community</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Tue, 16 Jul 2019 17:50:59 +0000</pubDate>
      <link>https://dev.to/tschellenbach/the-best-dev-community-4fgi</link>
      <guid>https://dev.to/tschellenbach/the-best-dev-community-4fgi</guid>
      <description>&lt;p&gt;Dev.to should clearly win the Noonies award for best dev community:  &lt;a href="https://noonies.hackernoon.com/award/cjxr8yn9weqhp0b129w4ygn5h"&gt;https://noonies.hackernoon.com/award/cjxr8yn9weqhp0b129w4ygn5h&lt;/a&gt;&lt;/p&gt;

</description>
      <category>community</category>
      <category>noonies</category>
    </item>
    <item>
      <title>Layer webhook issues?</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Mon, 24 Jun 2019 19:30:54 +0000</pubDate>
      <link>https://dev.to/tschellenbach/layer-webhook-issues-4fa7</link>
      <guid>https://dev.to/tschellenbach/layer-webhook-issues-4fa7</guid>
      <description>&lt;p&gt;Is anyone else experiencing issues with Layer webhooks? One of our customers syncs their Layer chat messages to Stream via webhooks. It seems that today (June 24th) all webhooks from the last 2 weeks were repeated. The end result is that they are sending push notifications/emails to their userbase repeatedly. So far Layer support has unfortunately been unresponsive on this issue. Not quite sure what's going on. &lt;/p&gt;

</description>
      <category>api</category>
      <category>stability</category>
      <category>layer</category>
    </item>
    <item>
      <title>Redux in 2019?</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Wed, 12 Jun 2019 16:42:42 +0000</pubDate>
      <link>https://dev.to/tschellenbach/redux-in-2019-22np</link>
      <guid>https://dev.to/tschellenbach/redux-in-2019-22np</guid>
      <description>&lt;p&gt;I noticed that many new projects adopt either GraphQL and/or React Hooks. Neither of these solve the same issues as Redux... On the other hand it does seem to reduce the need for using Redux. Here at Stream we're still using redux... &lt;/p&gt;

&lt;p&gt;How do you all feel about Redux in 2019, do you think it's still useful/relevant?&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
    </item>
    <item>
      <title>Discord vs Slack</title>
      <dc:creator>Thierry</dc:creator>
      <pubDate>Thu, 06 Jun 2019 03:13:55 +0000</pubDate>
      <link>https://dev.to/tschellenbach/discord-vs-slack-1he4</link>
      <guid>https://dev.to/tschellenbach/discord-vs-slack-1he4</guid>
      <description>&lt;p&gt;As far as I know both Discord and Slack are using Electron. Somehow Discord's app feels much faster and responsive. Does anybody have some insights into how they achieved this? &lt;/p&gt;

</description>
      <category>electron</category>
      <category>react</category>
    </item>
  </channel>
</rss>
