profile
viewpoint

raywenderlich/c-sharp-style-guide 320

C# Style Guide for Unity Tutorials

raywenderlich/android-bootcamp-summer-2020 11

Homework solutions for the Android Bootcamp, class of Summer 2020.

raywenderlich/DadJokes 11

A way to improve the programmer's day.

raywenderlich/CircuitRacer 10

CircuitRacer game for iOS Games by Tutorials.

raywenderlich/atdd-materials 9

The projects and the materials that accompany the Android Test-Driven Development by Tutorials book

raywenderlich/ControllingSource 2

Beginning source control in Xcode 5 sample project

raywenderlich/ana-materials 1

The projects and materials that accompany the Advanced Android App Architecture book

raywenderlich/Catstagram 1

Sample project for intermediate debugging video series

raywenderlich/deckle-sublime-text-plugin 1

A plugin for Sublime Text that opens the currently edited markdown file in Deckle.

raywenderlich/aa-materials 0

The projects and the materials that accompany the Android Apprentice book.

startedraywenderlich/ia-materials

started time in an hour

startedraywenderlich/swift-algorithm-club

started time in 3 hours

fork unalCe/swift-algorithm-club

Algorithms and data structures in Swift, with explanations!

fork in 3 hours

startedraywenderlich/swift-algorithm-club

