hogashi.*

日記から何から

日記

f:id:hogashi:20210802205133j:image

 今日はなぜかかなり滅入っていて、ひとまず歩くかと思って外に出たけど、目当ての店は閉まっており、そうか〜とか言いながら川まで来たりしている。下りたらところどころ花火の煙が上がっていて、地面から蛙と虫の声がして、水が背景になっていた。

 目に映る景色のうち、かなりのものが残せるようになった。言葉は元より、写真も技術の進歩が進み、きめ細かで鮮やかな場面を切り取る。切り取ってからさらに手を入れている、という非難もあるけど、少なくとも自分がそのときを思い出すための道具としてならどうあってもいいと勝手に思っている。

f:id:hogashi:20210802205930j:image

 まだ難しいなと感じるのは連続したシーンで、録画などをしてもあまりしっくりこないことが多い。どちらかといえば、その残した録画を見たときに、当時のハッとした心持ちを思い出せない。これは、技術的に写真ほど細やかに残らないからなのか、残してみるとなんだそんなものかとなってしまうからなのかわからない。後者は写真にも少し感じるものだけど、動画で顕著だと感じる。

f:id:hogashi:20210802211406j:image
 ところで、普段おもしろいと感じるときのひとつに、わからない部分がある光景を、自分の頭の引き出しをどんどん開けて理解しようとするとき、があるのではないかと思っている。落語を見て実際のシーンを勝手に思い浮かべるのが典型的だけど、映画でも速さや重さなどをイメージして確かに疲れそうと考えたりする。

 似た話題で、録画に対して考える余地を見出だせず、つまり記憶を呼び起こせないので、当時の気持ちとずれるのかも、と考えることはできそう。写真は時間の軸の分の余地があるので、より思い出す余地が残されているということになる。

f:id:hogashi:20210802212853j:image

 情報量が減ればよいというものではなくて、それぞれの量によって生まれる余地が変わりそう。言葉だけなら色も想像することになるし、録画でも気温やその前後なども思い浮かべられるはずではある。個人的に今そのバランスが合うのが言葉〜落語〜写真くらいなのかな、と思った。

f:id:hogashi:20210802203823j:image

 結局今日は渡ったことのない橋を渡れたので収穫があった。そのうちパックマンみたいに歩き尽くしてしまうだろうけど、幸いこちらは忘れることができるし、意外と道の様子ががらりと変わることもあるはず。ここに楽しむ余地がある。

 

>はてなインターネット文学賞「記憶に残っている、あの日」

 

Chrome拡張機能をManifestV3に上げる活動

 規模の小さい chrome-usercss-hogashi - Chrome ウェブストア から始めてみている。

 Manifest V3 migration checklist - Chrome Developers を見ると結構色々ある。いっこずつ対応していったらよいのだけど、難関だったのは background pages の Service Worker 化。

 色々 Google で検索しまくった結果、 localStorage を使っていたので Service Worker として invalid だったっぽい。のだけどエラーメッセージに何も現れてこなくてめちゃくちゃむずかった。

 Service Worker で使える localStorage の代替を調べると、 chrome.storage というのがある。これは Chrome 拡張機能の機能として存在していて、 permission に storage とか足すと使える。

developer.chrome.com

 データとしては key/value なのだけど、呼び出しが非同期になっている(あと callback 形式)ので、単純に置き換えはできなくて、ちまちま Promise に包んで使うように変えたりした。

 これでいいかと思ったらもう一回ハマって、 background pages からの sendMessage への応答 (sendResponse) が非同期だとおかしくなることがわかった。具体的には Unchecked runtime.lastError: The message port closed before a response was received みたいなエラーが出ていて、 sendResponse で返したはずの値が返っていない。

stackoverflow.com

 この stackoverflow の回答はめちゃくちゃおもてなし度があって、 Chrome 拡張機能を使っている側としてはそのエラーを出してる拡張機能を消したら解決するけど、開発側としてはそのエラー自体への対処を知りたいよね、そういう目的で見に来た人に向けて書くね、みたいな内容で助かった。

 それっぽいコードを書くと、 Promise が返る関数を呼んだとして、その then で sendResponse するような書き方にしたときにこうなる。

chrome.runtime.onMessage.addListener(() => {
  myAsyncFunction().then(result => {
    sendResponse(result);
  });
});

 MDN を見ると、非同期に返す方法は 2通りあると書かれている。

To send an asynchronous response, there are two options:

  • return true from the event listener. This keeps the sendResponse() function valid after the listener returns, so you can call it later. See an example.
  • return a Promise from the event listener, and resolve when you have the response (or reject it in case of an error). See an example.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage

 イベントリスナから Promise を返すほうでやってみたけど、全然うまくいかなかった (なんかミスっているかもしれない……)。ここで Chrome 拡張機能API ドキュメントを見に行くと、非同期ならイベントリスナからは true を返してくれと書かれていた。実際 true を返すほうでやって解決した。 Chrome 拡張機能のほうは Promise を返すほうに対応してないのかも?

