2019年3月19日火曜日

三代目MacBook(Air→Pro→Air)

以前はずっとWindowsを使い続けていて、初めてMacを買ったのが2012年。
11インチのMacBook Air(64GB)でした。
iOSアプリをつくるため仕方なく導入したものなので、SSDは64GBで大丈夫だろうとケチったのですが、当時仕事でUNIX系OSを触る機会が多く、自分のPCでTerminal+bashが使えるのがやたらと便利な事に加え、トラックパッドがかなり操作し易いのでマウスを持ち運ばなくて良いのも助かるしキーボードも使いやすい。そのため、次第にWindows PCを使わなくなり、Macをメインで使うようになりました。

ただ、そうなってくるとSSDが小さい点が色々とネックになってきます。(2012年モデルのMacBook Airなら)SSDを置き換えることも不可能ではありませんが、性能アップも兼ねて2016年ごろMacBook Pro 13インチ(512GB)に買い換えました。この際に初代MacBook Airは売却(為替レートの関係で8万で買ったものが4万で売れた)。

この2代目MacBook(Pro)ですが、性能面は申し分無いです。
初代では余りにも重すぎたAndroid Studioが概ね快適に動きます。
余談ですが、Android Studio(IntelliJ)は便利ですが各種リソースをアホみたいに使うから好きにはなれません。
ただ、13インチは物理的にデカ過ぎ & 重すぎる...
たった+2インチ、されど+2インチ。
飛行機(エコノミークラス)のテーブルに載せるとかなりギリギリで切迫感がある感じになってしまいます。11インチなら余裕でスッポリ収まるのですが。
あと、バッテリー持ちも微妙に悪くて、充電出来ない機材(B787とか割と新しめの機材でもエコノミーはUSBポートぐらいしかない)だと10時間以上の長期フライトで終始使い続けることができません。(11インチでも10時間のフライト中に終始使い続けるのは困難かもしれませんが、バッテリー残量は気にならない程度に使えました)

MacBook 12インチに買い換えようかと一瞬考えたこともありますが、
・電源アダプタを会社PC(MacBookPro)と共有したいのでマグネット式が良い
・USB1ポートだけだと不便(ハブは邪魔なので常設NG)
・店頭で触ってみた限りキーボードが押しにくい(何かペチペチしてて打鍵感が足りず、恐らく他機種よりも快適なプログラミングが難しい)
・スペック比で値段が高すぎる
辺りがネックで導入を断念しました。

Retinaディスプレイって、iPhoneと違ってMacだと恩恵よりもそれによるバッテリー消費の方が気になる。ということはMacBookだとAir(非Retina)よりもバッテリー持ちが悪いかもしれない。(その辺は実際に買って長期使わないと分からないので未検証ですが)

新型のMacBook Airが登場しましたが、それは13インチしかないので検討対象外です。
11インチがあれば速攻買ったのですが残念。
13インチしか無いのにAir?(なぜそんな中途半端な機種を出したのか謎)

という訳でAppleが良い感じの機種を出すことはもう無いかもしれないと判断して、HARD OFFで2013年モデルのMacBook Air 11インチ(128GB)を購入しました。6万円ほどで。やはり、11インチのMacBook Airが一番手に馴染む。

ただし、6年前の古いモデルなので、macOSのサポート切れを考慮する必要があります。現時点で最新の 10.14 (Mojave) では、2011年以前のモデルが切り捨てられています。
・2009年モデルMacBook Airの最終OS: 10.11 (El Capitan)
・2010年モデルMacBook Airの最終OS: 10.13 (High Sierra)
・2011年モデルMacBook Airの最終OS: 10.13 (High Sierra)
・2012年モデルMacBook Air以降(まだ最新OSへアップデート可能)
High Sierraは2017年MIDに登場なので、およそ7年でサポート切れになるようです。この流れで行くと、今年で丸6年の2013年モデルはそろそろ切り捨てられるかもしれません。
スマホならともかく、PCなら10年ぐらいはサポートして欲しい気もします。去年あたりから、Macのシェアが大幅に下落していますが、恐らくこのサポートの短さに起因しているかも。2010〜2011といえば、開発者がMacを(iPhone対応の関係で)使い始めた時期に重なり、それで増加した分のシェアが一気に下落した形でしょうか。なので、小規模なアプリ開発がピークだった2012〜2014年あたりのモデルがサポート切れになれば、Macのシェアはもっとドカッと落ちるかもしれません。

