Skip to content

Instantly share code, notes, and snippets.

View hafizrahman's full-sized avatar
🦉

Hafiz Rahman hafizrahman

🦉
View GitHub Profile
@hafizrahman
hafizrahman / SubjectFragment.kt
Created April 20, 2020 08:06
Observe the MediatorLiveData given by ViewModel, and update RecyclerViewAdapter accordingly.
mainViewModel = ViewModelProvider(activity!!).get(MainViewModel::class.java)
// New observer
mainViewModel.getAllData()?.observe(viewLifecycleOwner,
Observer { subjectsAndRemindersPair ->
view.sro_subject_list.adapter = SubjectRecyclerViewAdapter(
subjectsAndRemindersPair.first,
subjectsAndRemindersPair.second,
listener)
})
@hafizrahman
hafizrahman / SubjectRecyclerViewAdapter.kt
Created April 20, 2020 08:04
Put in the two List<> as constructor parameters in RecyclerViewAdapter
class SubjectRecyclerViewAdapter(
val subjects: List<Subject>,
val reminders: List<Reminder>,
val listener: OnListFragmentInteractionListener?
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
@hafizrahman
hafizrahman / MainViewModel.kt
Created April 20, 2020 08:03
Methods inside ViewModel to grab two LiveData from repository and put them into one MediatorLiveData
fun getSubjects(): LiveData<List<Subject>>? {
return sroRepository.getSubjects()
}
fun getReminders(): LiveData<List<Reminder>>? {
return sroRepository.getReminders()
}
fun getAllData(): CombinedSubjectReminders? {
var ldSubjects = getSubjects()
@hafizrahman
hafizrahman / CombinedSubjectReminders.kt
Created April 20, 2020 08:01
Example of a MediatorLiveData class to handle two LiveDatas at once.
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
// This class ia a MediatorLiveData created since I have two different sources of data:
// - subjects table
// - reminders table
// Since they then become two separate LiveData, and I need both to fill in the data
// on the main RecyclerView, then we're using a MediatorLiveData to grab both LiveData
// and add them as sources, so that we can notify observers when any of the data gets
@hafizrahman
hafizrahman / exampleActivity.kt
Created December 29, 2019 03:35
Example of View Binding using Kotlin Extension
// Using R.layout.activity_main from the 'main' source set
import kotlinx.android.synthetic.main.activity_main.*
class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Instead of findViewById<TextView>(R.id.textView)
textView.setText("Hello, world!")
@hafizrahman
hafizrahman / ConstantsUsageExample.kt
Created December 8, 2019 07:49
Example of how to use a constant variable
val sharedPreferences = EncryptedSharedPreferences.create(
WPFC_SHARED_PREFS_FILENAME,
masterKeyAlias,
this,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
@hafizrahman
hafizrahman / constants.kt
Last active December 9, 2019 03:00
Constants file example.
package studio.oldblack.wpflightcontrol
const val WPFC_SHARED_PREFS_FILENAME = "wpfc_prefs"
const val WPFC_WPCOM_AUTH_ENDPOINT = "https://public-api.wordpress.com/oauth2/authorize"
const val WPFC_WPCOM_TOKEN_ENDPOINT = "https://public-api.wordpress.com/oauth2/token"
@hafizrahman
hafizrahman / gist:04265e530b2823792fa53c802a4894f2
Last active December 5, 2019 04:56
Add WP REST API support to certain taxonomies
/**
* Add REST API support to an already registered taxonomy.
*/
add_filter( 'register_taxonomy_args', 'my_taxonomy_args', 10, 2 );
function my_taxonomy_args( $args, $taxonomy_name ) {
if ( 'freebbble-type' === $taxonomy_name || 'freebbble-license' === $taxonomy_name ) {
$args['show_in_rest'] = true;
@hafizrahman
hafizrahman / add-gutenberg-class.php
Last active April 10, 2019 05:00
WordPress: Add body class (for single post template) or post class (for blog/archive pages) "made-with-gutenberg" for posts/pages created with Gutenberg editor.
// add class to body class on single post template
function themeprefix_body_class_blocks( $classes ) {
if ( is_singular() && has_blocks() ) {
$classes[] = 'made-with-gutenberg';
}
return $classes;
}
add_filter( 'body_class', 'themeprefix_body_class_blocks' );
(function(e,t,n,r){function b(){var t=u;if(p==0&&c){if(!O())return}if(t.steps[p].popup.type!="modal"&&t.steps[p].popup.type!="nohighlight"){m.html("");if(t.steps[p].wrapper==""||t.steps[p].wrapper==r){alert('Your walkthrough position is: "'+t.steps[p].popup.type+'" but wrapper is empty or undefined. Please check your "'+a+'" wrapper parameter.');return}var i=B(e(t.steps[p].wrapper).offset().top);var s=B(e(t.steps[p].wrapper).offset().left);var o=B(e(t.steps[p].wrapper).innerWidth())||B(e(t.steps[p].wrapper).width());var f=B(e(t.steps[p].wrapper).innerHeight())||B(e(t.steps[p].wrapper).height());var l=F(t.steps[p].margin,"top"),h=F(t.steps[p].margin,"right"),d=F(t.steps[p].margin,"bottom"),v=F(t.steps[p].margin,"left"),g=30,y="",b="";var x={height:B(parseInt(i)-(parseInt(l)+g))};var T={top:x.height,width:B(parseInt(s)-(parseInt(v)+g)),height:B(parseInt(f)+g*2+parseInt(l)+parseInt(d))};if(t.steps[p].overlay==r||t.steps[p].overlay){y="overlay"}else{y="noOverlay";b="killOverlay"}var N=e('<div id="overlayTop" clas