Monday, April 12, 2021

Bookmarklets for Sharing

Android has Share intents, which are a way to send a string, frequently a URL, to another program.

The receiving program can even be a PWA. This means it is fairly easy to write a new target to share on Android, such as a note-taking website or a link aggregator.

On a desktop browser, the standard tools are less easy. There's no simple share command. Many apps, such as Pocket and Google Keep, implement this functionality with a browser extension. Browser extensions are much more involved to write than PWAs, and I find the buttons to activate extensions inconvenient to manage. In addition, you have to write a different extension for every browser you want to support.

I found a much better solution for my purposes: bookmarklets.

Bookmarklets are bookmarks that, instead of constaining a URL, have a snippet of JavaScript. When clicked, the bookmark's JavaScript executes in the current page.

Obviously, this has all the danger of running custom JavaScript on any page. Never run any you don't trust: it can trivially steal your cookies and other authentication, or perform any action you could on the page.

That being said, creating one yourself is very simple. You create a new bookmark (the "Add Page" option in Chrome), give it the title you want, and then write the JavaScript to execute, preceded by javascript:. The most inconvenient thing is that it all has to be on one line, so it's usually worth working the details out elsewhere, removing the newlines, and copying it in.

I have found two bookmarklets to be useful (the comment header is required by my employer, however, you will not be able to copy it into your bookmarklets).

Background Send

// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
javascript:const _u = new URL("https://example.com/save.cgi"); _u.searchParams.set("url", location.href); fetch(_u, {mode: "no-cors"});
This bookmarklet sends the current URL to a server for processing. I use this for link aggregators where the only relevant information is the URL itself. It uses the new fetch() API to send a GET request (it uses no-cors mode because the whole point is that the destination is a different server).

The server that receives the message just expects a URL in a GET parameter and handles it. Since no special page is seen by the user, this is most akin to the very lightweight share intents in Android like Pocket has, which do not interrupt the current screen.

Because this is GET, no real authentication is possible, so for a real use I would probably require HTTPS and include a unique key in another GET parameter that needs to match. This means it shouldn't be run on an untrusted browser, but that's already true for bookmarklets.

Sharing Window

// Copyright 2021 Google LLC.
// SPDX-License-Identifier: Apache-2.0
javascript:const _u = new URL("https://example.com/share.html"); _u.searchParams.set("text", location.href); const _a = document.createElement("a"); _a.setAttribute("target", "_blank"); _a.setAttribute("href", _u.toString()); _a.click()
The second useful bookmarklet creates an <a> tag, target=_blank, with an HREF that includes the current URL in a GET parameter, then clicks the link. This means that clicking the bookmarklet opens a new page with data that includes the previous page's URL. This is exactly like the experience of most Android apps when you share to them, in which selecting share takes you to a new page that you can use to make some choices on the data you included.

In fact, I was able to use this second form of bookmarklet to work with the exact same URL I had already written for share intents in a PWA.

Usage

To conserve space on my bookmarks bar, I'm giving these short names, just a character or two, or even an emoji (inspired by this article about using favicons alone for bookmark names, but bookmarklets don't support favicons.)

For the moment I am putting these directly on my bookmarks bar. If I make enough that even with short names I start to run out of space, I will probably put them all into a single folder, possibly named "Share". This will mimic the Android share button that when pressed reveals a list of possible applications (but will load much faster).

I hope this is useful for someone else!

Postscript

I discovered Use Bookmarklets on Chrome on Android, which points out that you can invoke bookmarklets by name if you are using Chrome and synced it to an Android device. I'm not sure whether this works for other mobile browsers, or for Chrome on iOS, and the original purpose here was to supplement a desktop computer with a mobile-inspired feature, but there might be some cool combinations possible with this.

Friday, September 18, 2020

Watch Charger Support

 I have a (Google) Wear OS smartwatch, the LG Watch R. It's pretty old now (for a smartwatch), and a few months ago, the strap broke. I bought a nice purple replacement.

But, the replacement strap is made of a much firmer material than the old one was. Now, the watch won't easily sit in its charging cradle, because the straps push down and lift the watch up, making it difficult to charge.

The charging cradle for the LG Watch R, a plastic disk with a raised lip to hold the watch in place, and metal contacts.
The charging cradle for the LG Watch R, a plastic disk with a raised lip to hold the watch in place, and metal contacts.

The charging cradle from above, with the watch unable to sit on it correctly.Another view of the watch unable to sit on the charger
The misalignment means the contacts in the cradle don't line up with the watch's. Even when they do align, sometimes there's too little pressure for the watch to charge consistently.

There are chargers which are lifted higher to help solve this problem, but I don't have one (well, I do, but it's in the office that I haven't been to since March).