公式から切り捨てられても、有志によるパッチでバージョンアップできたりします。もちろん、公式サポートの対象外ですが。私の場合、サポートが切れたらArchLinuxを入れて使う予定です。
Macで気に入っているのはOSというよりもハードなので。
だから、もうすぐ公式サポート切れになると知りつつ6万も出して購入できました。
LinuxにするとXCODEが使えなくなりますが、2代目は売却せずに残しているので当面はそれで良いかなと。ただし、なるべくメインマシン(ProではなくAir)の方でもXCODEを使いたいので、2013年モデルのサポートが長引いてくれた方が有り難いですが。

というか、11インチモデルを切らなければ普通に新品で買っても良いのですが。
モバイル用に13インチはデカ過ぎる。

2019年3月2日土曜日

自転車を買ってみた

東京で暮らしていると公共交通機関が充実しているので、自家用車やバイクは持つだけ無駄というか、何より駐車場がバカ高いし道も一方通行が複雑過ぎて運転できる自信が全くありません。ですが、道が平坦なので自転車とかなら快適に移動できそうだと前々から思っていました。(東京に住む以前に13年ぐらい住んでいた横浜は坂がヤバイぐらい沢山あるので自転車はマッチョ向けだった)
ただ、自転車を持とうにもマンションの駐輪場(月2000円ぐらい)が概ね埋まっているので空きを待つのが面倒くさい。
それなら、折りたたみ自転車を買って自宅玄関に置いておけば良かろう(駐輪場代も浮くしね!←重要)ということで、近所の自転車屋で買ってみました。
自宅玄関で折りたたんで鎮座しているマイ自転車の様子
車種はKHSのF20T。
この車種が欲しかった訳ではなく、折りたたみで一番安いのはどれ?と聞いたらコレを勧められました。お値段は6万円台後半。防犯登録、空気入れ、ライト(フロント+バック)、チェーンなどを諸々追加して8万円ちょっと。余談ですが、最近始めたFXで得られた利益が全額吹っ飛びましたw(ギャンブルで儲けたお金なんて持っていてもしょうがないから、ちゃんと消費できて良かったと考えよう)
カーナビ代わりにGoogleMapを使う為のスマホホルダーを買うのを忘れていた。まぁ、スマホホルダーはカーナビ使わないと行けないぐらい遠出をするようになってからで良いかなと思ったのですが、購入後の試し乗りで迷子になったのでやはり買っておくべきだった。まぁ、都度自転車から降りてmapを開けば良いだけなので、無いと詰むレベルではないもののあると便利な筈。(あと、折角折りたたみだから輪行バッグとかもあると便利かもしれないけど、それに至ってはもっと遠出するようにならないと不要と判断。ついでに輪行バッグは恐らく消耗品なので専門店じゃなくてAmazonで十分かなと)
ライトが結構高かった。ライトはAmazonで安いヤツがあったのでそっちでも良かったかもしれませんが、すぐに試し乗りしたかった(そして、購入時はもう夕方だった)ので割高だと思いつつ専門店で買ってしまいました。本体価格はまぁこんなもんだろうか。昔、折りたたみ自転車が結構欲しかったものの10万以上する高級品だったから手が出なかった記憶があるので、6万円台なら寧ろ安いと感じてしまった。(一応、店に行く前に今の相場をザックリとですがチェックしていて、まともなエントリーモデルは5万円前後が妥当ラインっぽいので、実際のところエントリーモデルとしては割高かもしれない)

ドンキに行けば1万円前後の激安品もありますが、折りたたみの複雑なメカニカルを安全に実装できているのか不安になるので私は買えない。別にドンキで売られている激安品が危ないと言っている訳ではなく、1万で自転車を買うなら、わざわざ折りたたみじゃなくて価格相応のシンプルな構造のものにした方が良いという話です。価格から推察するに大量生産を前提にしているだろうから、シンプルなものでも個体毎の品質にバラツキがある筈で、折りたたみだとメカニカルが複雑な分それがもっと酷くなる筈です。実際、激安折りたたみ自転車のAmazonレビューを見てみると、かなり初歩的な整備ミスによる低評価が目立ち、素人目に見てもそれだけ酷いということはすぐには気づけないもっと重要な部分が粗悪状態だったらと考えると怖すぎる。

