All Posts in Wordpress

August 25, 2018 - No Comments!

Devices, apps and random gear I’m currently using

People frequently ask about the devices, apps and other random gear I'm using. Since I'm often testing new stuff I'll update this page every month or so.

If you have questions or there's something I missed, comment below or send a quick message.

iOS apps that live on my home screen

I keep a clutter free home screen, with only four apps in my dock. My traditional home screen, full of apps I use most often, is just a swipe left.

  • Drafts
  • OmniFocus
  • Launch Center Pro
  • DayOne

iOS apps I couldn't do without

  • 1Password
  • Fantastical
  • Workflow
  • Overcast
  • Evernote
  • Dark Sky

Devices

  • iPhone 6s
  • iPad Pro 10.5"
  • MacBook Pro 13"

Gear and protection

Gear - devices and accessories

  • Apple Magic Keyboard
  • Apple Magic Mouse
  • Apple Pencil
  • iPad stand
  • MBP lifts
  • MBP charger

Protection - cases and sleeves

  • 5.11 Tactical - COVRT18™ 25L Backpack
  • Spigen Tough Armor case – all black, both iPhone and iPad
  • Speck Matte Black case - keeps my MBP safe from scratches
  • Amazon Basics Poly Sleeve - keeps my MBP safer from scratches
  • Apple Pencil sleeve
  • Apple Pencil case
  • Mouse case
  • Keyboard case

On my Mac

  • Alfred / Alfred Workflows
  • TextExpander
  • OmniFocus
  • Quiver
  • SublimeText 3
  • Airmail 3
  • Fantastical
  • FileZilla
  • DayOne
  • 1Password
  • Evernote
  • Hemingway Editor
  • EncryptMe
  • Duet
  • MindNode

Mac Menubar Apps

  • Bartender 3
  • Amphetamine
  • Magnet
  • Hemingboard

December 5, 2017 - No Comments!

Hide Intercom chat between certain times on a schedule or at night

It turns out Intercom doesn't offer a dynamic way of hiding the chat launcher button. It's either on or it's off, as set through the Intercom dashboard.

With the help of a little JavaScript, we can set predefined times to hide the chat window.

Why would anyone want to hide the chat button between certain times?

Better user experience—don't offer a real-time chat if you're not available at 1am. Here's how to hide Intercom while you sleep.

 

For you TLDR's; here's the full code:

<script>
var d = new Date();
var currentHour = d.getHours();
var currentMins = d.getMinutes();

var newTime = (currentHour +':'+ currentMins).split(":");
var currentMils = (+newTime[0] * (60000 * 60)) + (+newTime[1] * 60000);

var availableStart = ('05:00').split(":"); // 05:00 = 5am
var startSplitMils = (+availableStart[0] * (60000 * 60)) + (+availableStart[1] * 60000);

var availableEnd = ('23:00').split(":"); // 23:00 = 11pm 
var endSplitMils = (+availableEnd[0] * (60000 * 60)) + (+availableEnd[1] * 60000);