started time in 3 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.onboarding++import android.content.Context+import android.content.Intent+import android.os.Bundle+import android.view.LayoutInflater+import android.view.ViewGroup+import androidx.fragment.app.FragmentActivity+import androidx.lifecycle.lifecycleScope+import androidx.preference.PreferenceManager+import androidx.recyclerview.widget.RecyclerView+import com.raywenderlich.android.tacotuesday.MainActivity+import com.raywenderlich.android.tacotuesday.R+import com.raywenderlich.android.tacotuesday.databinding.ActivityOnboardingBinding+import com.raywenderlich.android.tacotuesday.databinding.ItemOnboardingBinding+import kotlinx.coroutines.*++class OnboardingActivity : FragmentActivity() {++  private lateinit var binding: ActivityOnboardingBinding++  override fun onCreate(savedInstanceState: Bundle?) {+    super.onCreate(savedInstanceState)++    binding = ActivityOnboardingBinding.inflate(layoutInflater)+    setContentView(binding.root)+    val pagerAdapter = OnboardingPagerAdapter()+    binding.onboardingPager.adapter = pagerAdapter++    lifecycleScope.launch(Dispatchers.IO) {+      val options = resources.getStringArray(R.array.pop_up_options)+      while (isActive) {+        delay(5000) // 5 seconds++        withContext(Dispatchers.Main) {+          if (binding.onboardingPager.currentItem == NUM_PAGES - 1) {+            MainActivity.startActivity(this@OnboardingActivity)+            this.cancel()+          } else {+            binding.onboardingPager.currentItem = binding.onboardingPager.currentItem + 1+          }+        }+      }+    }++    val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)+    with(sharedPref.edit()) {+      putBoolean("onboarding", false)+      apply()+    }+  }++  override fun onBackPressed() {+    if (binding.onboardingPager.currentItem == 0) {+      // If the user is currently looking at the first step, allow the system to handle the+      // Back button. This calls finish() on this activity and pops the back stack.+      super.onBackPressed()+    } else {+      // Otherwise, select the previous step.+      binding.onboardingPager.currentItem = binding.onboardingPager.currentItem - 1

binding.onboardingPager.currentItem--

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.discover++import androidx.hilt.Assisted+import androidx.hilt.lifecycle.ViewModelInject+import androidx.lifecycle.SavedStateHandle+import androidx.lifecycle.ViewModel+import androidx.lifecycle.viewModelScope+import com.raywenderlich.android.tacotuesday.data.Recipe+import com.raywenderlich.android.tacotuesday.data.RecipeRepository+import com.raywenderlich.android.tacotuesday.shared.TryDiscardRecipeViewModel+import com.raywenderlich.android.tacotuesday.shared.TryDiscardRecipeViewModelImpl+import kotlinx.coroutines.Dispatchers+import kotlinx.coroutines.Job+import kotlinx.coroutines.delay+import kotlinx.coroutines.launch++class DiscoverViewModel @ViewModelInject constructor(+    private val recipeRepository: RecipeRepository,+    @Assisted savedStateHandle: SavedStateHandle+) : ViewModel(), TryDiscardRecipeViewModel by TryDiscardRecipeViewModelImpl(+    recipeRepository) {++  private val recipe = savedStateHandle.getLiveData<Recipe>(SAVED_STATE_KEY)+  val nextRecipe = recipe++  private var fetchTacoJob: Job? = null++  fun fetchRandomTaco() {+    // Reset the timer if this is called again through requesting a new recipe+    fetchTacoJob?.cancel()++    viewModelScope.launch(Dispatchers.IO) {+      recipeRepository.randomTacoRecipe()?.let {+        recipe.postValue(it)+      }+    }++    fetchTacoJob = viewModelScope.launch(Dispatchers.IO) {+      delay(15000) // 15 seconds

If this considers user's activity with thumbs up/down buttons only, I would suggest to use countdown on a background thread instead of setting the delay. If you detect an activity on the buttons in less than 10/15 sec, you can reset the countdown. In this case, you will call fetchRandomTaco() only when it is necessary. I'm a bit concerned about this approach with the delay because you are not canceling the action when you detect the user's activity during the delay. There is a possibility to reach a situation with more parallel fetchRandomTaco() calls at the same time.

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+# Taco Tuesday++This project is the sample project for the RW Android Accessibility book. It is An app for

"An" uppercased on purpose or it's a typo?

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.data++import com.raywenderlich.android.tacotuesday.R++/**+ * All recipes are from https://github.com/sinker/tacofancy+ */+object DataFactory {+

Reaaaaally nice data 🌮

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.tryIt++import android.os.Bundle+import android.view.LayoutInflater+import android.view.View+import android.view.ViewGroup+import androidx.fragment.app.Fragment+import androidx.fragment.app.viewModels+import androidx.lifecycle.Observer+import androidx.lifecycle.viewModelScope+import androidx.recyclerview.widget.ItemTouchHelper+import androidx.recyclerview.widget.LinearLayoutManager+import com.google.android.material.snackbar.Snackbar+import com.raywenderlich.android.tacotuesday.data.Recipe+import com.raywenderlich.android.tacotuesday.databinding.FragmentTryItRecipesListBinding+import dagger.hilt.android.AndroidEntryPoint++@AndroidEntryPoint+class TryItRecipesFragment : Fragment() {++  private lateinit var binding: FragmentTryItRecipesListBinding+  private val viewModel: TryItRecipesViewModel by viewModels()++  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,+      savedInstanceState: Bundle?): View? {+    binding = FragmentTryItRecipesListBinding.inflate(+        layoutInflater, container, false)++    val recipeRecyclerViewAdapter = TryItRecipesRecyclerViewAdapter(::discard, ::toggleHasMade)+    with(binding.root) {+      layoutManager = LinearLayoutManager(context)+      adapter = recipeRecyclerViewAdapter+    }++    ItemTouchHelper(SwipeToDiscardCallback(recipeRecyclerViewAdapter, ::discard))+        .attachToRecyclerView(binding.root)++    with(viewModel) {+      savedRecipes.observe(viewLifecycleOwner, Observer {+        (binding.root.adapter as TryItRecipesRecyclerViewAdapter).submitList(it)+      })+    }+    return binding.root+  }++  private fun discard(recipe: Recipe) {+    viewModel.discardRecipe(recipe, viewModel.viewModelScope)+    Snackbar.make(binding.root,+        "Note deleted",

This should be extracted to strings.xml. Everything what is presented to the user should be inside the .xml. In this case we will not skip any text when translating the app. I've seen more strings inside the project which are not extracted. Please check the entire project :] Thanks

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.tryIt++import android.graphics.Canvas+import android.view.View+import androidx.recyclerview.widget.ItemTouchHelper+import androidx.recyclerview.widget.RecyclerView+import com.raywenderlich.android.tacotuesday.data.Recipe+++class SwipeToDiscardCallback(+    private val recipeRecyclerViewAdapter: TryItRecipesRecyclerViewAdapter,+    private val discard: (Recipe) -> Unit+) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {++  override fun onMove(+      recyclerView: RecyclerView,+      viewHolder: RecyclerView.ViewHolder,+      target: RecyclerView.ViewHolder): Boolean {+    return false+  }++  override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {+    val itemPosition = viewHolder.adapterPosition+    val recipe: Recipe = recipeRecyclerViewAdapter.getRecipeAtPosition(itemPosition)++    discard(recipe)+  }++  override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {+    if (viewHolder != null) {+      val foregroundView: View = (viewHolder as TryItRecipesRecyclerViewAdapter.ViewHolder).viewForeground+      ItemTouchHelper.Callback.getDefaultUIUtil().onSelected(foregroundView)

I would extract "ItemTouchHelper.Callback.getDefaultUIUtil()" to a lazy val.

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.settings++import android.os.Bundle+import androidx.preference.PreferenceFragmentCompat+import com.raywenderlich.android.tacotuesday.R++class SettingsFragment : PreferenceFragmentCompat() {++  override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {+    setPreferencesFromResource(+        R.xml.root_preferences, rootKey)

Please move this in the line above. "R.xml.root_preferences, rootKey)". Sorry, OCD 🤣

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.data++import android.content.Context+import androidx.room.Database+import androidx.room.Room+import androidx.room.RoomDatabase+import androidx.sqlite.db.SupportSQLiteDatabase+import java.util.concurrent.Executors++@Database(entities = arrayOf(Recipe::class), version = 1, exportSchema = false)+public abstract class RecipeRoomDatabase : RoomDatabase() {

Redundant "public"

Manda94

comment created time in 5 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.onboarding++import android.content.Context+import android.content.Intent+import android.os.Bundle+import android.view.LayoutInflater+import android.view.ViewGroup+import androidx.fragment.app.FragmentActivity+import androidx.lifecycle.lifecycleScope+import androidx.preference.PreferenceManager+import androidx.recyclerview.widget.RecyclerView+import com.raywenderlich.android.tacotuesday.MainActivity+import com.raywenderlich.android.tacotuesday.R+import com.raywenderlich.android.tacotuesday.databinding.ActivityOnboardingBinding+import com.raywenderlich.android.tacotuesday.databinding.ItemOnboardingBinding+import kotlinx.coroutines.*++class OnboardingActivity : FragmentActivity() {++  private lateinit var binding: ActivityOnboardingBinding++  override fun onCreate(savedInstanceState: Bundle?) {+    super.onCreate(savedInstanceState)++    binding = ActivityOnboardingBinding.inflate(layoutInflater)+    setContentView(binding.root)+    val pagerAdapter = OnboardingPagerAdapter()+    binding.onboardingPager.adapter = pagerAdapter++    lifecycleScope.launch(Dispatchers.IO) {+      val options = resources.getStringArray(R.array.pop_up_options)+      while (isActive) {+        delay(5000) // 5 seconds++        withContext(Dispatchers.Main) {+          if (binding.onboardingPager.currentItem == NUM_PAGES - 1) {+            MainActivity.startActivity(this@OnboardingActivity)+            this.cancel()+          } else {+            binding.onboardingPager.currentItem = binding.onboardingPager.currentItem + 1

I would use "binding.onboardingPager.currentItem++".

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.detail++import android.os.Bundle+import android.text.method.LinkMovementMethod+import android.view.LayoutInflater+import android.view.View+import android.view.ViewGroup+import androidx.core.content.ContextCompat+import androidx.core.content.res.ResourcesCompat+import androidx.fragment.app.Fragment+import androidx.fragment.app.viewModels+import androidx.lifecycle.Observer+import androidx.lifecycle.viewModelScope+import com.raywenderlich.android.tacotuesday.R+import com.raywenderlich.android.tacotuesday.data.Recipe+import com.raywenderlich.android.tacotuesday.databinding.FragmentRecipeDetailBinding+import dagger.hilt.android.AndroidEntryPoint+import io.noties.markwon.AbstractMarkwonPlugin+import io.noties.markwon.Markwon+import io.noties.markwon.core.MarkwonTheme++@AndroidEntryPoint+class RecipeDetailFragment : Fragment() {++  private lateinit var binding: FragmentRecipeDetailBinding+  private val viewModel: RecipeDetailViewModel by viewModels()+  private val markwon by getMarkwon()++  override fun onCreateView(+      inflater: LayoutInflater,+      container: ViewGroup?,+      savedInstanceState: Bundle?+  ): View? {+    binding = FragmentRecipeDetailBinding.inflate(layoutInflater, container, false)+    viewModel.recipe.observe(viewLifecycleOwner, Observer { recipe ->+      showRecipeDetails(recipe)+      if (recipe.wantsToTry) {+        showEditableFields(recipe)+      } else {+        hideEditableFields(recipe)+      }+    })+    return binding.root+  }++  private fun showRecipeDetails(recipe: Recipe) = with(binding) {+    recipeDetailRecipe.text = recipe.recipe.toMarkdownOrDefaultText(+        getString(R.string.recipe_detail_recipe))+    recipeDetailRecipe.movementMethod = LinkMovementMethod.getInstance()

I would move "movementMethod = LinkMovementMethod.getInstance()" inside an extension on a view like toMarkdownOrDefaultText() just to reduce the amount of code. Just a personal preference

Manda94

comment created time in 5 hours

Pull request review commentraywenderlich/acca-materials

Adding 02-hello-accessibility

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday++import android.app.Application+import android.content.Context+import androidx.test.runner.AndroidJUnitRunner+import dagger.hilt.android.testing.HiltTestApplication++class TestRunner : AndroidJUnitRunner() {++  override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application {+    return super.newApplication(cl, HiltTestApplication::class.java.name, context)

"return {}" can be replaced with "="

Manda94

comment created time in 5 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */+package com.raywenderlich.android.tacotuesday.shared++import android.content.Context+import android.graphics.Canvas+import android.graphics.Rect+import android.os.Bundle+import android.util.AttributeSet+import android.view.KeyEvent+import android.view.MotionEvent+import android.view.View+import androidx.annotation.DrawableRes+import androidx.core.content.res.ResourcesCompat+import androidx.core.content.res.getResourceIdOrThrow+import androidx.core.view.ViewCompat+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat+import androidx.customview.widget.ExploreByTouchHelper+import com.raywenderlich.android.tacotuesday.R+++class CustomRatingBar @JvmOverloads constructor(+    context: Context,+    attrs: AttributeSet? = null,+    defStyleAttr: Int = 0+) : View(context, attrs, defStyleAttr) {++  @DrawableRes+  private val drawableResUnchecked: Int+  @DrawableRes+  private val drawableResChecked: Int+  private val label: String+  var rating = 0+    set(value) {+      field = value+      invalidate()+    }+  private val screenDensity = context.resources.displayMetrics.density+  private val diameter = (iconSizeDp * screenDensity).toInt()+  private val spacingWidth = (spacingWidthDp * screenDensity).toInt()+  private val maxRating = 5+  private val rectangles: Array<Rect> = Array(maxRating) { i ->+    val yFactor = i / maxRating+    val xFactor = i % maxRating+    val x = paddingLeft + xFactor * (diameter + spacingWidth)+    val y = paddingTop + yFactor * (diameter + spacingWidth)+    Rect(x, y, x + diameter, y + diameter)+  }+  private val exploreByTouchHelper = RatingExploreByTouchHelper(this)++  init {+    context.theme.obtainStyledAttributes(+        attrs,+        R.styleable.CustomRatingBar,+        0, 0).apply {++      try {+        drawableResChecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableChecked)+        drawableResUnchecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableUnchecked)+        label = getString(R.styleable.CustomRatingBar_ratingLabel) ?: ""+      } finally {+        recycle()+      }+    }+    isFocusable = true+    ViewCompat.setAccessibilityDelegate(this, exploreByTouchHelper)+    invalidate()+  }++  override fun dispatchHoverEvent(event: MotionEvent?): Boolean {+    return (event?.let { exploreByTouchHelper.dispatchHoverEvent(it) } ?: run { false }+        || super.dispatchHoverEvent(event))+  }++  override fun dispatchKeyEvent(event: KeyEvent?): Boolean {+    return (event?.let { exploreByTouchHelper.dispatchKeyEvent(it) } ?: run { false }+        || super.dispatchKeyEvent(event))+  }++  override fun onFocusChanged(gainFocus: Boolean, direction: Int, previouslyFocusedRect: Rect?) {+    super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)+    exploreByTouchHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect)+  }++  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {+    super.onMeasure(widthMeasureSpec, heightMeasureSpec)+    val width: Int = maxRating * (diameter + spacingWidth) - spacingWidth + paddingLeft + paddingRight+    val height: Int = diameter + paddingTop + paddingBottom++    setMeasuredDimension(width, height)+  }++  override fun onDraw(canvas: Canvas) {+    diameter / 2.toFloat()+    for (i in 0 until maxRating) {+      val image = if (i >= rating) {+        ResourcesCompat.getDrawable(resources, drawableResUnchecked, context.theme)+      } else {+        ResourcesCompat.getDrawable(resources, drawableResChecked, context.theme)+      }+      image!!.setBounds(rectangles[i].left, rectangles[i].top, rectangles[i].right,+          rectangles[i].bottom)+      image.draw(canvas)+    }+  }++  override fun onTouchEvent(event: MotionEvent): Boolean {+    when (event.action) {+      MotionEvent.ACTION_DOWN -> return true+      MotionEvent.ACTION_UP -> {+        val selectedIndex = findRatingAtPoint(event.x, event.y)+        onSelected(selectedIndex)+        return true+      }+    }+    return super.onTouchEvent(event)+  }++  protected fun onSelected(selectedIndex: Int) {+    if (selectedIndex == INVALID_VALUE) return+    rating = selectedIndex + 1+    invalidate()+  }++  private fun findRatingAtPoint(x: Float, y: Float): Int {+    var selectedIndex = INVALID_VALUE+    for (i in 0 until maxRating) {+      if (rectangles[i].contains(x.toInt(), y.toInt())) {+        selectedIndex = i+        break+      }+    }+    return selectedIndex+  }++  companion object {+    const val INVALID_VALUE = -1+    const val spacingWidthDp = 10f+    const val iconSizeDp = 48f+  }++  inner class RatingExploreByTouchHelper(host: View) : ExploreByTouchHelper(host) {++    override fun getVirtualViewAt(x: Float, y: Float): Int {+      val index = findRatingAtPoint(x, y)+      return if (index == INVALID_VALUE) INVALID_ID else index+    }++    override fun getVisibleVirtualViews(virtualViewIds: MutableList<Int>?) {+      for (i in 0 until maxRating) virtualViewIds?.add(i)+    }++    override fun onPerformActionForVirtualView(+        virtualViewId: Int,+        action: Int,+        arguments: Bundle?+    ): Boolean {+      when (action) {+        AccessibilityNodeInfoCompat.ACTION_CLICK -> {

I think you can use if statement here because you have only one action ... : Boolean = if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) { onSelected(virtualViewId) true } else { false }

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.tryIt++import android.os.Bundle+import android.view.LayoutInflater+import android.view.View+import android.view.ViewGroup+import androidx.fragment.app.Fragment+import androidx.fragment.app.viewModels+import androidx.lifecycle.Observer+import androidx.lifecycle.viewModelScope+import androidx.recyclerview.widget.ItemTouchHelper+import androidx.recyclerview.widget.LinearLayoutManager+import com.google.android.material.snackbar.Snackbar+import com.raywenderlich.android.tacotuesday.data.Recipe+import com.raywenderlich.android.tacotuesday.databinding.FragmentTryItRecipesListBinding+import dagger.hilt.android.AndroidEntryPoint++@AndroidEntryPoint+class TryItRecipesFragment : Fragment() {++  private lateinit var binding: FragmentTryItRecipesListBinding+  private val viewModel: TryItRecipesViewModel by viewModels()++  override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,+      savedInstanceState: Bundle?): View? {+    binding = FragmentTryItRecipesListBinding.inflate(+        layoutInflater, container, false)++    val recipeRecyclerViewAdapter = TryItRecipesRecyclerViewAdapter(::discard, ::toggleHasMade)+    with(binding.root) {+      layoutManager = LinearLayoutManager(context)+      adapter = recipeRecyclerViewAdapter+      itemAnimator = null+    }++    ItemTouchHelper(SwipeToDiscardCallback(recipeRecyclerViewAdapter, ::discard))+        .attachToRecyclerView(binding.root)++    with(viewModel) {+      savedRecipes.observe(viewLifecycleOwner, Observer {+        (binding.root.adapter as TryItRecipesRecyclerViewAdapter).submitList(it)+      })+    }+    return binding.root+  }++  private fun discard(recipe: Recipe) {+    viewModel.discardRecipe(recipe, viewModel.viewModelScope)+    Snackbar.make(binding.root,+        "Note deleted",

I did a duplicate comment on this in the chapter 02. Sorry

Manda94

comment created time in 3 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.tryIt++import android.view.LayoutInflater+import android.view.ViewGroup+import androidx.core.view.ViewCompat+import androidx.navigation.findNavController+import androidx.recyclerview.widget.DiffUtil+import androidx.recyclerview.widget.ListAdapter+import androidx.recyclerview.widget.RecyclerView+import com.google.android.material.dialog.MaterialAlertDialogBuilder+import com.raywenderlich.android.tacotuesday.R+import com.raywenderlich.android.tacotuesday.data.Recipe+import com.raywenderlich.android.tacotuesday.databinding.ItemTryItRecipeBinding++class TryItRecipesRecyclerViewAdapter(+    private val onDiscardRecipe: (Recipe) -> Unit,+    private val toggleHasMade: (Recipe) -> Unit+) : ListAdapter<Recipe, TryItRecipesRecyclerViewAdapter.ViewHolder>(RecipeDiffCallback()) {++  init {+    setHasStableIds(true)+  }++  override fun getItemId(position: Int): Long {+    return getItem(position).id

=

Manda94

comment created time in 3 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */+package com.raywenderlich.android.tacotuesday.shared++import android.content.Context+import android.graphics.Canvas+import android.graphics.Rect+import android.os.Bundle+import android.util.AttributeSet+import android.view.KeyEvent+import android.view.MotionEvent+import android.view.View+import androidx.annotation.DrawableRes+import androidx.core.content.res.ResourcesCompat+import androidx.core.content.res.getResourceIdOrThrow+import androidx.core.view.ViewCompat+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat+import androidx.customview.widget.ExploreByTouchHelper+import com.raywenderlich.android.tacotuesday.R+++class CustomRatingBar @JvmOverloads constructor(+    context: Context,+    attrs: AttributeSet? = null,+    defStyleAttr: Int = 0+) : View(context, attrs, defStyleAttr) {++  @DrawableRes+  private val drawableResUnchecked: Int+  @DrawableRes+  private val drawableResChecked: Int+  private val label: String+  var rating = 0+    set(value) {+      field = value+      invalidate()+    }+  private val screenDensity = context.resources.displayMetrics.density+  private val diameter = (iconSizeDp * screenDensity).toInt()+  private val spacingWidth = (spacingWidthDp * screenDensity).toInt()+  private val maxRating = 5+  private val rectangles: Array<Rect> = Array(maxRating) { i ->+    val yFactor = i / maxRating+    val xFactor = i % maxRating+    val x = paddingLeft + xFactor * (diameter + spacingWidth)+    val y = paddingTop + yFactor * (diameter + spacingWidth)+    Rect(x, y, x + diameter, y + diameter)+  }+  private val exploreByTouchHelper = RatingExploreByTouchHelper(this)++  init {+    context.theme.obtainStyledAttributes(+        attrs,+        R.styleable.CustomRatingBar,+        0, 0).apply {++      try {+        drawableResChecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableChecked)+        drawableResUnchecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableUnchecked)+        label = getString(R.styleable.CustomRatingBar_ratingLabel) ?: ""+      } finally {+        recycle()+      }+    }+    isFocusable = true+    ViewCompat.setAccessibilityDelegate(this, exploreByTouchHelper)+    invalidate()+  }++  override fun dispatchHoverEvent(event: MotionEvent?): Boolean {+    return (event?.let { exploreByTouchHelper.dispatchHoverEvent(it) } ?: run { false }+        || super.dispatchHoverEvent(event))+  }++  override fun dispatchKeyEvent(event: KeyEvent?): Boolean {+    return (event?.let { exploreByTouchHelper.dispatchKeyEvent(it) } ?: run { false }+        || super.dispatchKeyEvent(event))+  }++  override fun onFocusChanged(gainFocus: Boolean, direction: Int, previouslyFocusedRect: Rect?) {+    super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)+    exploreByTouchHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect)+  }++  override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {+    super.onMeasure(widthMeasureSpec, heightMeasureSpec)+    val width: Int = maxRating * (diameter + spacingWidth) - spacingWidth + paddingLeft + paddingRight+    val height: Int = diameter + paddingTop + paddingBottom++    setMeasuredDimension(width, height)+  }++  override fun onDraw(canvas: Canvas) {+    diameter / 2.toFloat()+    for (i in 0 until maxRating) {+      val image = if (i >= rating) {+        ResourcesCompat.getDrawable(resources, drawableResUnchecked, context.theme)+      } else {+        ResourcesCompat.getDrawable(resources, drawableResChecked, context.theme)+      }+      image!!.setBounds(rectangles[i].left, rectangles[i].top, rectangles[i].right,+          rectangles[i].bottom)+      image.draw(canvas)+    }+  }++  override fun onTouchEvent(event: MotionEvent): Boolean {+    when (event.action) {+      MotionEvent.ACTION_DOWN -> return true+      MotionEvent.ACTION_UP -> {+        val selectedIndex = findRatingAtPoint(event.x, event.y)+        onSelected(selectedIndex)+        return true+      }+    }+    return super.onTouchEvent(event)+  }++  protected fun onSelected(selectedIndex: Int) {+    if (selectedIndex == INVALID_VALUE) return+    rating = selectedIndex + 1+    invalidate()+  }++  private fun findRatingAtPoint(x: Float, y: Float): Int {+    var selectedIndex = INVALID_VALUE+    for (i in 0 until maxRating) {+      if (rectangles[i].contains(x.toInt(), y.toInt())) {+        selectedIndex = i+        break+      }+    }+    return selectedIndex+  }++  companion object {+    const val INVALID_VALUE = -1+    const val spacingWidthDp = 10f+    const val iconSizeDp = 48f+  }++  inner class RatingExploreByTouchHelper(host: View) : ExploreByTouchHelper(host) {++    override fun getVirtualViewAt(x: Float, y: Float): Int {+      val index = findRatingAtPoint(x, y)+      return if (index == INVALID_VALUE) INVALID_ID else index+    }++    override fun getVisibleVirtualViews(virtualViewIds: MutableList<Int>?) {+      for (i in 0 until maxRating) virtualViewIds?.add(i)+    }++    override fun onPerformActionForVirtualView(+        virtualViewId: Int,+        action: Int,+        arguments: Bundle?+    ): Boolean {+      when (action) {+        AccessibilityNodeInfoCompat.ACTION_CLICK -> {+          onSelected(virtualViewId)+          return true+        }+      }+      return false+    }++    override fun onPopulateNodeForVirtualView(+        virtualViewId: Int,+        node: AccessibilityNodeInfoCompat+    ) {+      node.contentDescription = context.getString(

node.apply {}

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */+package com.raywenderlich.android.tacotuesday.shared++import android.content.Context+import android.graphics.Canvas+import android.graphics.Rect+import android.os.Bundle+import android.util.AttributeSet+import android.view.KeyEvent+import android.view.MotionEvent+import android.view.View+import androidx.annotation.DrawableRes+import androidx.core.content.res.ResourcesCompat+import androidx.core.content.res.getResourceIdOrThrow+import androidx.core.view.ViewCompat+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat+import androidx.customview.widget.ExploreByTouchHelper+import com.raywenderlich.android.tacotuesday.R+++class CustomRatingBar @JvmOverloads constructor(+    context: Context,+    attrs: AttributeSet? = null,+    defStyleAttr: Int = 0+) : View(context, attrs, defStyleAttr) {++  @DrawableRes+  private val drawableResUnchecked: Int+  @DrawableRes+  private val drawableResChecked: Int+  private val label: String+  var rating = 0+    set(value) {+      field = value+      invalidate()+    }+  private val screenDensity = context.resources.displayMetrics.density+  private val diameter = (iconSizeDp * screenDensity).toInt()+  private val spacingWidth = (spacingWidthDp * screenDensity).toInt()+  private val maxRating = 5+  private val rectangles: Array<Rect> = Array(maxRating) { i ->+    val yFactor = i / maxRating+    val xFactor = i % maxRating+    val x = paddingLeft + xFactor * (diameter + spacingWidth)+    val y = paddingTop + yFactor * (diameter + spacingWidth)+    Rect(x, y, x + diameter, y + diameter)+  }+  private val exploreByTouchHelper = RatingExploreByTouchHelper(this)++  init {+    context.theme.obtainStyledAttributes(+        attrs,+        R.styleable.CustomRatingBar,+        0, 0).apply {++      try {+        drawableResChecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableChecked)+        drawableResUnchecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableUnchecked)+        label = getString(R.styleable.CustomRatingBar_ratingLabel) ?: ""+      } finally {+        recycle()+      }+    }+    isFocusable = true+    ViewCompat.setAccessibilityDelegate(this, exploreByTouchHelper)+    invalidate()+  }++  override fun dispatchHoverEvent(event: MotionEvent?): Boolean {+    return (event?.let { exploreByTouchHelper.dispatchHoverEvent(it) } ?: run { false }+        || super.dispatchHoverEvent(event))+  }++  override fun dispatchKeyEvent(event: KeyEvent?): Boolean {+    return (event?.let { exploreByTouchHelper.dispatchKeyEvent(it) } ?: run { false }

= instead of return {}

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */+package com.raywenderlich.android.tacotuesday.shared++import android.content.Context+import android.graphics.Canvas+import android.graphics.Rect+import android.os.Bundle+import android.util.AttributeSet+import android.view.KeyEvent+import android.view.MotionEvent+import android.view.View+import androidx.annotation.DrawableRes+import androidx.core.content.res.ResourcesCompat+import androidx.core.content.res.getResourceIdOrThrow+import androidx.core.view.ViewCompat+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat+import androidx.customview.widget.ExploreByTouchHelper+import com.raywenderlich.android.tacotuesday.R+++class CustomRatingBar @JvmOverloads constructor(+    context: Context,+    attrs: AttributeSet? = null,+    defStyleAttr: Int = 0+) : View(context, attrs, defStyleAttr) {++  @DrawableRes+  private val drawableResUnchecked: Int+  @DrawableRes+  private val drawableResChecked: Int+  private val label: String+  var rating = 0+    set(value) {+      field = value+      invalidate()+    }+  private val screenDensity = context.resources.displayMetrics.density+  private val diameter = (iconSizeDp * screenDensity).toInt()+  private val spacingWidth = (spacingWidthDp * screenDensity).toInt()+  private val maxRating = 5+  private val rectangles: Array<Rect> = Array(maxRating) { i ->+    val yFactor = i / maxRating+    val xFactor = i % maxRating+    val x = paddingLeft + xFactor * (diameter + spacingWidth)+    val y = paddingTop + yFactor * (diameter + spacingWidth)+    Rect(x, y, x + diameter, y + diameter)+  }+  private val exploreByTouchHelper = RatingExploreByTouchHelper(this)++  init {+    context.theme.obtainStyledAttributes(+        attrs,+        R.styleable.CustomRatingBar,+        0, 0).apply {+

Redundant line

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.settings++import android.os.Bundle+import androidx.appcompat.app.AppCompatDelegate+import androidx.preference.Preference+import androidx.preference.PreferenceFragmentCompat+import androidx.preference.SwitchPreferenceCompat+import com.raywenderlich.android.tacotuesday.R++class SettingsFragment : PreferenceFragmentCompat() {++  override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {+    setPreferencesFromResource(+        R.xml.root_preferences, rootKey)++    findPreference<SwitchPreferenceCompat>("dark_mode")?.onPreferenceChangeListener =+        Preference.OnPreferenceChangeListener { _, newValue ->+          AppCompatDelegate.setDefaultNightMode(if (newValue == true) {

if (newValue)

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */+package com.raywenderlich.android.tacotuesday.shared++import android.content.Context+import android.graphics.Canvas+import android.graphics.Rect+import android.os.Bundle+import android.util.AttributeSet+import android.view.KeyEvent+import android.view.MotionEvent+import android.view.View+import androidx.annotation.DrawableRes+import androidx.core.content.res.ResourcesCompat+import androidx.core.content.res.getResourceIdOrThrow+import androidx.core.view.ViewCompat+import androidx.core.view.accessibility.AccessibilityNodeInfoCompat+import androidx.customview.widget.ExploreByTouchHelper+import com.raywenderlich.android.tacotuesday.R+++class CustomRatingBar @JvmOverloads constructor(+    context: Context,+    attrs: AttributeSet? = null,+    defStyleAttr: Int = 0+) : View(context, attrs, defStyleAttr) {++  @DrawableRes+  private val drawableResUnchecked: Int+  @DrawableRes+  private val drawableResChecked: Int+  private val label: String+  var rating = 0+    set(value) {+      field = value+      invalidate()+    }+  private val screenDensity = context.resources.displayMetrics.density+  private val diameter = (iconSizeDp * screenDensity).toInt()+  private val spacingWidth = (spacingWidthDp * screenDensity).toInt()+  private val maxRating = 5+  private val rectangles: Array<Rect> = Array(maxRating) { i ->+    val yFactor = i / maxRating+    val xFactor = i % maxRating+    val x = paddingLeft + xFactor * (diameter + spacingWidth)+    val y = paddingTop + yFactor * (diameter + spacingWidth)+    Rect(x, y, x + diameter, y + diameter)+  }+  private val exploreByTouchHelper = RatingExploreByTouchHelper(this)++  init {+    context.theme.obtainStyledAttributes(+        attrs,+        R.styleable.CustomRatingBar,+        0, 0).apply {++      try {+        drawableResChecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableChecked)+        drawableResUnchecked = getResourceIdOrThrow(R.styleable.CustomRatingBar_drawableUnchecked)+        label = getString(R.styleable.CustomRatingBar_ratingLabel) ?: ""+      } finally {+        recycle()+      }+    }+    isFocusable = true+    ViewCompat.setAccessibilityDelegate(this, exploreByTouchHelper)+    invalidate()+  }++  override fun dispatchHoverEvent(event: MotionEvent?): Boolean {

= instead of return {}

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday++import android.app.Application+import android.content.SharedPreferences+import androidx.appcompat.app.AppCompatDelegate+import dagger.hilt.android.HiltAndroidApp+import javax.inject.Inject++@HiltAndroidApp+open class TacoTuesdayApp : Application() {++  @Inject+  lateinit var sharedPreferences: SharedPreferences++  override fun onCreate() {+    super.onCreate()+    AppCompatDelegate.setDefaultNightMode(if (sharedPreferences.getBoolean("dark_mode", false)) {

🥇 🎉

Manda94

comment created time in 4 hours

Pull request review commentraywenderlich/acca-materials

Adding 11-designing-for-mental-health

+/*+ * Copyright (c) 2020 Razeware LLC+ *+ * Permission is hereby granted, free of charge, to any person obtaining a copy+ * of this software and associated documentation files (the "Software"), to deal+ * in the Software without restriction, including without limitation the rights+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+ * copies of the Software, and to permit persons to whom the Software is+ * furnished to do so, subject to the following conditions:+ *+ * The above copyright notice and this permission notice shall be included in+ * all copies or substantial portions of the Software.+ *+ * Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,+ * distribute, sublicense, create a derivative work, and/or sell copies of the+ * Software in any work that is designed, intended, or marketed for pedagogical or+ * instructional purposes related to programming, coding, application development,+ * or information technology.  Permission for such use, copying, modification,+ * merger, publication, distribution, sublicensing, creation of derivative works,+ * or sale is expressly withheld.+ *+ * This project and source code may use libraries or frameworks that are+ * released under various Open-Source licenses. Use of those libraries and+ * frameworks are governed by their own individual licenses.+ *+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+ * THE SOFTWARE.+ */++package com.raywenderlich.android.tacotuesday.onboarding++import android.content.Context+import android.content.Intent+import android.os.Bundle+import android.view.LayoutInflater+import android.view.View+import android.view.ViewGroup+import androidx.fragment.app.FragmentActivity+import androidx.preference.PreferenceManager+import androidx.recyclerview.widget.RecyclerView+import androidx.viewpager2.widget.ViewPager2+import com.raywenderlich.android.tacotuesday.MainActivity+import com.raywenderlich.android.tacotuesday.R+import com.raywenderlich.android.tacotuesday.databinding.ActivityOnboardingBinding+import com.raywenderlich.android.tacotuesday.databinding.ItemOnboardingBinding++class OnboardingActivity : FragmentActivity() {++  private lateinit var binding: ActivityOnboardingBinding++  override fun onCreate(savedInstanceState: Bundle?) {+    super.onCreate(savedInstanceState)++    binding = ActivityOnboardingBinding.inflate(layoutInflater)+    setContentView(binding.root)+    val pagerAdapter = OnboardingPagerAdapter()+    binding.onboardingPager.adapter = pagerAdapter+    binding.onboardingPager.registerOnPageChangeCallback(object :+        ViewPager2.OnPageChangeCallback() {+      override fun onPageSelected(position: Int) {+        binding.onboardingNextButton.text = if (position == NUM_PAGES - 1) {+          getString(R.string.onboarding_done)+        } else {+          getString(R.string.onboarding_next)+        }+        binding.onboardingBackButton.visibility = if (position == 0) {

binding.onboardingBackButton.isVisible = position == 0

Manda94

comment created time in 4 hours

push eventraywenderlich/ios-bootcamp-summer-2020

Jeff Rames

commit sha 6b39afb9d9f33066d2c6d25dbb3c6a15ece51bfd

add week 10

view details

push time in 5 hours

startedraywenderlich/swift-algorithm-club

started time in 7 hours

push eventraywenderlich/ia-materials

Fahim Farook

commit sha b84a20ed869242aa62f297eb9c8922501ab059a2

Chapter 19 * Resources * Source projects for Chapter 19

view details

push time in 8 hours

fork vinamelody/swift-algorithm-club

Algorithms and data structures in Swift, with explanations!

fork in 11 hours

startedraywenderlich/swift-style-guide

started time in 12 hours

startedraywenderlich/swift-style-guide

started time in 14 hours

startedraywenderlich/c-sharp-style-guide

started time in 17 hours

startedraywenderlich/swift-algorithm-club

started time in 17 hours

fork insaineyesay/swift-algorithm-club

Algorithms and data structures in Swift, with explanations!

fork in 20 hours

startedraywenderlich/swift-algorithm-club

started time in 20 hours

startedraywenderlich/swift-algorithm-club

started time in 21 hours

push eventraywenderlich/advs-materials

Ehab Yosry Amer

commit sha 0fc77724c3275c9ac4d20187fe2251e2db445861

Rewrite the project to UIKit SwiftUI showed alot of items within instruments specially in the leaks profiler.

view details

push time in a day

startedraywenderlich/swift-style-guide

started time in a day

fork arush7parth/swift-algorithm-club

Algorithms and data structures in Swift, with explanations!

fork in a day

startedraywenderlich/swift-algorithm-club

started time in a day

startedraywenderlich/swift-algorithm-club

started time in a day

startedraywenderlich/swift-algorithm-club

started time in a day

push eventraywenderlich/sa-materials

Ehab Yosry Amer

commit sha 009df34268cfab8be0be8aad7c52d44bc2ccdae2

Chapter updates from Ray's comments Divided the playground improved naming for weight example expanded on recursive constraints on associated types additional example on type erasures from the standard library

view details

push time in a day

push eventraywenderlich/bkk

Sam Davies

commit sha 8944a8a2e55f5c69e2aeacb5ebb32e3d6a6e85fb

Adding placeholders for new metadata fields - Sections and chapters can have a number set to "auto" - in_flux and hide_chapter_numbers at the book level are useful for cookbooks.

view details

push time in a day

fork yechentide/swift-algorithm-club

Algorithms and data structures in Swift, with explanations!

fork in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

startedraywenderlich/swift-style-guide

started time in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

fork Tack75/rwTODOs

Sample project for the Beginning git video course

fork in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

PullRequestEvent

startedraywenderlich/swift-style-guide

started time in 2 days

push eventraywenderlich/ckswift-materials

Ray Wenderlich

commit sha db59d5afdfb182d61fff48ce163e189210d6fda2

Bugfix

view details

push time in 2 days

push eventraywenderlich/ckswift-materials

Ray Wenderlich

commit sha 3660ca8a6f49157dcb14925d2e777ffe5464d047

Added source code from other repo.

view details

push time in 2 days

PR opened raywenderlich/ckswift-materials

Functions and methods playground

Originally I was thinking to do "functions and closures" changed it to "functions and methods". We can do closures as another section by itself.

+180 -0

0 comment

4 changed files

pr created time in 2 days

create barnchraywenderlich/ckswift-materials

branch : functions-and-methods

created branch time in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

fork GridPen/swift-algorithm-club

Algorithms and data structures in Swift, with explanations!

fork in 2 days

push eventraywenderlich/sa-materials

Ehab Yosry Amer

commit sha c385a8afb48b9beffdf31cd339c96c8fa4f68b37

Update Contents.swift

view details

push time in 2 days

fork adeelilyas81/rwTODOs

Sample project for the Beginning git video course

fork in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

startedraywenderlich/swift-algorithm-club

started time in 2 days

fork UebuNogamy/ideas

The "ideas" repository for the raywenderlich.com book Mastering Git

fork in 2 days

fork lacefarin/rwTODOs

Sample project for the Beginning git video course

fork in 2 days

startedraywenderlich/swift-style-guide

started time in 2 days

startedraywenderlich/swift-style-guide

started time in 3 days

push eventraywenderlich/da-materials

suragch

commit sha 901bb690e5ea8447347ac34540a633d2962b65f1

first draft finished

view details

push time in 3 days

startedraywenderlich/swift-algorithm-club

started time in 3 days

fork GiulianoSoria/ios-interview

The resources and instructions for the iOS Sample Project interview question.

fork in 3 days

delete branch raywenderlich/ckswift-materials

delete branch : beginning-control-flow

delete time in 3 days

push eventraywenderlich/ckswift-materials

Ray Fix

commit sha 7a0afe4603ad36ea9124cf6bd385d59f9caf508c

control flow playground

view details

Ray Fix

commit sha 07032f8a92e0bebcd9f280b68570183a09746cd8

Merge pull request #2 from raywenderlich/beginning-control-flow control flow playground

view details

push time in 3 days

PR opened raywenderlich/ckswift-materials

control flow playground

going through the motions

+142 -0

0 comment

4 changed files

pr created time in 3 days

create barnchraywenderlich/ckswift-materials

branch : beginning-control-flow

created branch time in 3 days

fork anasancho/swift-algorithm-club

Algorithms and data structures in Swift, with explanations!

fork in 3 days

startedraywenderlich/swift-algorithm-club

started time in 3 days

push eventraywenderlich/adva-materials

Manda94

commit sha fa7e9a46644e5bb964c1a632767b0939808c6c31

Update book repo title

view details

push time in 3 days

startedraywenderlich/swift-algorithm-club

started time in 3 days

startedraywenderlich/swift-algorithm-club

started time in 3 days

fork lacefarin/rwTODOs

Sample project for the Beginning git video course

fork in 3 days

push eventraywenderlich/android-bootcamp-summer-2020

Luka Kordić

commit sha cfbd4692d9dda28ce0bfb6c0f5d60c81d4e8ab10

Feature/koin (#3) * Provide all dependencies using Koin * Create scope for LoginActivity.kt * Write SharedPreferences provider

view details

push time in 3 days

PR merged raywenderlich/android-bootcamp-summer-2020

Reviewers
Feature/koin

Create Koin providers for all of the dependencies. Create custom scope for LoginActivity

+171 -142

0 comment

17 changed files

LukaKordic

pr closed time in 3 days

fork zaibatsu1/rwTODOs

Sample project for the Beginning git video course

fork in 3 days

startedraywenderlich/swift-style-guide

started time in 3 days

push eventraywenderlich/ia-materials

Fahim Farook

commit sha 79b203dcb4bd5b838d12a792a3cc637d6ad17fc5

Chapter 18 * Source projects for Chapter 18

view details

push time in 3 days

startedraywenderlich/ia-materials

started time in 3 days

push eventraywenderlich/advs-materials

Ehab Yosry Amer

commit sha fb640ecc483e8db47079443442813779600ed84e

Update SlowChain.swift

view details

push time in 4 days

startedraywenderlich/swift-algorithm-club

started time in 4 days

fork izniburak/ia-materials

The projects and materials that accompany the iOS Apprentice book

https://store.raywenderlich.com/products/ios-apprentice

fork in 4 days

startedraywenderlich/swift-style-guide

started time in 4 days

startedraywenderlich/SKTUtils

started time in 4 days

PR opened raywenderlich/ckswift-materials

Advanced optionals

Playgrounds for basic and advanced optionals. We can remove temp-playgrounds once merged.

+318 -0

0 comment

7 changed files

pr created time in 4 days

create barnchraywenderlich/ckswift-materials

branch : advanced-optionals

created branch time in 4 days

push eventraywenderlich/dag-materials

Massimo Carli

commit sha 36d5802ceea5698ea616d4d4c6248bed53cb748d

Fixes spacing and adds placeholders for Server IP in started project

view details

push time in 4 days

startedraywenderlich/swift-style-guide

started time in 4 days

more