とか言いつつ、開口一番に「一番安いのはどれ?」と聞いてしまうのは人の性。

補足すると、「こういうシーンで使いたいんだけど予算無制限ならどれがお勧めですか?」みたいなことも店員に聞いていたりする。その上でコスパを考慮して「これで良い」と判断しました。(良いものなら予算無制限で買っても良かったけど、そもそも自転車自体にあまり興味が無いことも手伝って、対価を支払う価値を見いだせなかった)

購入後、防犯登録(小一時間掛かる)が終わったらそのままお持ち帰りがてら、走行テストを実施。16:50頃に自転車店(銀座一丁目)からスタートして、先ずは気分で有楽町〜日比谷まで行き、ちょうど皇居が目についたので外周をグルッと一周。皇居ランナー達を横目に涼しい顔で追い抜いていくつもりでしたが、結構速い人が多くあまりもたもた走っていると邪魔になりそうだったので、少し汗ばむぐらいのペース配分で走行。日曜日には自転車道ができるらしいので日曜日なら良かったかもしれない。その後、日比谷公園横の道から新橋方面に出て、道に迷って繁華街をもたもたしてから自宅に到着したのが18:00頃。トータル8km弱ぐらい(外周4kmで他4km弱ぐらい)を1時間ちょっとという中々のタイムでした。

歩道や横断歩道などでは都度降りて牽引していたので、道を把握した状態で走ればもっとタイムを縮められそう。信号待ち等込みの平均時速は多分12〜13km/h前後だろうか。会社から10km圏内なら(晴れていれば)自転車で通勤できそう。電車に乗るのが嫌で会社の徒歩圏に棲んでいるのですが、もうちょっと離れた家賃の安い所に移っても良いかもしれない。(ただし、雨天時は電車を使わざるを得ないので少し考えもの...)

折りたたみ自転車だから走行性能に関しては捨てていたつもりでしたが、少し走ってみた限りかなり凄かった。感覚的にはママチャリよりロードバイクに近い。ペダルを回した時のグッと感じる推進力的なアレが。ロードバイクなんて数回しか乗ったことが無いので、あまりアテにはなりませんが、普通のスポーツ自転車並のスピードは出せそうだと思いました。(購入初日でしかも自転車に乗るのが十数年ぶりだったから当然本気は出していないから限界性能がどれぐらいなのかは未知数)

帰宅後に車種の情報を調べてみたところ、走行性能に定評があるモデルらしい。KHS(台湾人が作ったアメリカの会社)なんて名前すら知らなかったけど中々良い仕事してます。エントリーモデルにしては若干割高だと感じましたが、走行性能分のプラスαが乗っていると考えれば良い買い物だったかもしれない。走行テスト時に「10km圏内の通勤なら余裕かも」と感じたのは、この車種だからかもしれません。

ちなみ、当初はダホンのRouteを買うつもり(理由は「折りたたみ自転車界のカローラ」というネット上で見たコピーがグッときた為)だったのですが、近所の自転車屋では取り扱って無かった。別にAmazonで買ってしまっても良かったのですが、私は自転車のメンテ関連はサッパリ(パンク修理ぐらいしかできない)なので、ちゃんと自転車屋で買っておき、パンクとか不具合発生時に「こちらのお店で買ったんですが」とドヤりながら相談できる状態にしておきたかったのですが、結果的に性能が良いものが手に入って良かったです。

2019年1月10日木曜日

ファミコンでゲームを作ってRPGアツマールに投稿してみた

ニコニコ動画にRPGアツマールというRPGツクールMVで作られたゲームを投稿してプレイできるサービスがあります。
https://game.nicovideo.jp/atsumaru/?header

ただし、RPGツクールMVを使わなくてもHTML5で作ったブラウザゲームなら投稿可能なようです。実際、投稿画面にそれらしきことが書いてありました。
投稿画面の説明文
2点目に以下のように書かれています。
* ゲームの制作には「RPGツクールMV」などHTML5ゲーム制作ツールをご利用ください。
サービス名に「RPG」と銘打っているぐらいですし、RPGツクールMVを買って作って投稿するのが運営想定のユースケースなのだろうとは思います。とはいえ、ニコニコ動画の運営会社ではAkashic EngineというJavaScriptのゲームエンジンを公開していたりするので、それで作られたゲームなら一応許容範囲なのかな?

