2016年1月25日月曜日

ツイッターWebのページ遷移の仕組みについて調べた

私が作ったMuting on Twitterというユーザースクリプトはその名の通り,
ツイッターWeb(Twitter Web Client)と検索ページでよくあるミュート機能を使えるようにする
というものです.
長らく悩ませていたページ遷移問題に決着をつけることができた(と思う)ので,それについてここに書いておきます.

ページ遷移問題とは

ページ遷移しても別ページ扱いにならず,ホームに戻った時にスクリプトが死んでる.

原因

別ページに飛んだ場合,ページが変わるわけではなく,中身のHTMLのコンテンツ部分が切り替わる.
そのため,ホームに戻った場合,HTMLが切り替わってしまうのでスクリプトも(見た目上は)死んでる.

解決するために必要なこと

  • ページの切り替わりを監視する
  • 動的にHTMLをまた作り直す
  • 変数に格納したノードも死んでるので再び格納する

修正

まず.ページの切り替わりがわからないと何もできない.
デベロッパーツールを開いてページが切り替わる際のHTMLを見てみると,
BODYタグが変更されたのがまず目についたのでMutationObserverを使って監視してみる.
(MutationObserverはとても面白いAPIなので,またどこかに書きます.)
するとクラス名やスタイルがコロコロと変わることが確認できた.
しかし1回の変更部分が多くて条件を書くのがちょっと大変だし,判定漏れする可能性もあった.
そこで他にも変更があったノードの一つ,div#docを監視してみた.
すると少ない変更部分でページ切り替えを感知することができたのでそちらを監視対象にすることにした.
どのような判定で再処理を行っているかはコードを参照.

なお,ページによっては別ページ扱いになる場合もあったので,
以下にホームから各ページに遷移した場合の扱いをまとめた.
  • 別ページ扱い
    • リスト
    • ヘルプ
    • おすすめユーザー
    • Twitterについて
    • 規約
    • プライバシー
    • クッキー
    • 広告ヘルプ
    • ブランド
    • ブログ
    • ステータス
    • アプリ連携
    • 採用情報
    • 広告管理画面
    • 広告掲載方法
    • メディア
    • 開発者
    • おすすめユーザー部分
  • 別タブで開く
    • Twitter広告
    • アナリティクス
あとはページがホームor検索の時に再びHTMLを動的に作って,必要なノードを格納するだけ.
イベントリスナーなどの1回きりの処理とそうでない処理を分けて,ページ切り替え時に後者を実行する.

まとめ

ページ遷移に対応できた.
しかし,別ページにいる時間が長い,もしくはさらに別ページに遷移した場合,再構成できないことがあった.
詳しい条件がわからないので,判定をすり抜けたのか,切り替えを感知できなかったのかは断言できない.
そのどちらでもないとしたら新たな解決法を探す必要がある.
また追ってその問題は確認したいと思う.
もし再現できた人はどこでもいいので教えて欲しい.

追記(17:17:40)

報告により原因が解明できた.

他のページ(ユーザーページなど)を起点としてホームや検索に行った場合,ホームと検索以外ではスクリプトが動かないから,当然スクリプトは動いてない状態だしページ内移動扱いだから新たにスクリプトが動くこともない

これは例えばユーザーページへアドレスバーとかブックマークとかで移動した場合に限らず,ホームや検索で別ページ扱いになるページに移動した後,上部の「ホーム」でホームに戻った場合も該当する.
ホームを出す(スクリプト動く)→別ページに行く (ページが新たに読み込まれる.スクリプト死ぬ)→ホームに行く(ページ内移動扱いなのでHTMLが切り替わるだけで,ページは再読み込みされないし当然スクリプトは実行されない)

解決法として,スクリプトが動く範囲を Twitterのページ全てにすることでどのページでも動くようにした
しかし内部のページ読み込み(iFrame)でも反応してしまうので,そこらへんのページの除外を地道にやっていく必要がある
十分に検証をしたら修正版をあげる

追記(2016/01/27)

修正版を上げた.もしexcludeに不足があれば今後修正していく

2015年12月24日木曜日

ユーザースクリプトを書くときにjQueryを使おうと思ったけど変なところがあったので詰まったのを解決?した話

おさらい

ユーザースクリプトでjQueryを使う時は,
@require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
のように宣言してjQueryを利用します.
コンフリクトした場合は,
this.$ = this.jQuery = jQuery.noConflict(true);
と書くと回避できます.
ここらへんは公式のリファレンスを見てもらったほうが早いと思います.

実は…

Chrome+Tampermonkeyだと何もしなくても使えます.
ウェブページのjQueryを自動的に適用してくれているみたいです.
なのでChromeでは詰まりませんでした.

しかし

Firefox+Greasemonkeyではそうはいかないので素直に@requireして使います.
だけど正しく動かない.
あるノードのイベント一覧を取得したかったのですが,
なぜかundefined,未定義と言われてしまう….
しかしコンソールから同じコードを実行するとちゃんとイベント一覧が取れる!
ドキュメントの読み込みのタイミングかと思いましたがそうではありませんでした.

原因

Chromeではなぜか動くということから無事糸口を見つけることができました.
読み込んだjQueryではなくウェブページのjQueryを使う必要があったのです!!!
それぞれのjQueryが完結しているみたいなので,外部からは触れられないっていう話だと思います.
なのでjQueryで実行部分をスクリプトタグの中に入れて,スクリプトタグをページに挿入し,
該当スクリプトをページ内で実行させるようにしました.
(ユーザースクリプトからウェブページのjQueryを利用する方法がわからなかった…)
そうすることで無事,FirefoxでもChromeでも動くようになりました!

ちなみに

そのユーザースクリプトというのがこれ
右クリック禁止とかコピペ禁止を禁止するスクリプトです.

2015年12月13日日曜日

Android用Twitterクライアント「Peafowl」を作りました

この記事は「Twitterクライアント開発マン Advent Calendar 2015」の13日目の記事です

***

機能とかスクリーンショットとかはこちら
Google Playのリンクはここです


世の中には数多くのTwitterクライアントがあるのになぜ作ったのかというと,
・Androidアプリの勉強をしたかった
・Twitterをそれなりに使っているので作りやすいんじゃないか
という理由です.

デザインはみなさんお馴染みのマテリアルデザインを元に設計しています.
ガイドラインを見れば大体なんとかなります.
すごく細かく書いてあるので何か困ったらガイドラインっていう感じです.
それでもわからなかったり腑に落ちなかったりした場合は,
Google謹製のアプリのデザインやMaterialUpを参考にしました.
前者に関してはデザイン作ったのはいいけど実際に動かしてみたらどうなんだろう,
というのがわかるのでオススメです.
後者に関してはデザインのアイデアが浮かばないな〜〜〜っていうときにオススメです.
それを作るかどうかはともかくとして,とてもいい刺激になります.

システムは公式で使える機能を網羅するように頑張りました
それだけじゃなくて細かいところに手が届くように気を配りました
ですので一応「多機能」と謳っていますが多分他のクライアントのほうが機能がある…と思います
まだまだ実装したい機能があるので今後のアップデートで追いつきたい!です!


最初のリリースということで不具合があるかもしれませんが,
継続的にアップデートを行っていくつもりです.
もしよかったら使ってみてください!