forked from replit-archive/repl.it
-
Notifications
You must be signed in to change notification settings - Fork 1
/
session.coffee
203 lines (185 loc) · 7.67 KB
/
session.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# Extension module.
# Encapsulates for all session/state loading saving logic.
# TODO(amasad): Graceful localStorage degradation to cookies.
$ = jQuery
PUSHSTATE_SUPPORTED = 'pushState' of history
WAIT_BETWEEN_SAVES = 2000
SHARE_TEMPLATE =
twitter: ->
text = 'Check out my REPL session - '
related = 'replit'
url = window.location.href
uri = $.param {
text
url
related
}
"""
<a href="https://twitter.com/share?#{uri}" target="_blank"></a>
"""
facebook: ->
"""
<a href="javascript:var d=document,f='http://www.facebook.com/share',l=d.location,e=encodeURIComponent,p='.php?src=bm&v=4&i=1315186262&u='+e(l.href)+'&t='+e(d.title);1;try{if (!/^(.*\.)?facebook\.[^.]*$/.test(l.host))throw(0);share_internal_bookmarklet(p)}catch(z) {a=function() {if (!window.open(f+'r'+p,'sharer','toolbar=0,status=0,resizable=1,width=626,height=436'))l.href=f+p};if (/Firefox/.test(navigator.userAgent))setTimeout(a,0);else{a()}}void(0)"></a>
"""
# Unofficial!
gplus: ->
text = 'Check out my REPL session - ' + window.location.href
text = encodeURI text
"""
<a href="https://m.google.com/app/plus/x/bggo8s9j8yqo/?v=compose&content=#{text}&login=1&pli=1&hideloc=1" target="_blank"></a>
"""
$.extend REPLIT,
session:
eval_history: []
pushState: (text) ->
if PUSHSTATE_SUPPORTED
# We only want to clear state #0 (Session path), restore the page hash
# after clearing the session path.
{hash} = window.location
window.history.pushState null, null, "/#{text}"
window.location.hash = hash
else
REPLIT.setHash 0, text
# Resets application to its initial state (handler for language_loaded event).
reset_state = (e, lang_name) ->
localStorage.setItem 'lang_name', lang_name
$('#replay-button').hide()
@session = {}
@session.eval_history = []
REPLIT.pushState ''
$ ->
# If there exists a REPLIT_DATA variable, then we are in a saved session.
if REPLIT_DATA?
# Load the language specified by the incoming session data.
REPLIT.current_lang_name = REPLIT_DATA.language
REPLIT.OpenPage 'workspace', ->
REPLIT.LoadLanguage REPLIT_DATA.language, ->
# Set the editor text.
REPLIT.editor.getSession().setValue REPLIT_DATA.editor_text if not REPLIT.ISMOBILE
# Get the session data.
REPLIT.session.id = REPLIT_DATA.session_id
REPLIT.session.rid = REPLIT_DATA.revision_id
REPLIT.session.saved_eval_history = REPLIT_DATA.eval_history
# Show the replay button.
$('#replay-button').show()
# Delete the incoming session data from the server since we have
# extracted everything we neeed.
delete window['REPLIT_DATA']
# On each language load after this one reset the state.
REPLIT.$this.bind 'language_loaded', reset_state
else
# We are not in a saved session.
# Safely bind the reset state function.
REPLIT.$this.bind 'language_loaded', reset_state
lang_name = localStorage.getItem('lang_name')
if lang_name?
REPLIT.loading_saved_lang = true
# We have a saved local settings for language to load. Delay this until
# the Analytics modules has set its hook so it can catch language loading.
$ ->
REPLIT.current_lang_name = lang_name
REPLIT.OpenPage 'workspace', ->
REPLIT.LoadLanguage lang_name
else
# This is the first visit; show language overlay.
$('#languages-back').bind 'click.language_modal', (e) ->
e.stopImmediatePropagation()
return false
$('#content-languages .language-group li').bind 'click.language_modal', (e) ->
REPLIT.Modal false
REPLIT.$this.bind 'language_loaded.language_modal', (e) ->
$('#languages-back').unbind 'click.language_modal'
REPLIT.OpenPage 'languages'
REPLIT.Modal true
# Click handler for the replay button.
$('#replay-button').click (e) ->
# Get the history comming from the server.
history = REPLIT.session.saved_eval_history
locked = false
locked_queue = []
index = -1
# Executes a command from history and waits for the result to continue
# with the next command.
handler = ->
if not locked
index++
if history[index]?
# Set the prompt text to the command in question.
REPLIT.jqconsole.SetPromptText history[index]
# Remove multiline handler from jqconsole to ensure it doesn't
# continue to the next line.
_multiline = REPLIT.jqconsole.multiline_callback
REPLIT.jqconsole.multiline_callback = undefined
# Simulate an enter button on jqconsole.
REPLIT.jqconsole._HandleEnter()
# Reassign the multiline handler.
REPLIT.jqconsole.multiline_callback = _multiline
else
# There is no more commands; unbind the handler.
REPLIT.$this.unbind 'result', handler
REPLIT.$this.unbind 'error', handler
# We are done with the eval history from the server; delete it.
delete REPLIT.session['saved_eval_history']
else
locked_queue.push handler
input_lock = ->
locked = true
input_unlock = ->
locked = false
fn = locked_queue.shift()
setTimeout fn, 100 if fn?
REPLIT.$this.bind 'result', handler
REPLIT.$this.bind 'error', handler
REPLIT.$this.bind 'input', input_unlock
REPLIT.$this.bind 'input_request', input_lock
# Initiate the first handler to start executing history commands.
handler()
# This button can only be clicked once. Now hide it.
$(this).hide()
saveSession = (e) ->
# Can't save if we haven't selected a language yet.
if not REPLIT.current_lang? then return
# Get the post data to save.
post_data =
language: REPLIT.current_lang.system_name
editor_text: REPLIT.editor.getSession().getValue() if not REPLIT.ISMOBILE
eval_history: JSON.stringify REPLIT.session.eval_history
console_dump: REPLIT.jqconsole.Dump();
# If we are already REPLing on a saved session, get its id.
post_data.id = REPLIT.session.id if REPLIT.session.id?
# Do the actual save request.
$.post '/save', post_data, (data) ->
{session_id, revision_id} = data
$savebox = $('#save-box')
# Update URL.
if revision_id > 0
REPLIT.pushState session_id + '/' + revision_id
else
REPLIT.pushState session_id
# Update IDs.
REPLIT.session.id = session_id
REPLIT.session.rid = revision_id
# Render social share links.
$savebox.find('li.twitter a').replaceWith SHARE_TEMPLATE.twitter()
$savebox.find('li.facebook a').replaceWith SHARE_TEMPLATE.facebook()
$savebox.find('li.gplus a').replaceWith SHARE_TEMPLATE.gplus()
$savebox.find('input').val window.location.href
$savebox.find('.downloads a.editor').attr 'href', "/download/editor/#{session_id}/#{revision_id}/"
$savebox.find('.downloads a.repl').attr 'href', "/download/repl/#{session_id}/#{revision_id}/"
$savebox.slideDown()
$savebox.click (e) ->
return e.stopPropagation()
$('body').bind 'click.closesave', ->
$savebox.slideUp()
$('body').unbind('click.closesave')
# Disable share button for a little while.
unbindSaveButton()
setTimeout bindSaveButton, WAIT_BETWEEN_SAVES
bindSaveButton = -> $('#button-save').click saveSession
unbindSaveButton = -> $('#button-save').unbind 'click'
bindSaveButton()
$('#save-box input').click -> $(this).select()
# When any command is evaled, save it in the eval_history array of the session
# object, in order to send it to the server on save.
REPLIT.$this.bind 'eval', (e, command) ->
REPLIT.session.eval_history.push command