何処までが許容範囲なのか・・・気になります。

少し話は変わりますが、昨年末ファミコンのゲームプログラミングの方法を勉強して習作で1本ゲームを作ってみたのですが、世の中にはJavaScriptで作られたファミコンエミュレータが存在するので、それを使えばHTML5で動作するファミコンゲームを作ることができます。

【ファミコン習作ゲーム】
https://github.com/suzukiplan/stg-for-nes

【JavaScript製のファミコンエミュレータ】
https://github.com/bfirsh/jsnes

【習作ゲーム+jsnes】
https://github.com/suzukiplan/stg-for-nes-web

無事、ファミコン用ゲームがHTML5ゲームになりました。
※jsnesはスマホブラウザでは動かないので、スマホでは何も表示されていないかも

これを「HTML5ゲーム制作ツール」で制作したゲームと呼んで良いのか微妙な気がしないでもないですが、HTML5ゲームであることには違い無いので、これをRPGアツマールに投稿してみたところ、普通に投稿できました。
RPGアツマールの投稿管理画面
(ファイルサイズ0MBとなっていますが一応100KBぐらいあります)
以下からプレイできます。(PCブラウザ限定ですが)
https://game.nicovideo.jp/atsumaru/games/gm9628

違法な手段で入手したROMファイルを上記の方法で公開するのは当然NGですが、コレについては合法だと思っています。
このゲームのROMファイル内に含まれるプログラムやデータは、全て私自身が制作したもので、権利的にはGPLv3ライセンスで公開しているオープンソースのフリーソフトウェアです。なので、他の人が改造するなりして公開するのも(GPLライセンスを継承していれば)問題ありません。ファミコンのエミュレータ(jsnes)に関しても同じGPLv3ライセンスで、ハードウェアのエミュレーションに関しては、現時点で有効な特許や著作物(ファミコン実機内部に含まれているソフトウェアや画像等のデータ)が含まれている場合は話が変わりますが、ファミコンなら特許も切れている筈で、またIPL/OS/フォントといった著作権が発生するデータも含んでいない(そもそも無い)ので、合法だと判断しています。(ファミコンと銘打ってしまっている点が、商標権がまだ有効だと思うので少しマズイかもしれませんが、その点に関しては任天堂から商標権行使があった場合に対応するつもりです)
法律的な話を書くと少しギスギスしがちなので念の為補足すると、任天堂に喧嘩を売りたくてやっていることではないです。むしろ逆で、ファミコンは現代のゲームエンジンとしても魅力的なツールだと私は考えていて、登場から半世紀後、百年後でも新規のゲームが作り続けられる唯一のゲーム機になるだろうと割と本気で考えています。これは実際、ファミコンのゲームを作ってみて実感したことです。しかし、如何せんファミコンでゲームを作ることは大半のプログラマにとって敷居が高いと誤解されていると思っていて、「いやいや、ファミコンのゲームってこんなに簡単に作れるんですよ」と紹介したくてやってみました。

2018年8月14日火曜日

GooglePlay定期購読の解約方法について

Androidでサブスクリプション(定期購読)を提供しているアプリで退会するには、
  1. Google Play ストア Google Play を開き、
  2. メニュー  メニュー 次へ [定期購入] をタップし、
  3. 解約する定期購入をタップし、
  4. [定期購入を解約] をタップして、
  5. 画面の指示に沿って操作(退会理由のアンケートに答える)
という操作をする必要があって、やや面倒くさい。
詳しくは、以下に書かれています。
https://support.google.com/googleplay/answer/7018481?co=GENIE.Platform%3DAndroid&hl=ja

まず、「アプリ上で退会できないの?」と思うかもしれませんが、それは出来ません。
GooglePlayのライブラリが現状そういう機能を提供していないので。
ただ、これは割と正しい処置かもしれません。

GooglePlayの操作で定期購読を集中管理しているから、その方が不要な契約を整理しやすいと考えられるので。
なお、アプリからの解約は出来ませんが、アプリのサーバからの解約(cancel)なら出来ます。なので、仮にアプリに解約機能を持たせたい場合、サーバへ解約リクエストを出してサーバ側で解約処理をすることなら出来なくはなさそうです。ただし、「定期購読は基本GooglePlayで集中管理する」というスタンスからは外れるので、あまり推奨される方式ではないかも。(それが推奨される方式ならそもそもGooglePlay Billing Libraryに解約機能が入っている訳で)
とあるサブスクリプション課金を提供しているアプリのレビューでこのような意見があったのですが、
アンインストールで自動的に解約という機能はあっても良いんじゃないかと思いました。

