Jekyll2021-01-25T02:47:57+00:00https://anh.do/feed.xmlanh.doI build appsAnh DoTime Tracking with Toggl, Part I2020-08-14T00:00:00+00:002020-08-14T00:00:00+00:00https://anh.do/blog/time-tracking-toggl-part-i<p>In the past I made several attempts to do time tracking but they all ended miserably. I was no stranger to automated tools like <a href="https://www.rescuetime.com">RescueTime</a> or <a href="https://qotoqot.com/qbserve/">Qbserve</a> but none of them clicked for me. They ran quietly in the background and once a week I would receive an email detailing where my time had gone the previous week. Rinse and repeat. There were nice charts to look at but for someone who wasn’t using time tracking to bill clients, they were noises to me.</p>
<p>Half a year ago I read more about how others used it and finally realized what I had done wrong: I had relied on the tools to automatically keep track of my tasks and categorize them into different buckets, while instead I should deliberately define which tasks I want to track and start/stop the timers myself. The benefit that comes from time tracking is that <em>intentionality</em> when I carry out the tasks during the day, not only when I open the summary email. A classic case of ‘the journey is the reward’.</p>
<p>Armed with that newfound knowledge, I again restarted my time tracking effort with <a href="https://toggl.com">Toggl</a> and its mobile companion, a third-party app called <a href="https://timeryapp.com">Timery</a>. This time it worked: The act of manually manipulating the timers made everything <em>intentional</em>. Stop working to look at Reddit for a few, erm, minutes – pause the current timer. Start watching Netflix or launching a game on Steam – I’d better start another timer. Focus on the categories I want to track and ignore the rest.</p>
<p>There was no need to track every single minute in the day; I only had to define a few categories that I cared about the most, like Productive Work (insert a side project name here), Entertainment (Netflix and Reddit and everything in between), Fitness (Jogging and Ring Fit Adventure, duh), etc. With 6 months’ worth of data, I can already form a picture of how well I spent my time during the current pandemic. Spoiler alert: A lot of Netflix, gaming, and procrastination.</p>
<p>At that point, I decided to extend the tracking history by importing the data I already had from last year (thanks to Qbserve) into Toggl. Toggl supports CSV import and had good documentation, so there shouldn’t be any problems, right?</p>
<p>Apparently not. I was baffled at how bad Toggl’s bulk management tools were when it came to CSV import. This was but an example:</p>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" align="center"><p lang="en" dir="ltr">Recently I gave time tracking a try. I imported my logs into Toggl as instructed (<a href="https://t.co/4nSloVucnY">https://t.co/4nSloVucnY</a>) and ended up with 3000 hours of overlapping time entries. Turned out Toggl didn't automatically combine such entries. Oops. (1/7)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1224078928115126272?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">I deleted the imported project and realized that it didn't remove any associated entries. They were just turned into uncategorized ones. (2/7)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1224078929654353921?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">Both the web interface and native apps didn't help - there was no way to bulk delete thousands and thousands of time entries. No Reset button anywhere either. (3/7)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1224078931302678532?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">I turned to the published API doc (<a href="https://t.co/yYrOlPD5Oo">https://t.co/yYrOlPD5Oo</a>), hoping to find a solution. No luck. Only one entry can be deleted at a time. (4/7)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1224078932586246144?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">Had to use Firefox Dev Tools to find the correct API calls from the web app - they allowed batch delete of up to 50 entries at a time. curl to the rescue. (5/7)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1224078933945126913?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">I set a quick 'n' dirty script to run every few seconds to go thru the whole list and remove them the 'correct' way. It look something like this: `curl GET_TIME_ENTRY_IDS | jq '.data[].id' | paste -sd "," - | xargs curl DELETE_TIME_ENTRIES` (6/7)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1224078935853555717?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">Moral of the story: Command line tools rock. (7/7)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1224078937392865288?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p>In Part II, I’ll write about how I managed to import my workout history into Toggl.</p>Anh DoOne habit I’m glad to have adopted successfully this year is time tracking. Although Toggl, my tool of choice, has been way better at the task than other tools I’ve previously tried, its limitation drives me banana.Reset macOS Login Password Without Remembering the Current One2020-04-14T00:00:00+00:002020-04-14T00:00:00+00:00https://anh.do/blog/singleusermode-applesetupdone-lion<p>This may not work if you’re using a new(er) machine with T2 security chip or having FileVault enabled. The one I was dealing with was an old MacBook Pro (Early 2011) running Lion.</p>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" align="center"><p lang="en" dir="ltr">Story time! A family member asked me to help with her old MBP (Early 2011). It was running Lion (!) and she couldn't watch YouTube because the browser was no longer supported. She wanted to upgrade her OS but she didn't know her admin password. (1/6)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1248310505955102722?ref_src=twsrc%5Etfw">April 9, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">Apparently her laptop was set up by someone else & that someone turned on Automatic Login. For 9 yrs she's been using her computer without ever having to enter her admin password. She didn't even remember who helped her set it up in the 1st place. (2/6)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1248310507058212865?ref_src=twsrc%5Etfw">April 9, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">How to reset the password without even knowing the current one? There's a support article for that: <a href="https://t.co/NpLlCwN5mH">https://t.co/NpLlCwN5mH</a>. Unfortunately, she had no Apple ID set up and FileVault turned off. (3/6)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1248310508190605313?ref_src=twsrc%5Etfw">April 9, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">Creating a new admin account using System Preferences wasn't an option either because she couldn't unlock the Users & Groups pane: <a href="https://t.co/tELUgvuVZ6">https://t.co/tELUgvuVZ6</a> (4/6)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1248310509469868032?ref_src=twsrc%5Etfw">April 9, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">The solution was to boot into Single User Mode and remove AppleSetupDone to force the machine to re-run Setup Assistant of course: <a href="https://t.co/Uknrfnhm04">https://t.co/Uknrfnhm04</a>. She then created a new Admin account, log in to it and reset the other account's password. (5/6)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1248310510765903872?ref_src=twsrc%5Etfw">April 9, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">She lost access to her old keychain, but all other data was there. Once again, Single User Mode saved the day.<br /> (6/6)</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1248310512246566912?ref_src=twsrc%5Etfw">April 9, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>Anh DoOnce again, Single User Mode + AppleSetupDone reset combo saved the day.Signing Git Commits Using GPG in Catalina2020-01-21T00:00:00+00:002020-01-21T00:00:00+00:00https://anh.do/blog/gpg-catalina<ol>
<li>Install dependencies:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew install gpg pinentry-mac
</code></pre></div> </div>
</li>
<li>Generate a GPG key (use 4096 bit option):
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gpg --full-generate-key
</code></pre></div> </div>
</li>
<li>Get the key ID (the one following <code class="language-plaintext highlighter-rouge">sec rsa4096/</code>, looking like this: <code class="language-plaintext highlighter-rouge">1234EA45F525C1AD</code>):
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gpg --list-secret-keys --keyid-format LONG
</code></pre></div> </div>
</li>
<li>Set your signing key in Git:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global user.signingkey KEY_ID_GOES_HERE
</code></pre></div> </div>
</li>
<li>Run these to automatically sign all commits with <code class="language-plaintext highlighter-rouge">gpg</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git config --global commit.gpgsign true
git config --global gpg.program gpg
</code></pre></div> </div>
</li>
<li>Use the public key block to update your remote repo settings (for GitHub, it’d be under <a href="https://github.com/settings/keys">GPG Keys</a>):
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gpg --armor --export KEY_ID_GOES_HERE | pbcopy
</code></pre></div> </div>
</li>
<li>Put this in <code class="language-plaintext highlighter-rouge">.bash_profile</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GPG_TTY=$(tty)
</code></pre></div> </div>
</li>
<li>Or, if you’re a Fish user like me, put in <code class="language-plaintext highlighter-rouge">config.fish</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>set -x GPG_TTY (tty)
</code></pre></div> </div>
</li>
<li>Add to <code class="language-plaintext highlighter-rouge">~/.gnupg/gpg-agent.conf</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pinentry-program /usr/local/bin/pinentry-mac
</code></pre></div> </div>
</li>
<li>Add to <code class="language-plaintext highlighter-rouge">~/.gnupg/gpg.conf</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>use-agent
batch
require-cross-certification
</code></pre></div> </div>
</li>
<li>Finally, restart <code class="language-plaintext highlighter-rouge">gpg-agent</code>:
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>killall gpg-agent
gpg-agent --daemon
</code></pre></div> </div>
</li>
</ol>
<h3 id="references">References</h3>
<ul>
<li><a href="https://help.github.com/en/github/authenticating-to-github/generating-a-new-gpg-key">Generating a new GPG key</a></li>
<li><a href="https://help.github.com/en/github/authenticating-to-github/telling-git-about-your-signing-key">Telling Git about your signing key</a></li>
<li><a href="https://bl.ocks.org/loklaan/41f39ba49ebf4ca9c97849c83f7ff242">GPG & SSH for Mac, the proper way?</a></li>
</ul>Anh DoMost of the instructions I found were scattered all over the place, so I collected them here to make it easier to find.Re-running OS X Setup Assistant in Catalina2019-11-21T00:00:00+00:002019-11-21T00:00:00+00:00https://anh.do/blog/applesetupdone-catalina<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" align="center"><p lang="en" dir="ltr">Apparently I should've not copied and pasted things I read on the Internet into Terminal. Managed to demote my user account to a Standard one. <br /><br />My machine had no other Admin account <a href="https://twitter.com/hashtag/FML?src=hash&ref_src=twsrc%5Etfw">#FML</a></p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1194782454957191168?ref_src=twsrc%5Etfw">November 14, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">This old single-user mode & .AppleSetupDone removal workaround didn't work in Catalina. <a href="https://t.co/Uknrfnhm04">https://t.co/Uknrfnhm04</a></p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1194782952384868354?ref_src=twsrc%5Etfw">November 14, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">What finally fixed the issue for me: <br /><br />1. Cmd+R to enter Recovery mode<br />2. Enter my account password<br />3. Use Disk Utilities to mount the FileVault disk (Macintosh HD)<br />4. `rm /Volumes/Macintosh\ HD\ -\ Data/private/var/db/.AppleSetupDone`<br />5. `reboot`<br /><br />[...]</p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1194783447719567360?ref_src=twsrc%5Etfw">November 14, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">[...]<br /><br />6. Create a new temp account with admin privilege<br />7. Log in to that account & promote my existing one to Admin<br />8. Reboot<br />9. Log back in to that account & remove the temp one<br />10. Let out a big sigh <a href="https://twitter.com/hashtag/NoteToSelf?src=hash&ref_src=twsrc%5Etfw">#NoteToSelf</a></p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1194783926369366016?ref_src=twsrc%5Etfw">November 14, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">This might also work: Enable the `root` account and use it to promote my standard one.<a href="https://t.co/dzzhk0gwn2">https://t.co/dzzhk0gwn2</a></p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1194784258881138689?ref_src=twsrc%5Etfw">November 14, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>Anh DoThe other day I accidentally demoted my macOS Admin user account to a Standard one. Re-running OS X Setup Assistant to create a new account wasn't as straightforward as I had expected.View Past Tweets on Google Maps2019-10-03T00:00:00+00:002019-10-03T00:00:00+00:00https://anh.do/blog/tweets-on-google-maps<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" align="center"><p lang="en" dir="ltr">I wanted to view my past tweets on Google Maps just for fun. Unfortunately there's no easy way to do it (all 1-click services are gone). <a href="https://t.co/p3lwgwQjVZ">pic.twitter.com/p3lwgwQjVZ</a></p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1179594340307480576?ref_src=twsrc%5Etfw">October 3, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="jekyll-twitter-plugin"><blockquote class="twitter-tweet" data-conversation="none" align="center"><p lang="en" dir="ltr">1. Download all my tweets from Download your Twitter data: <a href="https://t.co/tKfKUT2TKP">https://t.co/tKfKUT2TKP</a><br /><br />2. Unpack the ZIP file and open tweet.js<br /><br />3. Remove the variable assignment part<br /><br />4. Run this: <a href="https://t.co/e3LEFmmFjV">https://t.co/e3LEFmmFjV</a><br /><br />You'll need jq installed.<br /><br />5. Import the CSV into <a href="https://t.co/UucEVbd0Y1">https://t.co/UucEVbd0Y1</a></p>— Anh (@quanganhdo) <a href="https://twitter.com/quanganhdo/status/1179595094581825536?ref_src=twsrc%5Etfw">October 3, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>Anh Dojq and GPS Visualizer to the rescue.Tracking My Podcast Listening Habit2019-08-05T00:00:00+00:002019-08-05T00:00:00+00:00https://anh.do/blog/castro-history<p>My effort to back up my social media activities involves <a href="https://momentoapp.com">Momento</a>, an iOS private journal app that I wrote about in <a href="/blog/owning-data">my last post</a>. As the number of my listened podcast episodes over the years crossed 500, I wished to import my listening history into Momento as well. It was a cumbersome and convoluted process involving <em>a lot</em> of tools since there is no official way to do that in <a href="https://castro.fm">Castro</a>, my podcast player of choice.</p>
<p>By emailing Castro’s creator, I learned that the app includes a hidden feature to give access to the underlying SQLite database for technical support:</p>
<ol>
<li>Open the in-app Settings screen</li>
<li>Navigate to Support and long tap on Email Support</li>
<li>Choose “Email with Database And Logs” and send the email to my address</li>
</ol>
<p><img src="/assets/uploads/2019-08-05-castro-history-castro.png" alt="Export Castro's SQLite database" /></p>
<p>I then ran the SQL query below to retrieve all played/starred episodes and exported the results as JSON:</p>
<script src="https://gist.github.com/quanganhdo/c719d7e92497642234eebe75926d6f9b.js"></script>
<p>The output looked like this:</p>
<script src="https://gist.github.com/quanganhdo/5f6a6532f6bb4d87117add8a17562976.js"></script>
<p>Notice that I linked each episode to its page on Castro’s server (<a href="https://castro.fm/episode/MdiHr4">see example</a>). This came in handy as I later used Ruby to convert the JSON file to… <a href="https://getpocket.com">Pocket</a>’s exported bookmark format for use with <a href="https://pinboard.in/">Pinboard</a>’s Import Bookmarks feature (crazy, I know):</p>
<script src="https://gist.github.com/quanganhdo/9fa96538f3c49436603aa3bf1de9e4c2.js"></script>
<p>I named the resulting file <code class="language-plaintext highlighter-rouge">ril_export.html</code> and <a href="https://pinboard.in/settings/import">fetched it to Pinboard</a>:</p>
<script src="https://gist.github.com/quanganhdo/749b9d27eebd550cf2f1617460e774be.js"></script>
<p>Thanks to my <a href="https://pinboard.in/upgrade/">archival account</a>, Pinboard quickly imported the list and saved a permanent copy for each page.</p>
<p><img src="/assets/uploads/2019-08-05-castro-history-pinboard.png" alt="Podcast listening history in Pinboard" /></p>
<p>Finally, I set up a RSS feed to the tag in Momento to show off my listening habit:</p>
<p><img src="/assets/uploads/2019-08-05-castro-history-momento.png" alt="Podcast listening history in Momento" /></p>
<p>It was worth it.</p>Anh DoI found a convoluted way to import my podcast listening history in Castro into Momento, my favorite iOS social activity backup tool. It was worth the effort.Owning My Data2019-05-07T00:00:00+00:002019-05-07T00:00:00+00:00https://anh.do/blog/owning-data<p>My online presence went back <a href="/blog/online-services">10+ years</a>. Last year alone I made 146 new posts on Facebook, 65 tweets on Twitter, 76 photos on Instagram, 1091 check-ins on Swarm, and countless interactions such as “likes” and “favorites”. I knew the exact numbers because I’ve been making a conscious effort to preserve this data, if only to look back and reconstruct my activities in any given day<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote">1</a></sup>. <a href="http://cn.asc.upenn.edu/wp-content/uploads/2013/07/CSCW-2016-Schoenebeck.pdf">Backstalking</a> is fun.</p>
<p>There are online services like <a href="https://www.timehop.com/about">Timehop</a> that gives users an easy way to explore their historical digital content, but I prefer to keep my data offline in a portable format like JSON or XML. I’m relying on an app called <a href="https://momentoapp.com">Momento</a>, which has been under active development since 2011. It connects to more than a dozen social networks, periodically downloads my content there, and presents them in a nice layout<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote">2</a></sup>. Data can be exported at any time via iTunes File Sharing, so there’s no lock-in.</p>
<p>I keep the following feeds in Momento:</p>
<ul>
<li>Facebook, Instagram, Twitter, Swarm, Medium, Goodreads, Uber: All supported out of the box.</li>
<li>Pinboard, Vimeo, Instapaper (Archived and Starred), GitLab, NewsBlur (Saved Stories): Needs manual setup using RSS feed.</li>
</ul>
<p><img src="/assets/uploads/2019-05-07-owning-data-momento.png" alt="Momento" /></p>
<p>Momento’s ability to download RSS feed works extremely well with <a href="https://pinboard.in/faq/#viewing_bookmarks">Pinboard’s filter support</a>: Bookmarks can be filtered by multiple tags, with a secret RSS feed URL to subscribe to. I use <a href="https://ifttt.com">IFTTT</a> recipes to automatically send URLs from sources without RSS support to Pinboard, which in turn are pulled into Momento for safe keeping:</p>
<ul>
<li>Liked tweets on Twitter</li>
<li>Liked videos on YouTube</li>
</ul>
<p><img src="/assets/uploads/2019-05-07-owning-data-ifttt-pinboard.png" alt="IFTTT and Pinboard" /></p>
<p>One significant downside of Momento is its iPhone-only nature. In the past, I used <a href="https://digi.me">Digi.me</a> on the Mac to download my digital content but stopped doing so as they pivoted and changed their business model for the second time: from paid upfront to freemium with subscription, then to <a href="https://digi.me/terms-and-conditions/">free with some asterisks</a>. I have yet to find a replacement for that.</p>
<hr />
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>I’d recommend <a href="http://photoflashback.app">Photo Flashback</a> if you’re looking for an On This Day app for just your camera roll. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>Momento is positioned as a diary/journal app, yet I find this main feature to be way inferior than dedicated apps like <a href="http://dayoneapp.com">Day One</a>. Automatically collecting my daily activities from different sources makes it a hidden gem in my app collection. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>Anh DoI've been making a conscious effort to preserve my online footprints, if only to look back and reconstruct my activities in any given day. I'm using a combination of iOS app (Momento) and services (IFTTT, Pinboard) for that.Thoughts on Online Services2019-02-24T00:00:00+00:002019-02-24T00:00:00+00:00https://anh.do/blog/online-services<p>I recently looked back at my 15 years on the Internet and reviewed all the online services I’ve been using till now (and still haven’t been “sunset” yet). In chronological order:</p>
<ol>
<li><strong>Gmail</strong>: I started looking for a Gmail invite the day it came out on April 1st, 2004. I got an account to call mine some time in 2005 and have been using it as my primary email address ever since. The two biggest benefits are still the same: generous free storage and exceptional spam filter. I mostly interact with this account via IMAP clients, so their web UI with all the new “improvements” is largely invisible to me. With a growing number of <a href="https://killedbygoogle.com">sunset services</a>, I’m not surprised if Google will kill Gmail or make it a paid-only service someday. When the time comes, I’d switch full time to my vanity email address at this domain, which is currently hosted at <a href="https://www.zoho.com/mail/">Zoho</a>.</li>
<li><strong>Facebook</strong>: I created my account upon entering university in 2007. Over the years Facebook has grown into a big time sink for me, demanding my attention at its endless algorithmic newsfeed every single day. Looking at <a href="https://support.apple.com/en-us/HT208982">Screen Time</a> reports, I was horrified by the amount of time I wasted on Facebook and decided to aggressively cut down my time-on-app<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote">1</a></sup>. For now I’m pleased with a hard limit of 15 minute screen time per day and will gradually reduce it further.</li>
<li><strong>Twitter</strong>: My favorite social network since 2007. I can curate my following list, and (for now) have total control of what I see everyday in strict reversed chronological order. No feed ranking craps as long as I stick to third-party clients like Tweetbot or Twitterrific. Some niceties like streaming and polls are exclusive to the official client, but the app’s so bad that I’d rather enjoy Twitter without those features.</li>
<li><strong>Dropbox</strong>: As an early 2008 user, I was able to enjoy 30GB of free storage by maxing out my referrals. Dropbox’s ease of use, third-party support, and versioning feature are pretty much unmatched. Unfortunately it has become <a href="https://applehelpwriter.com/2016/08/29/discovering-how-dropbox-hacks-your-mac/">much more user hostile these days</a>, so I’m looking into iCloud Drive as a replacement.</li>
<li><strong>1password</strong>: Having a password manager is simply a must these days. Since I bought the iPhone version in 2008, 1password’s list of useful features has been growing non stop: PC/Android/Web versions, <a href="https://haveibeenpwned.com">Have I Been Pwned</a> integration, weak/reused/vulnerable password detection, two-factor authentication support, just to name a few. Hopefully they’ll soon copy their competitor Dashlane’s ability to <a href="https://support.dashlane.com/hc/en-us/articles/202699281-How-to-use-Password-Changer">change passwords for certain sites quickly</a>; it sounds really convenient.</li>
<li><strong>Foursquare/Swarm:</strong> One of the <a href="https://www.theverge.com/2019/2/19/18231985/foursquare-user-data-ceo-jeff-glueck-vergecast">genuinely good</a> guys in the list. I enjoyed checking into different places wherever I went, and earning badges just for the fun of it. Swarm’s animations and attention to details were so delightful and nicely done that I kept showing them to friends and asked them to give the service a try.</li>
<li><strong>Instapaper</strong>: The app has been on my iPhone home screen for the last 11 years. Couple of times I tried to switch to similar apps like Readability and Pocket for a change, but always had to go back to Instapaper because of its simplicity and superior reading experience. I’m quite worried about Instapaper’s <a href="https://techcrunch.com/2013/04/25/betaworks-instapaper/">repeated</a> <a href="https://www.wired.com/2016/08/pinterest-buys-instapaper/">owner</a> <a href="http://blog.instapaper.com/post/175953870856">changes</a>, but luckily the UX has never changed for the worse. Also I’m able to export my data and take it elsewhere at any time, so it’s at least a reassurance.</li>
<li><strong>Instagram</strong>: Simply playing with different photo filters was my original reason to download Instagram in 2010. Over the years, this has become my Facebook replacement: a smaller, more private space with more positive vibes. However, knowing that Facebook owns the product, has been messing around with <a href="https://techcrunch.com/2018/06/01/how-instagram-feed-works/">Instagram’s algorithmic feed</a> since 2016, and planned to blur the line between <a href="https://www.nytimes.com/2019/01/25/technology/facebook-instagram-whatsapp-messenger.html">its different properties</a>, I fully expect to delete my account one day, just like Facebook itself<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote">2</a></sup>.</li>
<li><strong>Pinboard</strong>: Another good guy that I’ve been relying on. I kept renewing my account with bookmark archival since 2010 to privately store all interesting links I came across along with their snapshots. Right now I’ve got ~13,000 bookmarks consuming 13GB of disk space, and full text search makes it so easy to find exactly what I need.</li>
<li><strong>Backblaze</strong>: My offsite backup solution of choice since 2010. The biggest advantage is its fast upload speed, no matter where I live. NAS support has always been on my wishlist, but with unlimited storage being offered at a relatively low price, I doubt it will ever come.</li>
<li><strong>iCloud Drive</strong>: I mostly use iCloud Drive for photo storage. I first registered for the 200GB plan in 2014, then upgraded to the biggest tier at 2TB when I had my first kid 3 years later. iCloud has become my favorite private “social network” to share photos with family members. It, however, still lacks advanced features like file versioning, folder sharing, finer control of which folders to sync, etc. I doubt Apple would ever add them, though.</li>
</ol>
<hr />
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:1" role="doc-endnote">
<p>Deactivating/Deleting my Facebook account outright isn’t really an option, as I still rely on it to catch up with my family and friends. Being away from home at least half of the time sucks. <a href="#fnref:1" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
<li id="fn:2" role="doc-endnote">
<p>Another thing that freaks me out about Facebook/Instagram is the increasingly-precise ad targeting. When I first started using the mobile version, the ads were terrible but easy to skip. Now they (un)surprisingly match my taste and more often than not, attract at least one click from me. This is so creepy. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">↩</a></p>
</li>
</ol>
</div>Anh DoI recently looked back at my 15 years on the Internet and reviewed all the online services I've been till now (and still haven't been "sunset" yet).Reviving My Blog2019-02-22T00:00:00+00:002019-02-22T00:00:00+00:00https://anh.do/blog/metablogging<p>My first online presence was back in 2005 in the form of a <a href="https://wordpress.org">WordPress</a> blog. Taking advantage of WordPress’ extensibility, I wrote <a href="https://profiles.wordpress.org/quanganhdo/#content-plugins">a bunch of plugins</a> to customize the self-hosted blog to suit my need. <a href="https://wordpress.org/plugins/custom-smilies/">One of them</a> was even picked up by Mashable and <a href="https://mashable.com/2007/07/24/wordpress-comments/#dOR0ki_yEuqq">featured there</a> <a href="https://mashable.com/2007/08/16/wordpress-god300-tools-for-running-your-wordpress-blog/">twice</a>. Some enjoyed it so much that they asked to <a href="https://github.com/wp-plugins/custom-smilies">take over the project </a> when I stopped maintaining it.</p>
<p>For a short while in 2006, I decided to turn my blog into a full-fledged site powered by a proper CMS called <a href="https://textpattern.com">Textpattern</a>. I added a few sections to the site to showcase my projects: some WordPress plugins, PHP scripts, and even <a href="http://m.majorgeeks.com/files/details/reg_assistant.html">Windows</a> <a href="http://m.majorgeeks.com/files/details/folder_tweaker.html">freeware</a>.</p>
<p>Then came the new tumblelogging trend with the launch of <a href="https://www.tumblr.com">Tumblr</a> in 2007. I found the concept of sharing interesting links and photos I came across <a href="/blog/on-tumblr">strangely appealing</a> and used Tumblr’s <a href="https://support.tumblr.com/post/21266862157/rachelfershleiser-how-to-use-a-tumblr">super-useful bookmarklet</a> extensively on my newly created tumblelog. Another migration was in order: I moved my main site from Textpattern to <a href="https://www.whoishostingthis.com/resources/chyrp/">Chyrp</a>, a now-defunct microblogging engine made by a single developer. Unlike Tumblr, Chyrp let me play around with different post formats, customizations, theming, and all that. It was fun while it lasted; upon entering university and later getting full time employment, I had much less time maintaining both sites and stopped blogging altogether.</p>
<p>Fast forward to 2016, <a href="https://medium.com">Medium</a> was <a href="https://m.signalvnoise.com/signal-v-noise-moves-to-medium/">all the rage</a>. While not being as generous as Tumblr (free custom domain for everyone), Medium let me set up a “publication” and pointed my domain to it. I moved some of my old writings there and wrote <a href="/blog/kindle-tips">one whole new blog post</a>.</p>
<p>The year is 2019. Everything changes. Medium <a href="https://m.signalvnoise.com/signal-v-noise-exits-medium/">becomes much nastier</a>. Tumblr <a href="https://www.theverge.com/2018/12/3/18123752/tumblr-adult-content-porn-ban-date-explicit-changes-why-safe-mode">aggressively cleans up its platform</a>. I no longer see them as viable choices to keep my personal site safe and sound. At the same time, endlessly customizing a blog no longer interests me as before. That leaves me with a simple choice: Go for a static site. I just need to focus on my writing and keep the amount of (unnecessary) tinkering to a minimum.</p>
<p>My blog is now powered by <a href="https://jekyllrb.com">Jekyll</a> and hosted on <a href="https://www.netlify.com">Netlify</a>. All blog posts are written in <a href="https://daringfireball.net/projects/markdown/syntax">Markdown</a> and pushed to a Git repository on <a href="https://gitlab.com">GitLab</a>. Changes are picked up, built, and deployed instantly by Netlify. If I want some fancy previews, I can use a separate branch for new blog posts and preview them privately before merging into master. It sounds much more complicated than, say, Medium or WordPress’ post editor, but I enjoy the total control I have. One downside thus far: It isn’t easy to blog on the go due to the lack of a native app. I can in theory set up an intricate system of <a href="https://workingcopyapp.com">Git client</a> and <a href="https://github.com/tbodt/ish">Linux shell</a> on my iPhone/iPad as a workaround, but it’s the story for another day.</p>
<p>For now, let’s end this post with a humble goal: <em>Here’s hoping I’ll be able to write at least 12 blog posts in 2019.</em></p>Anh DoAs one of my goals in 2019 is to write more, I decided to dust off my blog and migrate it to a (hopefully) longer-lasting place. I plan to write at least 12 blog posts this year.macOS Gems2019-01-21T00:00:00+00:002019-01-21T00:00:00+00:00https://anh.do/blog/macos-gems<p>In alphabetical orders:</p>
<ol>
<li><a href="https://beardedspice.github.io">BeardedSpice</a>: With this menubar app, I can use built-in media keys to control a bunch of native and web media players. The list of supported sites is long, be sure to check it out.</li>
<li><a href="http://getbumpr.com">Bumpr</a>: If you use different web browsers for whatever reasons, this app is a must. Every time you click on a link, you’ll be asked which browser to use for that one. The only downside is that you lose the ability to open links in the background. I tried to contact the authors to request this feature, but haven’t heard back from them.</li>
<li><a href="https://www.controlplaneapp.com">ControlPlane</a>: IFTTT-like app to invoke certain actions based on different ‘evidences’ such as current location, visible Wi-Fi networks, attached USB devices, etc. Sadly the app was discontinued back in 2017.</li>
<li><a href="https://www.deckset.com">Deckset</a>: Turns Markdown files into good-looking presentations.</li>
<li><a href="http://knotesapp.com">Knotes</a>: A simple viewer for Kindle’s <em>My Clippings.txt</em>. It does exactly what it says and doesn’t depend on any third party services.</li>
<li><a href="https://www.obdev.at/products/microsnitch">Micro Snitch</a>: From the same developers who made LaunchBar and Little Snitch, this menubar app lets me know whenever an app uses your microphone or webcam. Got it the day I watched <a href="https://en.wikipedia.org/wiki/Shut_Up_and_Dance_(Black_Mirror)">Shut Up and Dance</a> (lol).</li>
<li><a href="https://qotoqot.com/qbserve/">Qbserve</a>: An automatic time tracker like RescueTime, but it runs locally and doesn’t require a subscription.</li>
<li><a href="https://www.bresink.com/osx/TinkerTool.html">TinkerTool</a>: Helps me easily tweak macOS’ hidden preference settings without touching Terminal commands.</li>
<li><a href="https://itunes.apple.com/us/app/toothfairy/id1191449274?mt=12">ToothFairy</a>: This little menubar app does one thing and does it well: Helps connect Bluetooth headphones to my laptop with one click.</li>
<li><a href="https://www.rugarciap.com/turbo-boost-switcher-for-os-x/">Turbo Boost Switcher Pro</a>: Great companion for machines with Turbo Boost feature. I learned about this from <a href="https://marco.org/2018/07/31/mac-low-power-mode">Marco Arment’s blog post</a> and installed the app right away. Set it to “Disable Turbo Boost feature when: Battery not charging” and I’ve never had to worry about my MacBook Pro fans blasting all the time since.</li>
</ol>Anh DoSome lesser-known Mac apps I've relied on over the years: BeardedSpice, Bumpr, Micro Snitch, ToothFairy, etc.