For a while, I was solving the problem just by balancing the charger on a small box, but this was easy to knock over, as it was too light and didn't help hold the charger in place.

I decided to make a support out of air drying clay.
A hollow cylinder made of coiled white air drying clay, about an inch and a half tallThe same cylinder viewed from above, showing how it is hollow.


It was easy enough to use the standard coil like for a pot. Since I didn't need to hold anything inside it, I didn't make a bottom.

For the top, I tapered the clay so that the spiral would flatten out. I also pressed the charger down onto the wet clay, making a better surface for it to sit on. I pinched out the three ridges along the edge, and supported them with additional clay, to help keep the charger put.

Around this point I was inspired by clay items I've seen before like these:
A Roman bowl with designs on the outside
An Incan plate with painted designs on the surface and a handle

While mine looked rather boring by comparison. I used one of my clay tools to push a series of little triangles all up the coil, kind of suggesting scales on a snake.

When it had dried, I found that the "scales" gave it a particularly nice texture to hold.

Drying shrinks this kind of clay slightly, so there was a chance that it wouldn't work out when I placed the charger back on top of it.

I'm glad to say that it worked!

The charging cradle from above sitting on top of the clay support.

The watch sitting snugly in the charging cradle, which is lifted by the support.

Possible next steps include adding a mild adhesive to keep the clay in place, and attaching the wire to the side of the cabinet to keep it from getting in the way.




Sunday, August 9, 2020

Recording Ideas

I had intended for this to mostly be a project blog, but I've found it harder to document them than I'd like, so posting has been slow.

In addition, there keep being concepts I tell to several people and I would like to be able to point back to. Especially when there's a key idea that I might miss some pieces of later. So, fine, I guess I'll make an "ideas" category and put some things in it.

To try to stay on theme a little more, I'll note how formulating an idea can be a process a lot like building something, for me. It likely starts with a sense of what I want the end to be, but no clear plan for how to get there. Or, it can start with some raw materials that I want to combine well. I can let the raw materials, whether they are the focus or not, spin around in my head for a while, and I often seem to expect that I'll be able to come up with a complete image just with the power of my mind.

Often, this isn't true. There are too many variables and possibilities, often with no clear way to choose among them. They can be equally good, or hard to evaluate. I benefit a lot from getting started in some way that narrows things down. For projects, this often means taking the first few parts and picking a configuration to put them together. Either it works and now I have a real starting place, or it doesn't and I learn from that. For an idea, the key is getting out of my head and applying language, which might mean writing it out, or might mean telling someone. For writing, I have to overcome the tendency to skip over what I "know," because if I do then I'm back where I started, stuck. Better to write the obvious parts, as has to happen when I frame an idea in a conversation, and then I can start to progress. It works surprisingly well.

Saturday, March 7, 2020

Departure Board

Update: I have released the source for this, which is owned but not officially supported by Google. My partner named it the Charlie Board. It can be found at https://github.com/epw/charlie-board.

I live on a fairly busy road, with three bus lines that go past my house in both directions. They have stops within a two minutes' walk from my house. But, being the MBTA, their actual timing is random and unpredictable.

However, the MBTA does deserve some credit. All the buses are now equipped with GPS, and their locations are easily queryable using the MBTA v3 API.

I decided to make a departure board, like the Cambridge Public Library has.


The departure board consists of a flatscreen monitor mounted to the wall in my front hall, with a Raspberry Pi for the brains. The Pi runs a Web server with a page that queries the MBTA and displays upcoming departures. The page refreshes once a minute. Finally, the Pi is configured to start Chrome in "Kiosk mode" when it boots, making a fullscreen version of the page with no extra Chrome popup messages (like "Restore session?"). Together, this makes the board function easily with its one purpose, providing information that is as up-to-date as possible even if the Pi spontaneously reboots.

I iterated on the UI, starting with a very simple one that showed the data coming through:

Before moving to the current setup, that uses a background that is less bright, particularly at night, and making the values much more reader-friendly.

To save power when it isn't being used, I added a pair of cron jobs to turn the screen off at 1am and back on at 5am. This still wastes some power, when no-one is home, but as I haven't been able to make a presence detector yet, this still turns it off for 4 hours a day when it surely wouldn't help.

crontab:
0 5 * * * /home/pi/bin/turn-on-screen
0 1 * * * /home/pi/bin/turn-off-screen
turn-on-screen:
vcgencmd display_power 1 > /dev/null
turn-off-screen:
vcgencmd display_power 0 > /dev/null
 
I think these should work for any HDMI screen controlled by a Raspberry Pi, but this is the only one I've tested it on.