まぁ、それをアプリに要望するのはお門違いですが。
GooglePlayが持つべき機能なので、Googleへ文句を言うべき事案だと思います。

あと詐欺云々とか言っちゃってますが、少なくとも詐欺罪は成立しないと思います。
詐欺罪とは、
1、人を欺いて財物を交付させた者
2、前項の方法により、財産上不法の利益を得、又は他人にこれを得させた者

に適用される罪で、つまり「欺いた」証拠を立件しなければ成立しないものなので。この場合、詐欺だと言いたいのなら、契約時の各種同意事項の中に嘘が書かれていたことを立件すべきであって、私が見る限り契約の解除に関する方法は正確に明示されており、当然そこに嘘等は無かったように見受けられたから、詐欺罪は成立しない筈です。(契約者が未成年者か被保佐人で法定代理人の許可無く契約を締結したのであれば取消の余地ならあるかもしれませんが)
ただ、これは法律的な話で、実際普通の成年者でも使用許諾などを完全に理解できない人の方が多い。運用レベルでは徹底的にレベルが低い人を基準にすべきなのだが、こういう仕組みを作っているGoogleの人がそもそもレベルが高い人たちしか居ないから、上手く運用レベルで噛み合っていないのではないだろうか。(つまり、詐欺だと叫びたくなるのも分からないでもない)

2018年8月12日日曜日

GooglePlay IAB(subscription)のレシート検証処理の実装 (Node.js)

AndroidのIn-App-Billing API v3でアプリ内課金(subscription)を実装したアプリ+サーバを作ったのですが、アプリの実装は簡単だった反面サーバを作るのに若干難産したので、そのことをネタに備忘録的なものを書いてみます。なお、サーバ言語はNode.js + TypeScriptです。

【①クライアントの実装】
GooglePlay Billing Libraryを使って実装します。
https://developer.android.com/google/play/billing/billing_library_overview
半日ぐらいで簡単に作れました。ライブラリ自体の使い方が(v3だけあって)かなり洗練されていることに加え、ググれば十分に情報が出てくるので、初心者でも簡単に実装できるかと思います。
つまり、クライアントの実装ネタ自体は十分にあるので本記事では割愛します。

【②サーバ実装】
subscription IABでは、購入時に発行されるreceiptをサーバへ送信し、サーバでGooglePlayへのverification(REST API)を行い、有効な状態ならコンテンツ閲覧などの機能を開放するといった形で実装します。

実装時に注意すべき点としては、APIの実行上限が20万件/日に制限されている(引き上げは出来るけど恐らく有料になる)ので、verificationが完了した状態のreceiptデータをRedisやDB等にキャッシュしておく必要がある(要するに無闇にポンポンGoogleへリクエストを投げてはいけない)事ぐらいでしょうか。

【③verification API】
GooglePlay developer APIのPurchases.proudcts:getを用いて検証します。
https://developer.android.com/google/play/developer-api?hl=ja
https://developers.google.com/android-publisher/api-ref/purchases/products/get

Requires AuthorizationなAPIなので、予めGooglePlay developer consoleでサービスアカウントを作成して、JWT認証できるようにしておく必要があります。

APIは普通にHTTP clientで書いても良いかと思いますが、様々なサーバ言語向けライブラリが用意されていて、少なくともauth系のAPIはライブラリを使用することが(Googleから)推奨されています。
https://developers.google.com/android-publisher/libraries

上記ページには、現時点でJavaとPhytonしかありませんが、ページを辿っていくとNode.jsのライブラリもありました。ただし、Alpha版(この時点で嵐の予感)。
https://github.com/google/google-api-nodejs-client

とりあえず、上記ライブラリでJWT認証+purchases APIを実装してみた。ところが、JWT認証は上手くいったのですが、purchases APIが全然上手く動かない。「Invalid Value」というエラーで失敗するのですが、何処がinvalidなのやら...。

