無限スクロール中毒防止のChrome拡張機能を作った話

# 結論 作ったもの

"No Infinite Scroll"
インストールをすると無限スクロールを検知するたびに、
**「本当に初めやろうとしてたことやってるのか？考え直せ！」**
という趣旨の叱咤激励で戒めてくれます。
**無限スクロール界隈の大御所、Twitterとかを開くと警告が出まくり使う気がなくなるというメリットがあります。**

https://chrome.google.com/webstore/detail/no-infinite-scroll/egkkpoeccfplbjcdmflpjbjfofhcfmad?hl=ja&authuser=0

# エンジニア,ネットサーフィン多い問題
Googleや公式ドキュメントとStackoverflowを往復する日々。
個人的には、最近バックエンド系のDocker,Ansible,Linuxの勉強をしていると、エラーの対処のために一日中こうしたサイトを往復することが多いです。


# なんでついでにTwitterとか見ちゃう？
上のような問題の中、関係ないTwitterとかニュースサイトとかついついチェックしたくなる。
なんで？と思ってよくよく考えたら、
**この手のサイトは無限にコンテンツが出てくるから中毒性が高いのでは？**
と思うようになった。

# 底無し沼 ”無限スクロール”
無限スクロールのあるサイトでは、中毒性が高く時間を溶かすわりに、価値の薄い情報や広告に晒される。

**こうした情報の氾濫の中で、ネットサーフィンが仕事柄のエンジニアは、集中を保つことは年々難しくなっているのではないでしょうか？**

世界では、こうした中毒性のある無限スクロールを禁止しようという一部の流れもあるようです。

>ソーシャルメディア依存軽減テクノロジー法

>巨大テック企業に対して特に批判的な米国のジョシュ・ホーリー上院議員（共和党）が、ソーシャルメディア企業による無限スクロールや映像の自動再生、達成バッジなどのデザイン機能の使用を制限する新法案を提出した。

https://ascii.jp/elem/000/001/914/1914732/

# 教訓：世の中は変えられないが、自分の環境はある程度変えられる
「お願い！無限スクロールをやめてください」とシリコンバレーの偉い人にJapanese Dogeza Styleで（土下座で）嘆願しても、多分そうはしてくれません。ただ、自分で拡張機能を作ったりすれば、少なくとも自分の環境は改善できます。

激化するサービス間の競争の中で、人間の脳をハックする、中毒性の高いサービスが生まれるのは当然のことです。無意識に何もかも身を任せてしまうことのないように、皆さんも自分でお手製のツールを作成してみてはいかがでしょうか？

# 参考用のソースコード
Chrome Web Storeに提出した物と同じコードをgithubで公開しています。
https://github.com/kantasv/no-infinite-scroll/tree/main


# ソースコードの一部紹介 content.js

寝たいので説明は割愛します。

```js:content.js

const EXTENSION_NAME = 'No Infinite Scroll'
const BIG_NUMBER = 10000
let timeoutId;
let maxClientHeight = null

const heightIncreased = () => {
    // base case
    if (!maxClientHeight) {
        maxClientHeight = document.body.clientHeight
    } else {
        if (maxClientHeight < document.body.clientHeight) {
            console.log(`[${EXTENSION_NAME}] Possibly infinite scroll detected`)
            maxClientHeight = document.body.clientHeight
            return true
        }
        return false
    }
}

const getRandomMessage = () => {
    const questions = ['Hey, is this infinite scroll website truly important for you? ', 'Are you still doing what you initially meant to do?', 'Do you know that infinite scroll is highly addictive?']
    const actions = ['Breath deeply, and think about it for a while.', 'Inhale and exale for a moment. Be mindful to stay productive and happy.', 'You face tsunami of infomation nowadays, but your attention is finite.']
    var min = 0;
    var max = Math.max(questions.length) - 1

    const qIndex = Math.floor(Math.random() * (max + 1 - min)) + min;
    const aIndex = Math.floor(Math.random() * (max + 1 - min)) + min;

    return questions[qIndex] + ' ' + actions[aIndex]
}

const initSpeedBumpModal = () => {
    // modalWrapper
    const modalWrapper = document.createElement('div')
    modalWrapper.style.backgroundColor = '#738276'
    modalWrapper.style.zIndex = BIG_NUMBER
    modalWrapper.style.position = 'fixed'
    modalWrapper.style.top = '0px'
    modalWrapper.style.left = '0px'
    modalWrapper.style.height = '100%'
    modalWrapper.style.width = '100%'
    modalWrapper.style.display = 'none'

    // speedBumpMessageContainer
    const speedBumpMessageContainer = document.createElement('div')
    speedBumpMessageContainer.style.backgroundColor = '#738276'
    speedBumpMessageContainer.style.color = 'white'
    speedBumpMessageContainer.innerHTML = getRandomMessage()
    speedBumpMessageContainer.style.margin = '20px'
    speedBumpMessageContainer.style.height = '800px'
    speedBumpMessageContainer.style.width = '800px'
    speedBumpMessageContainer.style.margin = '0 auto'
    speedBumpMessageContainer.style.display = 'flex'
    speedBumpMessageContainer.style.alignItems = 'center'
    speedBumpMessageContainer.style.justifyContent = 'center'

    const gotitButton = document.createElement('div')
    gotitButton.innerText = 'Click here to dismiss.'
    gotitButton.style.color = 'white'
    gotitButton.style.margin = '10px'
    gotitButton.onclick = closeSpeedBumpModal
    gotitButton.style.position = 'fixed'
    gotitButton.style.right = '0px'
    gotitButton.style.bottom = '0px'

    speedBumpMessageContainer.appendChild(gotitButton)
    modalWrapper.appendChild(speedBumpMessageContainer)
    document.body.appendChild(modalWrapper)
    return modalWrapper
}
const showSpeedBumpModal = () => {
    modalWrapper.style.display = 'block'
}
const closeSpeedBumpModal = () => {
    modalWrapper.style.display = 'none'
}

const modalWrapper = initSpeedBumpModal()

window.addEventListener("scroll", function () {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(function () {
        if (heightIncreased()) {
            showSpeedBumpModal()
        }
    }, 500);
})

```