This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).

https://developer.chrome.com/docs/extensions/reference/runtime/#event-onMessage

 のでこういう感じでできた。

  chrome.runtime.onMessage.addListener(() => {
    myAsyncFunction().then(result => {
      sendResponse(result);
    });
+   return true;
  });

 chrome.storage に切り替えるけど、 localStorage のほうで育ててきた UserCSS が消えるともの悲しいので、ちゃんと localStorage からのデータ移行もやることにしている。 onInstalled で自動で移行するので基本的には意識しなくていいようにしたけど、何かの拍子におかしくなったとき用に、 localStorage からのエクスポートも別に用意した。ということは、移行中は (localStorage 使うので) Manifest V3 にはできないので、もうしばらく V2 のままでいる必要がある。

f:id:hogashi:20210801184132p:plain

 これでみなさまがデータ移行できたら Manifest V3 に上げてよい、となるのだけど、できたよ〜みたいなデータを送信したりしないことにしているので、どのくらい待つのがいいのかむずい (普通に使っていたら数ヶ月くらいで十分な気もする)。

 夢、死んだがそのまま起き上がり過ごす。脈がないことを自分で確認しつつ、なんとなく焦ったまま日が暮れる。自宅に帰ってからタピオカのストローくらいの管を手のひらから手首にかけて入れて何かを注射して蘇生される。

 経験したうちでは中の上くらいの悪夢だけど、神経のすり減り度は高かった。木更津キャッツアイ(かなり昔見た、最近思い出して予告を見て懐かしんだ)やバイオハザード8(最近出てたやつ、やってるの見ただけでやってはいない)などの影響がありそう。

 

あえて順序を逆にするとどうか

 Twitter でバズっているツイートにはリンクがないことが多い、という感覚は、逆にリンクがあるときはリンクを開いて満足してしまうということかもね、という会話をした。気をひく文や画像でも、リンクがあったら開いてしまい、ある程度納得してしまうのではないか、リンクがないときはなんだこれと思ったまま (他の人にも聞いて回るような具合で) RT するのではないか、みたいな仮説が立った。

 リンクがないことで、より RT に結びつく、というのは、今まで感じていた因果と順序が逆で面白かった。因果が逆そうだな〜みたいなときでも意外と逆のままにして (あるいはあえて逆にして) 考えるとわかる事柄もありそう。

 缶をミスってつぶしたのでちょっとでも戻そうとしたところ四角く戻った。断面の面積に思いをはせて、そういえば、長方形のうち全部の辺の長さが一定のとき面積が一番大きいのは正方形、というのは習ったけど、正方形と円だとどっちが大きいのか、と思って雑に計算した。合ってるかは自信は無い。

続きを読む

いまの天気でブログの背景を変える

 ブログの背景を京都のいまの天気によって切り替えてみたくなって OpenWeather という天気 API を使って素朴に background-image を切り替えるようにした。アカウント作ったら API が使えて便利、ちょろっと js 書いて完成した。いま京都は曇りです。

openweathermap.org

 写真は過去に取ってたやつを使っている、冬が好きなので夏だけど問答無用で雪の様子が出ます。

/* 京都の天気で背景変える */
const url = 'https://api.openweathermap.org/data/2.5/weather?lat=35&lon=135.7&units=Metric&appid=xxx';
fetch(url).then(res => res.json()).then(json => {
  const weather = json.weather;
  if (!weather || !weather[0]) { return; }
  const mainWeather = weather[0].main;
  const backgroundImageSrcs = {
    Clear: 'https://cdn-ak.f.st-hatena.com/images/fotolife/h/hogashi/20210715/20210715000656_original.jpg',
    Clouds: 'https://cdn-ak.f.st-hatena.com/images/fotolife/h/hogashi/20210714/20210714235934_original.jpg',
    Rain: 'https://cdn-ak.f.st-hatena.com/images/fotolife/h/hogashi/20210714/20210714233101_original.jpg',
    Snow: 'https://cdn-ak.f.st-hatena.com/images/fotolife/h/hogashi/20210714/20210714233101_original.jpg',
  };

  const imageSrc = backgroundImageSrcs[mainWeather];
  document.querySelector('html').style.backgroundImage = `url('${imageSrc}')`;
});
html {
  background: top / contain repeat-y url('');
}

body {
  /* 写真そのままだと見づらいこともあるのでちょっと白くする */
  background-color: rgba(255, 255, 255, 0.4);
}

 天気の API 探したらこの記事を見つけたので見つつやってて、確かにアカウントつくった直後は API 使えなかったけどちょっと待ったら使えるようになるみたいな感じだった。

dev.classmethod.jp