StackOverflow等で調べてもv2以前の情報しか載っていなくて、一応v3の実装自体は入っているけどexampleとか一切無い状態。
https://github.com/google/google-api-nodejs-client/tree/master/src/apis/androidpublisher
やる気が感じられない...せめてどうやって実装するか切り口となる説明ぐらいREADME.mdに書いて欲しい。なので、JWT認証はライブラリで行いつつnode-rest-clientで直にpurchases APIを実行するのが、現時点で最も無難な選択肢だろうと判断しました。

以下、上記の方式で実装したコードを晒します。

【④必要なパッケージ】
npm install --save googleapis
npm install --save node-rest-client
npm install --save xml2js
※xml2jsを入れないとnode-rest-clientのコンストラクタでモジュール不整合が起きる

【⑤実装】
const RestClient = require('node-rest-client');
const { google } = require('googleapis');
const authClient = new google.auth.JWT({
    email: サービスアカウントのEメール,
    key: サービスアカウントのプライベートキー,
    scopes: ['https://www.googleapis.com/auth/androidpublisher']
});

const restClient = new RestClient.Client();

(略)

authClient.authorize((error, tokens) => {
    if (error) {
        略(認証エラー時の処理)
        return;
    }
    const url = 
        "https://www.googleapis.com/androidpublisher/v3/applications/"
        + receipt.packageName + "/purchases/subscriptions/"
        + receipt.productId + "/tokens/" + receipt.purchaseToken
        + "?access_token=" + tokens.access_token;
    restClient.get(url, {
        headers: {
            'Content-Type': 'application/json'
        }
    }, (data, response) => {
        if (200 != response.statusCode) {
            略(APIエラー時の処理)
        } else {
            receiptExpire = data.expiryTimeMillis;
            略(成功時の処理)
        }
    });
});

2018年4月22日日曜日

東方VGS Lite 1.0.2 (不具合対策版)

不具合対策版の東方VGS Lite 1.0.2 を先程(AM2:30頃)リリースしました。
曲の再生が途中で止まってしまうという連絡を受けて調査していたのですが、結構難航しました。

デベロッパーコンソールで確認した限り、クラッシュレポートが挙がってきているので、アプリ側のバグであることは間違い無いのですが...
色々と厄介そうな感じです。

まず、「発生元不明」ってのが厄介そうですね。これは恐らく、stack traceを吐かずに強制したものと推測できるので、大方ActivityManager辺りにkillされたのだろうと思います。まぁ、それ自体はAndroidならよくある事です。

最も厄介なのは、私が再現環境(Android5.0以降の実機)を持っていないことです。(私物のスマホはiPhoneなんですよねぇ)

何とか知り合いからNexus6を借りることができたので、それで実機確認してみたところ、それらしき現象を確認。再現できればもう勝ったも同然だと思っていたのですが、そこからがまた長かった。

どういう修正をしたのかは、アプリのアップデート内容に無駄に事細かに書いておきましたが、(1)の修正が恐らく決め手です。これで治ってくれる・・・はず。
無駄に事細かに書いておいた修正内容
(500字制限なので実はこれでも結構削った)

2018年4月7日土曜日

東方VGS Liteを公開

GooglePlayで公開しました。
https://play.google.com/store/apps/details?id=com.suzukiplan.tohovgs2
開発着手から約2週間でリリースという超短期間で完成させたのですが、旧東方VGSのソースコードは1行も使っていなくて、完全フルスクラッチで作り直しました。言語はKotlinで。

音源モジュール部分はC言語(下記)ですが。
https://github.com/suzukiplan/vgs-bgm-decoder

言語の構成比率としては下図のような感じです。

ここまで短期間(実働では3人日ぐらい)で作れたのは、Kotlinの言語としての良し悪しというよりは、Android Studio(IntelliJ)の生産効率がメチャクチャ高いからですね。単純に私の開発速度が尋常じゃなく速いのもあるのですが、それでもiPhoneアプリで同じものを作ろうとしたら最低でも3倍(10人日)ぐらい掛かります。

iOS版の東方VGS Liteは多分作らないです。

合理的ではないものを作りたい

ここ最近、実機版の東方VGSの開発が忙しくて、東方VGSの曲追加が滞っています。 東方VGS(実機版)のデザインを作りながら検討中。基本レトロUIベースですがシークバーはモダンに倣おうかな…とか pic.twitter.com/YOYprlDsYD — SUZUKI PLAN (...