if (currentMils >= startSplitMils && currentMils <= endSplitMils) {
 
(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/APP_ID';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()

var APP_ID = "x123456x";
// be sure to use your App ID here

window.Intercom('boot', {
 app_id: APP_ID,
 });
 console.log('Chat available from ' + availableStart +' - '+availableEnd);

} else {
 Intercom('shutdown');
 console.log('Chat unavailable from ' + availableEnd +' - '+availableStart);
}
<script>

 

Breaking it down:

Get the current date (hours and minutes)

var d = new Date();
var currentHour = d.getHours();
var currentMins = d.getMinutes();

Convert 24-hour times to milliseconds

var newTime = (currentHour +':'+ currentMins).split(":");
var currentMils = (+newTime[0] * (60000 * 60)) + (+newTime[1] * 60000);

Set your desired start time - this is the beginning of the scheduled time to show Intercom

This is when the chat will begin displaying. In our example, it's 5am (05:00)

var availableStart = ('05:00').split(":");
// 05:00 = 5am

Convert the start time to milliseconds, define the end time (begin to hide Intercom), and convert to MS

var startSplitMils = (+availableStart[0] * (60000 * 60)) + (+availableStart[1] * 60000);
// converts the start time to milliseconds

var availableEnd = ('23:00').split(":");
// 23:00 = 11pm 
var endSplitMils = (+availableEnd[0] * (60000 * 60)) + (+availableEnd[1] * 60000);

Lastly, write the conditional check

There are a few approaches here. You may choose to use window.intercomSettings.hide_default_launcher = true; instead but I found the explicit loading and shutdown to be more reliable on site with cached files.

if (currentMils >= startSplitMils && currentMils <= endSplitMils) {
  // activate the chat launcher
}

else {
  // we're sleeping, don't run the chat launcher code
};

 

That's it!

Have questions? Comment below 🙂

October 3, 2017 - 11 comments

SASS won’t build in Sublime Text Mac High Sierra [Errno 2] No such File or Directory

You just tried building .sass or .scss from Sublime Text on a Mac and you're seeing an error [Errno 2] No such File or Directory. Me too.

If you've recently updated to OS High Sierra, the solution is likely very simple. This works for both SublimeText 2 and 3.

You'll need to reinstall SASS from Terminal.

  1. Open Terminal: CMD + SPACE to launch Spotlight — type "Terminal" and hit enter
  2. Check Ruby version: Ruby is bundled in OSX type:
    ruby -v

    You should see something like:

    ruby 2.3.3p222 (2016-11-21 revision 56859) [universal.x86_64-darwin17]
  3. Install SASS
    sudo gem install sass
  4. Enter your password and you're all set.
    Once it's finished installing, jump back to Sublime Text (2 or 3) and do your business!

 


If this worked for you please give a heads up in the comments 🙂

May 23, 2017 - No Comments!

Delete Images from Media Gallery when WordPress Post moved to Trash

I have a client who sells unique products on their custom WordPress site. The products listed have limited quantities and once they're sold they won't be available again. From the front end, it's easy enough to just "Trash" a post (product) and they won't display. However, this could quickly lead to unnecessarily large storage on the server since WordPress doesn't delete post attachments (images) when posts are trashed.

Here's a quick code block which will delete images when posts are moved to the trash.

This could be included in functions.php or wrapped inside a custom plugin, it'll work the same either way. Be sure to read the *disclaimer at the bottom before breaking things.

 

This code will delete just the featured image when a post is moved to trash:

add_action( 'trashed_post', 'mtp_delete_attached_thumbnail_for_trashed_product', 20, 1 );

function mtp_delete_attached_thumbnail_for_trashed_product( $post_id ) {
 
 // gets ID of post being trashed
 $post_type = get_post_type( $post_id );
 
 // does not run on other post types
 if ( $post_type != 'post' ) {
 return true;
 }
 
 // get ID of featured image
 $post_thumbnail_id = get_post_thumbnail_id( $post_id );

 // delete featured image
 wp_delete_attachment( $post_thumbnail_id, true );
}

 


In many cases you'll have more images associated with a post or product. This code will also delete gallery images in addition to the featured image.

add_action( 'trashed_post', 'mtp_delete_attached_thumbnail_for_trashed_product', 20, 1 );

function mtp_delete_attached_thumbnail_for_trashed_product( $post_id ) {
 
 // gets ID of post being trashed
 $post_type = get_post_type( $post_id );
 
 // does not run on other post types { $post }
 if ( $post_type != 'post' ) {
 return true;
 }
 
 // get ID of featured image
 $post_thumbnail_id = get_post_thumbnail_id( $post_id );

 // gets array from custom field { $gallery } 
 $gallery_images = get_field('gallery', $post_id);

 // loop through { $gallery } 
 foreach ($gallery_images as $gallery_image) {
 
 // get each attachment ID
 $gallery_id = $gallery_image['id'];

 // delete attachments
 wp_delete_attachment( $gallery_id, true );
 }
 
 // delete featured image
 wp_delete_attachment( $post_thumbnail_id, true );
}

For either example, if you need this to work on a custom post type, i.e. "product". You'll need to replace this line:

if ( $post_type != 'post' ) {

with:

if ( $post_type != 'YOUR_POST_TYPE_NAME' ) {

If you have a gallery associated with the post, you'll also need to change the gallery name. In my case, I'm using an ACF gallery named "Gallery". So you'd update this line:

$gallery_images = get_field('gallery', $post_id);

with

$gallery_images = get_field('YOUR_GALLERY_FIELD_NAME', $post_id);

 


This code is being used on WP 4.7.5
*This will permanently delete your media so as always, be sure to run a backup of your site files and database before testing on your site.