您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A small improvement to Flowdock
// ==UserScript== // @name FlowdockX // @namespace http://twitter.com/grahammcculloch // @version 0.9 // @noframes // @description A small improvement to Flowdock // @author Graham McCulloch // @match https://www.flowdock.com/app/* // @grant none // @icon http://blog.flowdock.com/wp-content/uploads/2017/05/[email protected] // ==/UserScript== (function() { 'use strict'; const storageKey = "flowdockX_withReplies"; console.log(String.raw` ______ _ _ _ __ __ | ___|| | | | | | \ \ / / | |_ | | ___ __ __ __| | ___ ___ | | __ \ V / | _| | | / _ \\ \ /\ / // _ | / _ \ / __|| |/ / / \ | | | || (_) |\ V V /| (_| || (_) || (__ | < / /^\ \ \_| |_| \___/ \_/\_/ \__,_| \___/ \___||_|\_\\/ \/ `); let withReplies = localStorage.getItem(storageKey, 'true') === 'true'; const $headCss = window.$(` <style type="text/css"> li.chat-message.message { transition: background-color 0s ease; } #toolbar > .right-item-group { right: 3.8rem; } #btn-toggle-threads { position: absolute; top: 0; right: 10px; z-index: 2; } #btn-toggle-threads svg { padding-top: 3px; } body, body>.flow { z-index: 1; } body.hide-replies .flow:not(.private) .left-panel #chat li.chat-message.message:not(.thread-starter) { display: none; } .reply-count { text-align: center; font-size: 80%; font-weight: bold; } .theme-flowdark .reply-count { color: #bbb; } .reply-count-wrapper { display: flex; } </style> `); const replyIcon = (size) => { return ` <svg class="vector-icon bubble-icon" x="0px" y="0px" viewBox="0 0 ${size} ${size}" data-reactid=".9.1"> <g data-reactid=".9.1.0"> <path class="vector-icon-path" d="M11.219297,12.803921 C11.2188795,13.287707 11.5307502,13.723651 12.0095154,13.908981 C12.4877588,14.093921 13.0390642,13.991804 13.4055227,13.650182 L19.6246697,7.847278 C20.1250405,7.380641 20.1250405,6.62344 19.6250872,6.156316 L13.4092801,0.350392 C13.1646266,0.121507 12.8368911,0 12.5033106,0 C12.3381903,0 12.1721307,0.029622 12.0136904,0.090716 C11.5349251,0.275656 11.222637,0.712087 11.222637,1.195483 L11.222637,4.755235 L8.988401,4.755235 C2.057852,4.755235 1.6948031,2.082537 1.1856852,1.074049 C1.018715,0.743306 0.4262512,0.646537 0.2128106,1.072977 C-0.7577142,3.01202 1.4935153,9.173136 8.988401,9.173136 L11.2205495,9.173136 L11.219297,12.803921 Z" data-reactid=".9.1.0.0"> </path> </g> </svg>`; } const toolbarBtn = window.$(` <a id="btn-toggle-threads" class="toolbar-link active" title="Hide replies"> <span class="toolbar-toggle"> ${replyIcon(20)} </span> </button> `); const body = window.$('body'); function updateThreadCounts(flowdockSanityActive) { const $threadStarters = window.$('.chat-message.thread-starter'); $threadStarters.each((index) => { const $threadStarter = window.$($threadStarters[index]); const threadId = $threadStarter.attr('data-parent'); const $threadReplies = window.$(`.chat-message:not(.thread-starter)[data-parent='${threadId}'`); if ($threadReplies.length) { const $replyCount = $threadStarter.find('.reply-count'); const replyCountText = flowdockSanityActive ? `${$threadReplies.length} ${$threadReplies.length > 1 ? 'replies' : 'reply'}` : $threadReplies.length; if (!$replyCount.length) { if (flowdockSanityActive) { const $messageAuthor = $threadStarter.find('.message-author'); $messageAuthor.wrap('<div class="reply-count-wrapper"></div>'); const $wrapper = $threadStarter.find('.reply-count-wrapper'); $wrapper.append(`<div class="reply-count">${replyCountText}</div>`); } else { const $bubble = $threadStarter.find('.bubble-container .bubble'); $bubble.append(`<div class="reply-count">${$threadReplies.length}</div>`); } } else { $replyCount.text(replyCountText); } } }); } function initMainChatList($chatList) { $chatList.attr('data-reply-count-init', true); const $threadIndicator = window.$('.thread-indicator'); const flowdockSanityActive = $threadIndicator.css('display') === 'none'; updateThreadCounts(flowdockSanityActive); const observer = new MutationObserver( (mutationsList, observer) => { if (mutationsList.find(m => m.type === 'childList' && m.addedNodes && m.addedNodes.length)) { updateThreadCounts(flowdockSanityActive); } } ); observer.observe($chatList[0], { childList: true }); } function checkForMainChatList() { const $mainChatList = window.$('.left-panel .chat-message-list'); if ($mainChatList.length) { const initialized = $mainChatList.attr('data-reply-count-init'); if (!initialized) { initMainChatList($mainChatList); } } } function setWithReplies(newWithReplies) { withReplies = newWithReplies; localStorage.setItem(storageKey, withReplies); if (withReplies) { body.removeClass('hide-replies'); toolbarBtn.attr('title', 'Hide replies'); toolbarBtn.addClass('active'); } else { body.addClass('hide-replies'); toolbarBtn.attr('title', 'Show replies'); toolbarBtn.removeClass('active'); } } window.$('head').append($headCss); body.append(toolbarBtn); setWithReplies(withReplies); toolbarBtn.on('click', () => { setWithReplies(!withReplies); }); setInterval(checkForMainChatList, 1000); })();