@@ -17,7 +17,10 @@ let Video = {
17
17
let msgContainer = document . getElementById ( "msg-container" ) ;
18
18
let msgInput = document . getElementById ( "msg-input" ) ;
19
19
let postButton = document . getElementById ( "msg-submit" ) ;
20
- let vidChannel = socket . channel ( "videos:" + videoId ) ;
20
+ let lastSeenId = 0 ;
21
+ let vidChannel = socket . channel ( "videos:" + videoId , ( ) => {
22
+ return { last_seen_id : lastSeenId } ;
23
+ } ) ;
21
24
22
25
postButton . addEventListener ( "click" , ( e ) => {
23
26
let payload = { body : msgInput . value , at : Player . getCurrentTime ( ) } ;
@@ -28,13 +31,29 @@ let Video = {
28
31
} ) ;
29
32
30
33
vidChannel . on ( "new_annotation" , ( resp ) => {
34
+ lastSeenId = resp . id ;
31
35
this . renderAnnotation ( msgContainer , resp ) ;
32
36
} ) ;
33
37
38
+ msgContainer . addEventListener ( "click" , ( e ) => {
39
+ e . preventDefault ( ) ;
40
+ let seconds =
41
+ e . target . getAttribute ( "data-seek" ) ||
42
+ e . target . parentNode . getAttribute ( "data-seek" ) ;
43
+ if ( ! seconds ) {
44
+ return ;
45
+ }
46
+ Player . seekTo ( seconds ) ;
47
+ } ) ;
48
+
34
49
vidChannel
35
50
. join ( )
36
- . receive ( "ok" , ( { annotations } ) => {
37
- annotations . forEach ( ( ann ) => this . renderAnnotation ( msgContainer , ann ) ) ;
51
+ . receive ( "ok" , ( resp ) => {
52
+ let ids = resp . annotations . map ( ( ann ) => ann . id ) ;
53
+ if ( ids . length > 0 ) {
54
+ lastSeenId = Math . max ( ...ids ) ;
55
+ }
56
+ this . scheduleMessages ( msgContainer , resp . annotations ) ;
38
57
} )
39
58
. receive ( "error" , ( reason ) => console . log ( "join failed" , reason ) ) ;
40
59
} ,
@@ -47,15 +66,41 @@ let Video = {
47
66
48
67
renderAnnotation ( msgContainer , { user, body, at } ) {
49
68
let template = document . createElement ( "div" ) ;
50
-
51
69
template . innerHTML = `
52
70
<a href="#" data-seek="${ this . esc ( at ) } ">
71
+ [${ this . formatTime ( at ) } ]
53
72
<b>${ this . esc ( user . username ) } </b>: ${ this . esc ( body ) }
54
73
</a>
55
74
` ;
56
75
msgContainer . appendChild ( template ) ;
57
76
msgContainer . scrollTop = msgContainer . scrollHeight ;
58
77
} ,
78
+
79
+ scheduleMessages ( msgContainer , annotations ) {
80
+ clearTimeout ( this . scheduleTimer ) ;
81
+ this . schedulerTimer = setTimeout ( ( ) => {
82
+ let ctime = Player . getCurrentTime ( ) ;
83
+ let remaining = this . renderAtTime ( annotations , ctime , msgContainer ) ;
84
+ this . scheduleMessages ( msgContainer , remaining ) ;
85
+ } , 1000 ) ;
86
+ } ,
87
+
88
+ renderAtTime ( annotations , seconds , msgContainer ) {
89
+ return annotations . filter ( ( ann ) => {
90
+ if ( ann . at > seconds ) {
91
+ return true ;
92
+ } else {
93
+ this . renderAnnotation ( msgContainer , ann ) ;
94
+ return false ;
95
+ }
96
+ } ) ;
97
+ } ,
98
+
99
+ formatTime ( at ) {
100
+ let date = new Date ( null ) ;
101
+ date . setSeconds ( at / 1000 ) ;
102
+ return date . toISOString ( ) . substr ( 14 , 5 ) ;
103
+ } ,
59
104
} ;
60
105
61
106
export default Video ;
0 commit comments