@@ -5,62 +5,63 @@ import { addBorderWhenClicked } from './addBorderWhenClicked';
5
5
import { temporarilyPreventClicks } from './temporarilyPreventClicks' ;
6
6
import { pendingQuestionColor } from '../pendingQuestionColor' ;
7
7
8
- const seenQuestionsIds = new Set (
9
- [ ... document . querySelectorAll ( '#questions > div.question-summary' ) ] . map ( ( { id } ) => id ) ,
10
- ) ;
8
+ const getQuestionDivs = ( ) => [ ... document . querySelectorAll < HTMLInputElement > ( '#questions div.question-summary' ) ] ;
9
+ const getQuestionId = ( questionDiv : HTMLElement ) => Number ( questionDiv . id . match ( / \d + $ / ) ! [ 0 ] ) ;
10
+ const seenQuestionsIds = new Set ( getQuestionDivs ( ) . map ( getQuestionId ) ) ;
11
11
const watchedTags = document . querySelector < HTMLInputElement > ( '#search input' ) ?. value . match ( / [ ^ \[ \] ] + (? = \] ) / g) || [ ] ;
12
12
const questionTagCountsLeftById : { [ questionId : string ] : number } = { } ;
13
13
const siteName = window . location . href === 'https://example.com/fakepage' ? '' : window . StackExchange . options . site . name ;
14
14
const siteNameSpokenText = siteName === 'Stack Overflow' ? '' : `${ siteName } , ` ;
15
15
16
16
export const checkNewQuestions = ( ) => {
17
17
temporarilyPreventClicks ( ) ;
18
- [ ...document . querySelectorAll < HTMLElement > ( '#questions > div.question-summary' ) ]
19
- . filter ( questionDiv => ! seenQuestionsIds . has ( questionDiv . id ) )
20
- . forEach ( ( questionDiv ) => {
21
- targetBlankAllAnchors ( questionDiv ) ;
22
- const { focusing } = getState ( ) ;
23
- // New question divs that have not been spoken yet will be highlighted yellow
24
- // But these divs may get removed and replaced with copies before being passed to queueUtterance (see below)
25
- // For style consistency while the divs are appearing, highlight them immediately
26
- if ( ! focusing ) {
27
- questionDiv . style . backgroundColor = pendingQuestionColor ;
28
- }
18
+ for ( const questionDiv of getQuestionDivs ( ) ) {
19
+ const questionId = getQuestionId ( questionDiv ) ;
20
+ if ( ! questionId || seenQuestionsIds . has ( questionId ) ) {
21
+ continue ;
22
+ }
23
+ targetBlankAllAnchors ( questionDiv ) ;
24
+ const { focusing } = getState ( ) ;
25
+ // New question divs that have not been spoken yet will be highlighted yellow
26
+ // But these divs may get removed and replaced with copies before being passed to queueUtterance (see below)
27
+ // For style consistency while the divs are appearing, highlight them immediately
28
+ if ( ! focusing ) {
29
+ questionDiv . style . backgroundColor = pendingQuestionColor ;
30
+ }
29
31
30
- /* StackExchange will send the client new info about an active question *for every question, and for every tag in that question* that you're watching
31
- * Eg if you're watching 5 tags, and a question is posted with 3 of them, the websocket will send you info 3 times
32
- * (there may be a moderate fraction of a second delay between each)
33
- * and each time, if the existing question div is already in the document, it will be completely removed and replaced
34
- * See: https://dev.stackoverflow.com/content//Js/full.en.js
35
- * search for: $('#question-summary-' + activeq.id).remove();
36
- * Rather than fiddling with the element (and with the styles added by the userscript, and with the linked audio) every time it gets replaced
37
- * just wait for the question to appear in the questions list for the nth time, where n is the number of watched tags that question has
38
- * Only on that nth time does the code below result in the questionDiv actually getting changed, watched, and linked to the utterance that gets queued
39
- */
40
- const questionId = questionDiv . id ;
41
- if ( ! questionTagCountsLeftById . hasOwnProperty ( questionId ) ) {
42
- const watchedTagCountForThisQuestion = Array . from (
43
- questionDiv . querySelectorAll ( '.tags > a' ) ,
44
- a => a . textContent ! ,
45
- )
46
- . reduce ( ( a , tag ) => a + Number ( watchedTags . includes ( tag ) ) , 0 ) ;
47
- questionTagCountsLeftById [ questionId ] = watchedTagCountForThisQuestion ;
48
- }
49
- questionTagCountsLeftById [ questionId ] -= 1 ;
50
- // User may not be watching any tags - may be just on /questions?tab=Newest page
51
- // in which case there's nothing to count, and only one socket message per question, so queue the question immediately
52
- if ( watchedTags . length && questionTagCountsLeftById [ questionId ] !== 0 ) {
53
- return ;
54
- }
55
- seenQuestionsIds . add ( questionId ) ;
56
- addBorderWhenClicked ( questionDiv ) ;
57
- if ( focusing ) {
58
- return ;
59
- }
60
- const questionText = questionDiv . querySelector ( '.question-hyperlink' ) ! . textContent ;
61
- const questionTags = [ ...questionDiv . querySelectorAll ( '.tags > a' ) ]
62
- . map ( tagA => tagA . textContent ! . replace ( / \. / g, ' dot ' ) ) ;
63
- const textToSpeak = `Question, ${ siteNameSpokenText } ${ questionText } ---- ${ questionTags . join ( ', ' ) } ` ;
64
- queueUtterance ( textToSpeak , questionId ) ;
65
- } ) ;
32
+ /* StackExchange will send the client new info about an active question *for every question, and for every tag in that question* that you're watching
33
+ * Eg if you're watching 5 tags, and a question is posted with 3 of them, the websocket will send you info 3 times
34
+ * (there may be a moderate fraction of a second delay between each)
35
+ * and each time, if the existing question div is already in the document, it will be completely removed and replaced
36
+ * See: https://dev.stackoverflow.com/content//Js/full.en.js
37
+ * search for: $('#question-summary-' + activeq.id).remove();
38
+ * Rather than fiddling with the element (and with the styles added by the userscript, and with the linked audio) every time it gets replaced
39
+ * just wait for the question to appear in the questions list for the nth time, where n is the number of watched tags that question has
40
+ * Only on that nth time does the code below result in the questionDiv actually getting changed, watched, and linked to the utterance that gets queued
41
+ */
42
+ if ( ! questionTagCountsLeftById . hasOwnProperty ( questionId ) ) {
43
+ const watchedTagCountForThisQuestion = Array . from (
44
+ questionDiv . querySelectorAll ( '.tags > a' ) ,
45
+ a => a . textContent ! ,
46
+ )
47
+ . reduce ( ( a , tag ) => a + Number ( watchedTags . includes ( tag ) ) , 0 ) ;
48
+ questionTagCountsLeftById [ questionId ] = watchedTagCountForThisQuestion ;
49
+ }
50
+ questionTagCountsLeftById [ questionId ] -= 1 ;
51
+ // User may not be watching any tags - may be just on /questions?tab=Newest page
52
+ // in which case there's nothing to count, and only one socket message per question, so queue the question immediately
53
+ if ( watchedTags . length && questionTagCountsLeftById [ questionId ] !== 0 ) {
54
+ continue ;
55
+ }
56
+ seenQuestionsIds . add ( questionId ) ;
57
+ addBorderWhenClicked ( questionDiv ) ;
58
+ if ( focusing ) {
59
+ continue ;
60
+ }
61
+ const questionText = questionDiv . querySelector ( '.question-hyperlink' ) ! . textContent ;
62
+ const questionTags = [ ...questionDiv . querySelectorAll ( '.tags > a' ) ]
63
+ . map ( tagA => tagA . textContent ! . replace ( / \. / g, ' dot ' ) ) ;
64
+ const textToSpeak = `Question, ${ siteNameSpokenText } ${ questionText } ---- ${ questionTags . join ( ', ' ) } ` ;
65
+ queueUtterance ( textToSpeak , questionId ) ;
66
+ }
66
67
} ;
0 commit comments