I also have slowly added trains as they became useful. I'm looking forwards to adding Green Line trains when the new stop opens, since it's not much further from my house than the bus stops are.



What Comes Next?

This has been pretty stable. I don't have to make changes very often these days, and changes are easy when I do need to. It's been serving its purpose, making it easy to plan when trying to get somewhere in a hurry, and encouraging me to head outside for a trip when I don't have much to do.

The main limitation is that it's just in the one place. And it's true, there are lots of other sources of MBTA information, like the useful Transit app, but the screen shows the value of having the departure information available at just a thought, without even having to take out a phone.

I don't want to put screens for this all over my house, but I do have Google Homes on every floor. This seems like the next place to go. Making it answer "When does the CT2 bus leave?" would probably be quite useful.

Tuesday, December 10, 2019

Birthday Card

I recently took a class on how to make embossed greeting cards. My girlfriend's birthday was coming up, so I decided to make one for her.
Photo of me holding a yellow envelope with a card inside.
The finished product! You can see small unevenness in the envelope but overall I think it came out well.
The envelope started as a square of medium-thick paper. I folded it along four lines with the help of a scoring board. I then centered a paper stencil under what would become the back of the envelope, and used an embossing stylus, rubbing quickly on the paper like I was taking a rubbing with a crayon. This kind of scratches up the side of the paper so it's important to do on the inside of the envelope. To finish, I cut a few small triangles out of the paper, and folded to make an envelope that I could glue together.
For the card itself, I used a nice, thick card-weight paper. I wanted a cutout of a moon and stars for the front, and a message on the inside. I had access to a laser cutter I know how to use, so decided to go with that. My first tests showed that the side facing away from the laser would have some visible charring when cutting, while the side facing the laser was clear. This meant I needed to run twice, cutting on one side of the paper and etching on the other, since it would be folded over and the inside of the front was going to be hidden. This also meant I had to be very careful about how I oriented things, to avoid flipping the cutouts.

A couple things that came up while working on the card with the laser cutter:
  • I'm pretty sure that the moon shape I cut out was incorrect. I thought about what the actual shapes would be but it was too hard to calculate, so I just used an SVG file off the internet.
  • Weirdly, the font I used for the engraved message had no exclamation point, so I had to use a separate piece of text with a separate font for that.
Finally, I cut a piece of the silvery paper down to about the card's size, painted glue onto the inside of the front of the card, being careful not to get too much on the edges of the holes, and let it set with something heavy on top of the closed card for a few minutes. It wasn't terribly well attached, but worked well enough for a card. I also trimmed some stray edges using it a straightedge and rolling paper cutting blade.
Photo of the front of the card, which is white and has a crescent Moon and four small star cutouts. A glittery silver background shows through.
The front of the finished card!
Photo of the inside of the card, with "Happy Birthday Alyssa!" laser etched. It looks like it's printed in tan ink
Inside the card. The left is actually the back of the silvery paper. It's covering the charred edges of the cut-out moon and stars. The writing on the right is laser etching, which I didn't realize would have this nice gold color.
All in all, I think this took me about 2 hours. However, that was entirely after the class. I could have made this card during the class, but I made too many mistakes in my first attempts and decided to start over after it was done.

Mistakes and Failures
The main troubles I had were in orienting the paper. On my first few tries for the envelope, I either embossed on the wrong side, or forgot to until I had already glued it together. I also glued without really thinking about what was happening, and as a result one time glued the envelope entirely shut. For making the card, I had the charred side for the laser cutter the visible on the outside one time, and another time I had folded the card before putting it into laser cutter, and the laser pretty much require that it be perfectly flat. When I was gluing the silvery backing on, I put too much glue around the stars, and it leaked through and stuck to the paper underneath, ruining that card. I made a reminder sheet to keep visible for when I actually made the card, which helped me look out for some of these common mistakes.

Saturday, December 7, 2019

Hello World, but for a project blog

Hello! I'm Eric (my.pronoun.is/he) Sometimes I make things, and it would be nice to be able to share what I did and learned. I don't like any of the current social media platforms for this, and I think the way blogs have been somewhat abandoned in the past decade was a mistake. So, here's a new one.

A couple housekeeping notes:
  1. The writing, views, and opinions expressed here are entirely my own, and do not represent my employer in any way. Please don't try to take them as such.
  2. This blog should be welcoming to all who are interested and are similarly welcoming. As such, this blog has no room for racism, sexism, classism, homophobia, transphobia, ableism, or other forms of discrimination. When I mess up and am unwelcoming, please contact me, privately if you wish, and let me know. I will listen, and try to understand and fix it. However, if me bringing this these ground rules up makes you uncomfortable, then that is working as intended. There is no room for fallacies around the Paradox of Tolerance here.