summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--content/fireflix-panel.xul3
-rw-r--r--content/fireflix.js17
-rw-r--r--content/flickr.js5
3 files changed, 20 insertions, 5 deletions
diff --git a/content/fireflix-panel.xul b/content/fireflix-panel.xul
index 405804c..8aec0e4 100644
--- a/content/fireflix-panel.xul
+++ b/content/fireflix-panel.xul
@@ -1,315 +1,316 @@
1<?xml version="1.0"?> 1<?xml version="1.0"?>
2<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> 2<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
3<?xml-stylesheet href="fireflix.css" type="text/css"?> 3<?xml-stylesheet href="fireflix.css" type="text/css"?>
4<!DOCTYPE page SYSTEM "chrome://fireflix/locale/fireflix.dtd"> 4<!DOCTYPE page SYSTEM "chrome://fireflix/locale/fireflix.dtd">
5<page 5<page
6 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 6 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
7 id="fireflixwindow" title="Fireflix" 7 id="fireflixwindow" title="Fireflix"
8 onload="fireflix.init()" 8 onload="fireflix.init()"
9 orient="vertical" 9 orient="vertical"
10 ondragover="nsDragAndDrop.dragOver(event,fireflix.uploadObserver)" 10 ondragover="nsDragAndDrop.dragOver(event,fireflix.uploadObserver)"
11 ondragdrop="nsDragAndDrop.drop(event,fireflix.uploadObserver)" 11 ondragdrop="nsDragAndDrop.drop(event,fireflix.uploadObserver)"
12 > 12 >
13 13
14 <script src="chrome://global/content/nsDragAndDrop.js"/> 14 <script src="chrome://global/content/nsDragAndDrop.js"/>
15 <script src="chrome://global/content/nsTransferable.js"/> 15 <script src="chrome://global/content/nsTransferable.js"/>
16 <script type="application/x-javascript" src="md5.js" /> 16 <script type="application/x-javascript" src="md5.js" />
17 <script type="application/x-javascript" src="util.js" /> 17 <script type="application/x-javascript" src="util.js" />
18 <script type="application/x-javascript" src="flickr.js" /> 18 <script type="application/x-javascript" src="flickr.js" />
19 <script type="application/x-javascript" src="fireflix.js" /> 19 <script type="application/x-javascript" src="fireflix.js" />
20 20
21 <stringbundleset> 21 <stringbundleset>
22 <stringbundle id="loc_strings" src="chrome://fireflix/locale/fireflix.properties" /> 22 <stringbundle id="loc_strings" src="chrome://fireflix/locale/fireflix.properties" />
23 </stringbundleset> 23 </stringbundleset>
24 24
25 <commandset> 25 <commandset>
26 <command id="cmd_auth_auth" label="&panel.auth.auth.label;" 26 <command id="cmd_auth_auth" label="&panel.auth.auth.label;"
27 oncommand="fireflix.on_cmd_auth()"/> 27 oncommand="fireflix.on_cmd_auth()"/>
28 <command id="cmd_auth_done" label="&panel.auth.done.label;" 28 <command id="cmd_auth_done" label="&panel.auth.done.label;"
29 oncommand="fireflix.on_cmd_auth_done()" disabled="true"/> 29 oncommand="fireflix.on_cmd_auth_done()" disabled="true"/>
30 <command id="cmd_auth_open_flickr" label="&panel.auth.flickr.label;" 30 <command id="cmd_auth_open_flickr" label="&panel.auth.flickr.label;"
31 oncommand="fireflix.openTab('http://www.flickr.com/')" /> 31 oncommand="fireflix.openTab('http://www.flickr.com/')" />
32 <command id="cmd_auth_unauth" label="&panel.auth.unauth.label;" 32 <command id="cmd_auth_unauth" label="&panel.auth.unauth.label;"
33 oncommand="fireflix.on_cmd_auth_unauth()" /> 33 oncommand="fireflix.on_cmd_auth_unauth()" />
34 <command id="cmd_help" label="?" 34 <command id="cmd_help" label="?"
35 oncommand="fireflix.openTab('chrome://fireflix/content/help.xml')" /> 35 oncommand="fireflix.openTab('chrome://fireflix/content/help.xml')" />
36 </commandset> 36 </commandset>
37 37
38 <popupset> 38 <popupset>
39 <popup id="auth_menu"> 39 <popup id="auth_menu">
40 <menuitem command="cmd_auth_auth"/> 40 <menuitem command="cmd_auth_auth"/>
41 <menuitem command="cmd_auth_done" hidden="true" id="menu_auth_done"/> 41 <menuitem command="cmd_auth_done" hidden="true" id="menu_auth_done"/>
42 <menuitem command="cmd_auth_unauth" /> 42 <menuitem command="cmd_auth_unauth" />
43 <menuseparator/> 43 <menuseparator/>
44 <menuitem command="cmd_auth_open_flickr"/> 44 <menuitem command="cmd_auth_open_flickr"/>
45 </popup> 45 </popup>
46 </popupset> 46 </popupset>
47 47
48 <commandset id="cmdset_search"> 48 <commandset id="cmdset_search">
49 <command id="cmd_search" label="&panel.search.cmd_search.label;" 49 <command id="cmd_search" label="&panel.search.cmd_search.label;"
50 oncommand="fireflix.foundphotos.search_photos()"/> 50 oncommand="fireflix.foundphotos.search_photos()"/>
51 <command id="cmd_search_open" label="&panel.search.cmd_search_open.label;" 51 <command id="cmd_search_open" label="&panel.search.cmd_search_open.label;"
52 oncommand="fireflix.foundphotos.on_cmd_open(event)" /> 52 oncommand="fireflix.foundphotos.on_cmd_open(event)" />
53 <command id="cmd_search_prev_page" 53 <command id="cmd_search_prev_page"
54 label="&panel.search.cmd_search_prev_page.label;" 54 label="&panel.search.cmd_search_prev_page.label;"
55 oncommand="fireflix.foundphotos.on_cmd_prev(event)" disabled="true"/> 55 oncommand="fireflix.foundphotos.on_cmd_prev(event)" disabled="true"/>
56 <command id="cmd_search_next_page" 56 <command id="cmd_search_next_page"
57 label="&panel.search.cmd_search_next_page.label;" 57 label="&panel.search.cmd_search_next_page.label;"
58 oncommand="fireflix.foundphotos.on_cmd_next(event)" disabled="true"/> 58 oncommand="fireflix.foundphotos.on_cmd_next(event)" disabled="true"/>
59 </commandset> 59 </commandset>
60 60
61 <commandset id="cmdset_sets"> 61 <commandset id="cmdset_sets">
62 <command id="cmd_refresh_sets" label="&panel.sets.cmd_refresh_sets;" 62 <command id="cmd_refresh_sets" label="&panel.sets.cmd_refresh_sets;"
63 oncommand="fireflix.on_refresh_sets()" /> 63 oncommand="fireflix.on_refresh_sets()" />
64 <command id="cmd_set_props" label="&panel.sets.cmd_properties;" 64 <command id="cmd_set_props" label="&panel.sets.cmd_properties;"
65 oncommand="fireflix.on_set_props()" disabled="true" /> 65 oncommand="fireflix.on_set_props()" disabled="true" />
66 </commandset> 66 </commandset>
67 67
68 <popupset> 68 <popupset>
69 <popup id="sets_menu"> 69 <popup id="sets_menu">
70 <menuitem command="cmd_set_props"/> 70 <menuitem command="cmd_set_props"/>
71 <menuitem command="cmd_refresh_sets"/> 71 <menuitem command="cmd_refresh_sets"/>
72 <menuseparator/> 72 <menuseparator/>
73 <menu label="&panel.sets.generate_html;" id="sets_html_menu"/> 73 <menu label="&panel.sets.generate_html;" id="sets_html_menu"/>
74 </popup> 74 </popup>
75 </popupset> 75 </popupset>
76 76
77 <commandset id="cmdset_setphotos"> 77 <commandset id="cmdset_setphotos">
78 </commandset> 78 </commandset>
79 79
80 <popupset> 80 <popupset>
81 <popup id="setphotos_menu"> 81 <popup id="setphotos_menu">
82 <menu label="&panel.setphotos.generate_html;" id="setphotos_html_menu"/> 82 <menu label="&panel.setphotos.generate_html;" id="setphotos_html_menu"/>
83 </popup> 83 </popup>
84 </popupset> 84 </popupset>
85 85
86 <commandset id="cmdset_uploads"> 86 <commandset id="cmdset_uploads">
87 <command id="cmd_uploads_clear" label="&panel.uploads.clear.label;" 87 <command id="cmd_uploads_clear" label="&panel.uploads.clear.label;"
88 oncommand="fireflix.uploads.on_clear()" /> 88 oncommand="fireflix.uploads.on_clear()" />
89 <command id="cmd_uploads_upload" label="&panel.uploads.upload.label;" 89 <command id="cmd_uploads_upload" label="&panel.uploads.upload.label;"
90 oncommand="fireflix.uploads.on_upload()" /> 90 oncommand="fireflix.uploads.on_upload()" />
91 <command id="cmd_uploads_remove" label="&panel.uploads.remove.label;" 91 <command id="cmd_uploads_remove" label="&panel.uploads.remove.label;"
92 oncommand="fireflix.uploads.on_remove()" /> 92 oncommand="fireflix.uploads.on_remove()" />
93 <command id="cmd_uploads_add" label="&panel.uploads.add.label;" 93 <command id="cmd_uploads_add" label="&panel.uploads.add.label;"
94 oncommand="fireflix.uploads.on_add()" /> 94 oncommand="fireflix.uploads.on_add()" />
95 </commandset> 95 </commandset>
96 96
97 <popupset> 97 <popupset>
98 <popup id="uploads_menu"> 98 <popup id="uploads_menu">
99 <menuitem command="cmd_uploads_add"/> 99 <menuitem command="cmd_uploads_add"/>
100 <menuitem command="cmd_uploads_clear"/> 100 <menuitem command="cmd_uploads_clear"/>
101 <menuitem command="cmd_uploads_remove"/> 101 <menuitem command="cmd_uploads_remove"/>
102 <menuseparator/> 102 <menuseparator/>
103 <menuitem command="cmd_uploads_upload"/> 103 <menuitem command="cmd_uploads_upload"/>
104 <menuseparator/> 104 <menuseparator/>
105 <menu label="&panel.uploads.generate_html;" id="uploads_html_menu"/> 105 <menu label="&panel.uploads.generate_html;" id="uploads_html_menu"/>
106 </popup> 106 </popup>
107 </popupset> 107 </popupset>
108 108
109 <vbox class="wholething" flex="1"> 109 <vbox class="wholething" flex="1">
110 110
111 <groupbox context="auth_menu"> 111 <groupbox context="auth_menu">
112 <caption label="&panel.auth_info;"/> 112 <caption label="&panel.auth_info;"/>
113 <hbox> 113 <hbox>
114 <vbox pack="center" flex="1"> 114 <vbox pack="center" flex="1">
115 <label id="auth_info" value="&panel.no_auth_info;" disabled="true" crop="end"/> 115 <label id="auth_info" value="&panel.no_auth_info;" disabled="true" crop="end"/>
116 </vbox> 116 </vbox>
117 <button class="lean" id="b_auth" command="cmd_auth_auth"/> 117 <button class="lean" id="b_auth" command="cmd_auth_auth"/>
118 <button class="lean" id="b_auth_done" command="cmd_auth_done" hidden="true"/> 118 <button class="lean" id="b_auth_done" command="cmd_auth_done" hidden="true"/>
119 <button class="lean" command="cmd_auth_open_flickr" 119 <button class="lean" command="cmd_auth_open_flickr"
120 tooltiptext="&panel.auth.flickr.tip;"/> 120 tooltiptext="&panel.auth.flickr.tip;"/>
121 <button class="lean" command="cmd_help"/> 121 <button class="lean" command="cmd_help"/>
122 </hbox> 122 </hbox>
123 </groupbox> 123 </groupbox>
124 124
125 <tabbox flex="1" id="fireflix_tabs"> 125 <tabbox flex="1" id="fireflix_tabs">
126 126
127 <tabs> 127 <tabs>
128 <tab label="&panel.tabs.search;"/> 128 <tab label="&panel.tabs.search;"/>
129 <tab label="&panel.tabs.sets;"/> 129 <tab label="&panel.tabs.sets;"/>
130 <tab label="&panel.tabs.tags;" hidden="true"/> <!-- TODO: --> 130 <tab label="&panel.tabs.tags;" hidden="true"/> <!-- TODO: -->
131 <tab id="tab_upload" label="&panel.tabs.upload;"/> 131 <tab id="tab_upload" label="&panel.tabs.upload;"/>
132 </tabs> 132 </tabs>
133 133
134 <tabpanels flex="1"> 134 <tabpanels flex="1">
135 135
136 <tabpanel id="tabpanel_search" flex="1"> 136 <tabpanel id="tabpanel_search" flex="1">
137 <vbox flex="1"> 137 <vbox flex="1">
138 <groupbox class="search_params" orient="vertical" onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.search_photos()"> 138 <groupbox class="search_params" orient="vertical" onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.search_photos()">
139 <hbox> 139 <hbox>
140 <vbox pack="center"> 140 <vbox pack="center">
141 <label control="search_for" value="&panel.search.search_for.label;" accesskey="s"/> 141 <label control="search_for" value="&panel.search.search_for.label;" accesskey="s"/>
142 </vbox> 142 </vbox>
143 <textbox id="search_for" flex="1"/> 143 <textbox id="search_for" flex="1"/>
144 </hbox> 144 </hbox>
145 <hbox> 145 <hbox>
146 <checkbox id="search_tags" label="&panel.search.mode.tagsonly.label;" 146 <checkbox id="search_tags" label="&panel.search.mode.tagsonly.label;"
147 tooltiptext="&panel.search.mode.tagsonly.tip;" checked="false" 147 tooltiptext="&panel.search.mode.tagsonly.tip;" checked="false"
148 accesskey="t" /> 148 accesskey="t" />
149 <checkbox id="search_mine" label="&panel.search.mode.mine.label;" checked="true" accesskey="m"/> 149 <checkbox id="search_mine" label="&panel.search.mode.mine.label;" checked="true" accesskey="m"/>
150 <spacer flex="1"/> 150 <spacer flex="1"/>
151 <button class="lean" command="cmd_search"/> 151 <button class="lean" command="cmd_search"/>
152 </hbox> 152 </hbox>
153 </groupbox> 153 </groupbox>
154 <hbox> 154 <hbox>
155 <button class="lean" command="cmd_search_prev_page"/> 155 <button class="lean" command="cmd_search_prev_page"/>
156 <spacer flex="1"/> 156 <spacer flex="1"/>
157 <label id="search_page" hidden="true"/> 157 <label id="search_page" hidden="true"/>
158 <spacer flex="1"/> 158 <spacer flex="1"/>
159 <button class="lean" command="cmd_search_next_page"/> 159 <button class="lean" command="cmd_search_next_page"/>
160 </hbox> 160 </hbox>
161 <tree id="searchresults" rows="2" flex="1" 161 <tree id="searchresults" rows="2" flex="1"
162 onselect="fireflix.foundphotos.on_select()" 162 onselect="fireflix.foundphotos.on_select()"
163 ondblclick="fireflix.foundphotos.on_cmd_open(event)" 163 ondblclick="fireflix.foundphotos.on_cmd_open(event)"
164 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.on_cmd_open(event)"> 164 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.foundphotos.on_cmd_open(event)">
165 <treecols> 165 <treecols>
166 <treecol id="sr_title" label="&panel.search.col.title.label;" flex="2" crop="end" align="start" /> 166 <treecol id="sr_title" label="&panel.search.col.title.label;" flex="2" crop="end" align="start" />
167 </treecols> 167 </treecols>
168 <treechildren/> 168 <treechildren/>
169 </tree> 169 </tree>
170 <groupbox id="searchresult_props" orient="horizontal" hidden="true"> 170 <groupbox id="searchresult_props" orient="horizontal" hidden="true">
171 <vbox width="100" pack="center"> 171 <vbox width="100" pack="center">
172 <hbox pack="center"> 172 <hbox pack="center">
173 <image id="search_photo" 173 <image id="search_photo"
174 ondblclick="fireflix.foundphotos.on_cmd_open(event)"/> 174 ondblclick="fireflix.foundphotos.on_cmd_open(event)"/>
175 </hbox> 175 </hbox>
176 </vbox> 176 </vbox>
177 <vbox flex="1"> 177 <vbox flex="1">
178 <label id="searchresult_title" crop="end"/> 178 <label id="searchresult_title" crop="end"/>
179 <hbox flex="1" pack="center"> 179 <hbox flex="1" pack="center">
180 <div flex="1" id="searchresult_description" xmlns="http://www.w3.org/1999/xhtml"/> 180 <div flex="1" id="searchresult_description" xmlns="http://www.w3.org/1999/xhtml"/>
181 </hbox> 181 </hbox>
182 <hbox pack="end"> 182 <hbox pack="end">
183 <button command="cmd_search_open"/> 183 <button command="cmd_search_open"/>
184 </hbox> 184 </hbox>
185 </vbox> 185 </vbox>
186 </groupbox> 186 </groupbox>
187 </vbox> 187 </vbox>
188 </tabpanel> 188 </tabpanel>
189 189
190 <tabpanel id="tabpanel_sets" flex="1" 190 <tabpanel id="tabpanel_sets" flex="1"
191 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) 191 onkeypress="if(event.keyCode==event.DOM_VK_RETURN)
192 document.getElementById('setphotos').focus()"> 192 document.getElementById('setphotos').focus()">
193 <vbox flex="1"> 193 <vbox flex="1">
194 <tree id="setslist" rows="2" onselect="fireflix.photosets.on_select()" 194 <tree id="setslist" rows="2" onselect="fireflix.photosets.on_select()"
195 flex="1" context="sets_menu" 195 flex="1" context="sets_menu"
196 ondblclick="fireflix.photosets.on_cmd_open_in_flickr(event)" 196 ondblclick="fireflix.photosets.on_cmd_open_in_flickr(event)"
197 > 197 >
198 <treecols> 198 <treecols>
199 <treecol id="sl_name" label="&panel.sets.name.label;" flex="4" crop="end" align="start" tooltiptext="&panel.sets.name.tip;"/> 199 <treecol id="sl_name" label="&panel.sets.name.label;" flex="4" crop="end" align="start" tooltiptext="&panel.sets.name.tip;"/>
200 <splitter class="tree-splitter" /> 200 <splitter class="tree-splitter" />
201 <treecol id="sl_photos" label="&panel.sets.photos.label;" flex="1" align="end" tooltiptext="&panel.sets.photos.tip;" /> 201 <treecol id="sl_photos" label="&panel.sets.photos.label;" flex="1" align="end" tooltiptext="&panel.sets.photos.tip;" />
202 </treecols> 202 </treecols>
203 <treechildren/> 203 <treechildren/>
204 </tree> 204 </tree>
205 <hbox> 205 <hbox>
206 <button command="cmd_refresh_sets" /> 206 <button command="cmd_refresh_sets" />
207 <button command="cmd_set_props" /> 207 <button command="cmd_set_props" />
208 </hbox> 208 </hbox>
209 <tree id="setphotos" rows="2" onselect="fireflix.photoset.on_select()" 209 <tree id="setphotos" rows="2" onselect="fireflix.photoset.on_select()"
210 flex="1" ondblclick="fireflix.photoset.on_cmd_open(event)" 210 flex="1" ondblclick="fireflix.photoset.on_cmd_open(event)"
211 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.photoset.on_cmd_open(event)" context="setphotos_menu"> 211 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.photoset.on_cmd_open(event)" context="setphotos_menu">
212 <treecols> 212 <treecols>
213 <treecol id="sp_title" label="&panel.setphotos.title.label;" flex="1" crop="end" align="start" tooltiptext="&panel.setphotos.title.tip;" /> 213 <treecol id="sp_title" label="&panel.setphotos.title.label;" flex="1" crop="end" align="start" tooltiptext="&panel.setphotos.title.tip;" />
214 <splitter class="tree-splitter" /> 214 <splitter class="tree-splitter" />
215 <treecol id="sp_taken" label="&panel.setphotos.taken.label;" crop="end" align="start" tooltiptext="&panel.setphotos.taken.tip;" hidden="true" /> 215 <treecol id="sp_taken" label="&panel.setphotos.taken.label;" crop="end" align="start" tooltiptext="&panel.setphotos.taken.tip;" hidden="true" />
216 <treecol id="sp_upload" label="&panel.setphotos.upload.label;" crop="end" align="start" tooltiptext="&panel.setphotos.upload.tip;" hidden="true" /> 216 <treecol id="sp_upload" label="&panel.setphotos.upload.label;" crop="end" align="start" tooltiptext="&panel.setphotos.upload.tip;" hidden="true" />
217 </treecols> 217 </treecols>
218 <treechildren/> 218 <treechildren/>
219 </tree> 219 </tree>
220 <groupbox id="set_photo_props" orient="horizontal" hidden="true"> 220 <groupbox id="set_photo_props" orient="horizontal" hidden="true">
221 <vbox width="100" pack="center"> 221 <vbox width="100" pack="center">
222 <hbox pack="center"> 222 <hbox pack="center">
223 <image id="set_photo" 223 <image id="set_photo"
224 ondblclick="fireflix.photoset.on_cmd_open(event)" /> 224 ondblclick="fireflix.photoset.on_cmd_open(event)" />
225 </hbox> 225 </hbox>
226 </vbox> 226 </vbox>
227 <spacer flex="1"/> 227 <spacer flex="1"/>
228 </groupbox> 228 </groupbox>
229 </vbox> 229 </vbox>
230 </tabpanel> 230 </tabpanel>
231 231
232 <tabpanel id="tabpanel_tags"> 232 <tabpanel id="tabpanel_tags">
233 <listbox id="tagslist" rows="8" flex="1"> 233 <listbox id="tagslist" rows="8" flex="1">
234 <listhead> 234 <listhead>
235 <listheader label="&panel.tagslist.tag.label;"/> 235 <listheader label="&panel.tagslist.tag.label;"/>
236 </listhead> 236 </listhead>
237 <listcols> 237 <listcols>
238 <listcol flex="1"/> 238 <listcol flex="1"/>
239 </listcols> 239 </listcols>
240 </listbox> 240 </listbox>
241 </tabpanel> 241 </tabpanel>
242 242
243 <tabpanel id="tabpanel_upload"> 243 <tabpanel id="tabpanel_upload">
244 <vbox flex="1"> 244 <vbox flex="1">
245 <tree id="uploadlist" rows="2" flex="1" 245 <tree id="uploadlist" rows="2" flex="1"
246 onselect="fireflix.uploads.selectionChanged()" 246 onselect="fireflix.uploads.selectionChanged()"
247 context="uploads_menu"> 247 context="uploads_menu" ondblclick="fireflix.uploads.on_cmd_open(event)"
248 onkeypress="if(event.keyCode==event.DOM_VK_RETURN) fireflix.uploads.on_cmd_open(event)" >
248 <treecols> 249 <treecols>
249 <treecol id="up_file" label="&panel.uploadlist.file.label;" flex="4" crop="start" align="start"/> 250 <treecol id="up_file" label="&panel.uploadlist.file.label;" flex="4" crop="start" align="start"/>
250 <splitter class="tree-splitter" /> 251 <splitter class="tree-splitter" />
251 <treecol id="up_title" label="&panel.uploadlist.title.label;" flex="5" crop="end" align="start" /> 252 <treecol id="up_title" label="&panel.uploadlist.title.label;" flex="5" crop="end" align="start" />
252 <splitter class="tree-splitter" /> 253 <splitter class="tree-splitter" />
253 <treecol id="up_status" label="&panel.uploadlist.status.label;" flex="1" crop="end" align="start" /> 254 <treecol id="up_status" label="&panel.uploadlist.status.label;" flex="1" crop="end" align="start" />
254 </treecols> 255 </treecols>
255 <treechildren/> 256 <treechildren/>
256 </tree> 257 </tree>
257 <progressmeter id="upload_progress" mode="undetermined" hidden="true" /> 258 <progressmeter id="upload_progress" mode="undetermined" hidden="true" />
258 <groupbox id="upload_file_props" orient="vertical" hidden="true"> 259 <groupbox id="upload_file_props" orient="vertical" hidden="true">
259 <hbox> 260 <hbox>
260 <image id="upload_file_preview" width="100" height="100" /> 261 <image id="upload_file_preview" width="100" height="100" />
261 <vbox flex="1"> 262 <vbox flex="1">
262 <grid> 263 <grid>
263 <columns> 264 <columns>
264 <column/> 265 <column/>
265 <column flex="1"/> 266 <column flex="1"/>
266 </columns> 267 </columns>
267 <rows> 268 <rows>
268 <row> 269 <row>
269 <label control="upload_filename" 270 <label control="upload_filename"
270 value="&panel.upload_props.filename.label;" /> 271 value="&panel.upload_props.filename.label;" />
271 <textbox id="upload_filename" 272 <textbox id="upload_filename"
272 oninput="fireflix.uploads.propsToSel('filename')"/> 273 oninput="fireflix.uploads.propsToSel('filename')"/>
273 </row> 274 </row>
274 <row> 275 <row>
275 <label control="upload_title" value="&panel.upload_props.title.label;" /> 276 <label control="upload_title" value="&panel.upload_props.title.label;" />
276 <textbox id="upload_title" 277 <textbox id="upload_title"
277 oninput="fireflix.uploads.propsToSel('title')"/> 278 oninput="fireflix.uploads.propsToSel('title')"/>
278 </row> 279 </row>
279 <row> 280 <row>
280 <label control="upload_tags" value="&panel.upload_props.tags.label;" /> 281 <label control="upload_tags" value="&panel.upload_props.tags.label;" />
281 <textbox id="upload_tags" 282 <textbox id="upload_tags"
282 oninput="fireflix.uploads.propsToSel('tags')"/> 283 oninput="fireflix.uploads.propsToSel('tags')"/>
283 </row> 284 </row>
284 <!-- TODO: description, public, friend, family --> 285 <!-- TODO: description, public, friend, family -->
285 </rows> 286 </rows>
286 </grid> 287 </grid>
287 <hbox> 288 <hbox>
288 <checkbox id="upload_is_public" label="&panel.upload_props.is_public;"/> 289 <checkbox id="upload_is_public" label="&panel.upload_props.is_public;"/>
289 <checkbox id="upload_is_friends" label="&panel.upload_props.is_friend;"/> 290 <checkbox id="upload_is_friends" label="&panel.upload_props.is_friend;"/>
290 <checkbox id="upload_is_family" label="&panel.upload_props.is_family;"/> 291 <checkbox id="upload_is_family" label="&panel.upload_props.is_family;"/>
291 </hbox> 292 </hbox>
292 </vbox> 293 </vbox>
293 </hbox> 294 </hbox>
294 <description id="upload_failure" hidden="true"/> 295 <description id="upload_failure" hidden="true"/>
295 </groupbox> 296 </groupbox>
296 <hbox> 297 <hbox>
297 <button class="lean" command="cmd_uploads_add" /> 298 <button class="lean" command="cmd_uploads_add" />
298 <spacer flex="1"/> 299 <spacer flex="1"/>
299 <button class="lean" command="cmd_uploads_remove" /> 300 <button class="lean" command="cmd_uploads_remove" />
300 <spacer flex="1"/> 301 <spacer flex="1"/>
301 <button class="lean" command="cmd_uploads_clear" /> 302 <button class="lean" command="cmd_uploads_clear" />
302 </hbox> 303 </hbox>
303 <hbox pack="center"> 304 <hbox pack="center">
304 <button command="cmd_uploads_upload" flex="1"/> 305 <button command="cmd_uploads_upload" flex="1"/>
305 </hbox> 306 </hbox>
306 </vbox> 307 </vbox>
307 </tabpanel> 308 </tabpanel>
308 309
309 </tabpanels> 310 </tabpanels>
310 311
311 </tabbox> 312 </tabbox>
312 313
313 </vbox> 314 </vbox>
314 315
315</page> 316</page>
diff --git a/content/fireflix.js b/content/fireflix.js
index 78e56c2..225e21c 100644
--- a/content/fireflix.js
+++ b/content/fireflix.js
@@ -247,769 +247,778 @@ var fireflix = {
247 var lb = document.getElementById('tagslist'); 247 var lb = document.getElementById('tagslist');
248 var _this = this; 248 var _this = this;
249 this.flickr.api_call( 249 this.flickr.api_call(
250 { 250 {
251 method: 'flickr.tags.getListUser', 251 method: 'flickr.tags.getListUser',
252 auth_token: 'default', 252 auth_token: 'default',
253 }, function(xr) { 253 }, function(xr) {
254 var x = xr.responseXML; 254 var x = xr.responseXML;
255 var xp = x.evaluate( 255 var xp = x.evaluate(
256 '/rsp/who/tags/tag', x, null, 256 '/rsp/who/tags/tag', x, null,
257 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); 257 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
258 // TODO: clear list 258 // TODO: clear list
259 var n; while(n=xp.iterateNext()) { 259 var n; while(n=xp.iterateNext()) {
260 lb.appendItem(n.firstChild.nodeValue); 260 lb.appendItem(n.firstChild.nodeValue);
261 } 261 }
262 }, function(x,s,c,m) { 262 }, function(x,s,c,m) {
263 _this.flickr_failure(x,s,c,m); 263 _this.flickr_failure(x,s,c,m);
264 } 264 }
265 ); 265 );
266 }, 266 },
267 267
268 uploadObserver: { 268 uploadObserver: {
269 fireflix: null, 269 fireflix: null,
270 init: function(f) { 270 init: function(f) {
271 this.fireflix = f; 271 this.fireflix = f;
272 }, 272 },
273 getSupportedFlavours: function() { 273 getSupportedFlavours: function() {
274 var rv = new FlavourSet(); 274 var rv = new FlavourSet();
275 rv.appendFlavour('application/x-moz-file','nsIFile'); 275 rv.appendFlavour('application/x-moz-file','nsIFile');
276 rv.appendFlavour('application/x-moz-url'); 276 rv.appendFlavour('application/x-moz-url');
277 rv.appendFlavour('text/uri-list'); 277 rv.appendFlavour('text/uri-list');
278 rv.appendFlavour('text/unicode'); 278 rv.appendFlavour('text/unicode');
279 return rv; 279 return rv;
280 }, 280 },
281 canHandleMultipleItems: true, 281 canHandleMultipleItems: true,
282 onDragOver: function(ev,fl,sess) { 282 onDragOver: function(ev,fl,sess) {
283 return true; 283 return true;
284 }, 284 },
285 onDrop: function(ev,dd,s) { 285 onDrop: function(ev,dd,s) {
286 var ldf = null; 286 var ldf = null;
287 for(var i in dd.dataList) { 287 for(var i in dd.dataList) {
288 var di = dd.dataList[i]; 288 var di = dd.dataList[i];
289 var dif = di.first; 289 var dif = di.first;
290 if( 290 if(
291 ldf==null 291 ldf==null
292 || ldf.flavour.contentType!=dif.flavour.contentType 292 || ldf.flavour.contentType!=dif.flavour.contentType
293 || ldf.contentLength!=dif.contentLength 293 || ldf.contentLength!=dif.contentLength
294 || ldf.data!=dif.data ) 294 || ldf.data!=dif.data )
295 this.drop_item(ev,di,s); 295 this.drop_item(ev,di,s);
296 ldf = dif; 296 ldf = dif;
297 } 297 }
298 }, 298 },
299 drop_item: function(ev,di,s) { 299 drop_item: function(ev,di,s) {
300 var d = di.first; 300 var d = di.first;
301 switch(d.flavour.contentType) { 301 switch(d.flavour.contentType) {
302 case 'text/unicode': 302 case 'text/unicode':
303 this.drop_urilist(ev,d.data,s); 303 this.drop_urilist(ev,d.data,s);
304 break; 304 break;
305 case 'application/x-moz-file': 305 case 'application/x-moz-file':
306 this.fireflix.uploads.add(d.data.path); 306 this.fireflix.uploads.add(d.data.path);
307 document.getElementById('fireflix_tabs').selectedTab 307 document.getElementById('fireflix_tabs').selectedTab
308 = document.getElementById('tab_upload'); 308 = document.getElementById('tab_upload');
309 break; 309 break;
310 case 'text/uri-list': 310 case 'text/uri-list':
311 // is it ascii or could it be utf8? 311 // is it ascii or could it be utf8?
312 this.drop_urilist(ev,splitascii(d.data),s); 312 this.drop_urilist(ev,splitascii(d.data),s);
313 break; 313 break;
314 default: alert(d.flavour.contentType+':'+d.data); break; 314 default: alert(d.flavour.contentType+':'+d.data); break;
315 }; 315 };
316 }, 316 },
317 drop_urilist: function(ev,ul,s) { 317 drop_urilist: function(ev,ul,s) {
318 // TODO: check for being a file? 318 // TODO: check for being a file?
319 var us = decodeURIComponent(ul).split(/[\r\n]/); 319 var us = decodeURIComponent(ul).split(/[\r\n]/);
320 for(var ui in us) 320 for(var ui in us)
321 if(/\S/.test(us[ui])) 321 if(/\S/.test(us[ui]))
322 this.fireflix.uploads.add(us[ui]); 322 this.fireflix.uploads.add(us[ui]);
323 document.getElementById('fireflix_tabs').selectedTab 323 document.getElementById('fireflix_tabs').selectedTab
324 = document.getElementById('tab_upload'); 324 = document.getElementById('tab_upload');
325 } 325 }
326 }, 326 },
327 327
328 uploads: { 328 uploads: {
329 fireflix: null, 329 fireflix: null,
330 init: function(f) { 330 init: function(f) {
331 this.fireflix=f; 331 this.fireflix=f;
332 pull_elements(this,document,[ 332 pull_elements(this,document,[
333 'upload_filename','upload_title','upload_file_preview', 333 'upload_filename','upload_title','upload_file_preview',
334 'upload_file_props','upload_progress','upload_tags', 334 'upload_file_props','upload_progress','upload_tags',
335 'cmd_uploads_upload', 'upload_failure', 'upload_is_public', 335 'cmd_uploads_upload', 'upload_failure', 'upload_is_public',
336 'upload_is_friends', 'upload_is_family' 336 'upload_is_friends', 'upload_is_family'
337 ]); 337 ]);
338 document.getElementById('uploadlist').view = this; 338 document.getElementById('uploadlist').view = this;
339 this.upload_is_public.addEventListener( 339 this.upload_is_public.addEventListener(
340 'CheckboxStateChange', { that: this, 340 'CheckboxStateChange', { that: this,
341 handleEvent: function(ev) { this.that.propsToSel('is_public'); } 341 handleEvent: function(ev) { this.that.propsToSel('is_public'); }
342 }, false ); 342 }, false );
343 this.upload_is_friends.addEventListener( 343 this.upload_is_friends.addEventListener(
344 'CheckboxStateChange', { that: this, 344 'CheckboxStateChange', { that: this,
345 handleEvent: function(ev) { this.that.propsToSel('is_friends'); } 345 handleEvent: function(ev) { this.that.propsToSel('is_friends'); }
346 }, false ); 346 }, false );
347 this.upload_is_family.addEventListener( 347 this.upload_is_family.addEventListener(
348 'CheckboxStateChange', { that: this, 348 'CheckboxStateChange', { that: this,
349 handleEvent: function(ev) { this.that.propsToSel('is_family'); } 349 handleEvent: function(ev) { this.that.propsToSel('is_family'); }
350 }, false ); 350 }, false );
351 }, 351 },
352 files: new Array(), 352 files: new Array(),
353 rowCount: 0, 353 rowCount: 0,
354 getCellText: function(r,c) { 354 getCellText: function(r,c) {
355 var f = this.files[r]; 355 var f = this.files[r];
356 if(c.id=='up_file') return f.file; 356 if(c.id=='up_file') return f.file;
357 if(c.id=='up_title') return f.title; 357 if(c.id=='up_title') return f.title;
358 if(c.id=='up_status') return f.state; 358 if(c.id=='up_status') return f.state;
359 return c.id; 359 return c.id;
360 }, 360 },
361 setTree: function(t) { this.tree = t }, 361 setTree: function(t) { this.tree = t },
362 isContainer: function(r) { return false; }, 362 isContainer: function(r) { return false; },
363 isSeparator: function(r) { return false; }, 363 isSeparator: function(r) { return false; },
364 isSorted: function(r) { return false; }, 364 isSorted: function(r) { return false; },
365 getLevel: function(r) { return 0; }, 365 getLevel: function(r) { return 0; },
366 getImageSrc: function(r,c) { return null }, 366 getImageSrc: function(r,c) { return null },
367 getRowProperties: function(r,p) { 367 getRowProperties: function(r,p) {
368 try { 368 try {
369 if(!Components) return; 369 if(!Components) return;
370 }catch(e) { return } 370 }catch(e) { return }
371 var f = this.files[r]; 371 var f = this.files[r];
372 var as = Components.classes['@mozilla.org/atom-service;1']. 372 var as = Components.classes['@mozilla.org/atom-service;1'].
373 getService(Components.interfaces.nsIAtomService); 373 getService(Components.interfaces.nsIAtomService);
374 p.AppendElement(as.getAtom(f.state)); 374 p.AppendElement(as.getAtom(f.state));
375 }, 375 },
376 getCellProperties: function(r,c,p) { this.getRowProperties(r,p); }, 376 getCellProperties: function(r,c,p) { this.getRowProperties(r,p); },
377 getColumnProperties: function(c,p) { }, 377 getColumnProperties: function(c,p) { },
378 cycleHeader: function(cid,e) { }, 378 cycleHeader: function(cid,e) { },
379 getParentIndex: function(r) { return -1; }, 379 getParentIndex: function(r) { return -1; },
380 drop: function(r,o) { }, 380 drop: function(r,o) { },
381 canDropBeforeAfter: function(r,b) { return false }, 381 canDropBeforeAfter: function(r,b) { return false },
382 382
383 add: function(f) { 383 add: function(f) {
384 if(f.indexOf('file:/')==0) { 384 if(f.indexOf('file:/')==0) {
385 f = f.substr(5); 385 f = f.substr(5);
386 while(f.substr(0,2)=='//') { // XXX: not very performant, is it? ;-) 386 while(f.substr(0,2)=='//') { // XXX: not very performant, is it? ;-)
387 f = f.substr(1); 387 f = f.substr(1);
388 } 388 }
389 } 389 }
390 var t = f; 390 var t = f;
391 var ls = t.lastIndexOf('/'); 391 var ls = t.lastIndexOf('/');
392 if(ls>0) t = t.substr(ls+1); 392 if(ls>0) t = t.substr(ls+1);
393 ls = t.lastIndexOf('\\'); 393 ls = t.lastIndexOf('\\');
394 if(ls>0) t = t.substr(ls+1); 394 if(ls>0) t = t.substr(ls+1);
395 var ld = t.lastIndexOf('.'); 395 var ld = t.lastIndexOf('.');
396 if(ld>0) t = t.substr(0,ld); 396 if(ld>0) t = t.substr(0,ld);
397 this.files.push( { 397 this.files.push( {
398 file: f, 398 file: f,
399 title: t, 399 title: t,
400 tags: '', 400 tags: '',
401 is_public: true, is_friend: false, is_family: false, 401 is_public: true, is_friend: false, is_family: false,
402 state: 'pending' 402 state: 'pending'
403 } ); 403 } );
404 this.rowCount = this.files.length; 404 this.rowCount = this.files.length;
405 this.tree.rowCountChanged(this.rowCount-1,1); 405 this.tree.rowCountChanged(this.rowCount-1,1);
406 }, 406 },
407 407
408 upload_worker: function() { 408 upload_worker: function() {
409 for(var f in this.files) { 409 for(var f in this.files) {
410 if(this.files[f].state=='pending') { 410 if(this.files[f].state=='pending') {
411 var ff = this.files[f]; 411 var ff = this.files[f];
412 this.on_file_upload(ff); 412 this.on_file_upload(ff);
413 ff.state='uploading'; 413 ff.state='uploading';
414 this.tree.invalidate(); 414 this.tree.invalidate();
415 var _this = this; 415 var _this = this;
416 this.fireflix.flickr.upload_file( 416 this.fireflix.flickr.upload_file(
417 ff.file, { 417 ff.file, {
418 title: ff.title, tags: ff.tags, 418 title: ff.title, tags: ff.tags,
419 is_public: ff.is_public?'1':'0', 419 is_public: ff.is_public?'1':'0',
420 is_friend: ff.is_friend?'1':'0', 420 is_friend: ff.is_friend?'1':'0',
421 is_family: ff.is_family?'1':'0' 421 is_family: ff.is_family?'1':'0'
422 }, function(x,p) { 422 }, function(x,p) {
423 ff.photoid = p; 423 ff.photoid = p;
424 _this.batch_ids.push(p); 424 _this.batch_ids.push(p);
425 ff.state='completed'; 425 ff.state='completed';
426 _this.tree.invalidate(); 426 _this.tree.invalidate();
427 window.setTimeout(_this.upload_to,0,_this); 427 window.setTimeout(_this.upload_to,0,_this);
428 }, function(x,s,c,m) { 428 }, function(x,s,c,m) {
429 ff.state='failed'; 429 ff.state='failed';
430 ff.flickr_errcode = c; 430 ff.flickr_errcode = c;
431 ff.flickr_errmsg = m; 431 ff.flickr_errmsg = m;
432 _this.tree.invalidate(); 432 _this.tree.invalidate();
433 window.setTimeout(_this.upload_to,0,_this); 433 window.setTimeout(_this.upload_to,0,_this);
434 } 434 }
435 ); 435 );
436 return; 436 return;
437 } 437 }
438 } 438 }
439 this.on_finish_upload(); 439 this.on_finish_upload();
440 }, 440 },
441 upload_to: function(_this) { _this.upload_worker(); }, 441 upload_to: function(_this) { _this.upload_worker(); },
442 on_file_upload: function(f) { 442 on_file_upload: function(f) {
443 this.cmd_uploads_upload.setAttribute('disabled','true'); 443 this.cmd_uploads_upload.setAttribute('disabled','true');
444 for(var fi in this.files) { 444 for(var fi in this.files) {
445 if(this.files[fi].file==f.file) { 445 if(this.files[fi].file==f.file) {
446 this.tree.ensureRowIsVisible(fi); 446 this.tree.ensureRowIsVisible(fi);
447 this.selection.rangedSelect(fi,fi,false); 447 this.selection.rangedSelect(fi,fi,false);
448 this.selection.currentIndex = fi; 448 this.selection.currentIndex = fi;
449 this.selToProps(); 449 this.selToProps();
450 break; 450 break;
451 } 451 }
452 } 452 }
453 }, 453 },
454 on_finish_upload: function() { 454 on_finish_upload: function() {
455 if(this.batch_ids.length) { 455 if(this.batch_ids.length) {
456 var psn = prompt(this.fireflix.loc_strings.getString('postUploadPhotoset')); 456 var psn = prompt(this.fireflix.loc_strings.getString('postUploadPhotoset'));
457 if(psn!=null) { 457 if(psn!=null) {
458 var pids = this.batch_ids.join(','); 458 var pids = this.batch_ids.join(',');
459 var ppid = this.batch_ids[0]; 459 var ppid = this.batch_ids[0];
460 var _this = this; 460 var _this = this;
461 this.fireflix.flickr.api_call( 461 this.fireflix.flickr.api_call(
462 { 462 {
463 method: 'flickr.photosets.create', 463 method: 'flickr.photosets.create',
464 auth_token: 'default', 464 auth_token: 'default',
465 title: psn, 465 title: psn,
466 primary_photo_id: ppid 466 primary_photo_id: ppid
467 }, function(x) { 467 }, function(x) {
468 var npid = 468 var npid =
469 x.responseXML.getElementsByTagName('photoset').item(0).getAttribute('id'); 469 x.responseXML.getElementsByTagName('photoset').item(0).getAttribute('id');
470 _this.fireflix.flickr.api_call( 470 _this.fireflix.flickr.api_call(
471 { 471 {
472 method: 'flickr.photosets.editPhotos', 472 method: 'flickr.photosets.editPhotos',
473 auth_token: 'default', 473 auth_token: 'default',
474 photoset_id: npid, 474 photoset_id: npid,
475 primary_photo_id: ppid, 475 primary_photo_id: ppid,
476 photo_ids: pids 476 photo_ids: pids
477 }, function(x) { 477 }, function(x) {
478 _this.fireflix.refresh_sets(); 478 _this.fireflix.refresh_sets();
479 }, function(x,s,c,m) { 479 }, function(x,s,c,m) {
480 _this.fireflix.flickr_failure(x,s,c,m); 480 _this.fireflix.flickr_failure(x,s,c,m);
481 } 481 }
482 ); 482 );
483 }, function(x,s,c,m) { 483 }, function(x,s,c,m) {
484 _this.fireflix.flickr_failure(x,s,c,m); 484 _this.fireflix.flickr_failure(x,s,c,m);
485 } 485 }
486 ); 486 );
487 } 487 }
488 } 488 }
489 this.selection.clearSelection(); 489 this.selection.clearSelection();
490 this.cmd_uploads_upload.setAttribute('disabled','false'); 490 this.cmd_uploads_upload.setAttribute('disabled','false');
491 this.upload_progress.setAttribute('hidden','true'); 491 this.upload_progress.setAttribute('hidden','true');
492 }, 492 },
493 493
494 clear_list: function() { 494 clear_list: function() {
495 this.tree.beginUpdateBatch(); 495 this.tree.beginUpdateBatch();
496 this.rowCount = 0; 496 this.rowCount = 0;
497 this.files = new Array(); 497 this.files = new Array();
498 this.tree.endUpdateBatch(); 498 this.tree.endUpdateBatch();
499 this.selToProps(); 499 this.selToProps();
500 }, 500 },
501 selectionChanged: function() { 501 selectionChanged: function() {
502 this.selToProps(); 502 this.selToProps();
503 }, 503 },
504 disableProps: function() { 504 disableProps: function() {
505 this.upload_filename.value=''; 505 this.upload_filename.value='';
506 this.upload_filename.disabled = true; 506 this.upload_filename.disabled = true;
507 this.upload_title.value=''; 507 this.upload_title.value='';
508 this.upload_title.disabled = true; 508 this.upload_title.disabled = true;
509 this.upload_file_preview.src = null; 509 this.upload_file_preview.src = null;
510 this.upload_tags.value=''; 510 this.upload_tags.value='';
511 this.upload_tags.disabled = true; 511 this.upload_tags.disabled = true;
512 this.upload_is_public.disabled = true; 512 this.upload_is_public.disabled = true;
513 this.upload_is_friends.disabled = true; 513 this.upload_is_friends.disabled = true;
514 this.upload_is_family.disabled = true; 514 this.upload_is_family.disabled = true;
515 /* this.upload_file_props.hidden = true; */ 515 /* this.upload_file_props.hidden = true; */
516 }, 516 },
517 selToProps: function() { 517 selToProps: function() {
518 if(!this.selection.count) { 518 if(!this.selection.count) {
519 this.disableProps(); 519 this.disableProps();
520 this.upload_file_props.hidden = true; 520 this.upload_file_props.hidden = true;
521 }else if(this.selection.count==1) { 521 }else if(this.selection.count==1) {
522 var f=this.files[this.selection.currentIndex]; 522 var f=this.files[this.selection.currentIndex];
523 if(f==null) { 523 if(f==null) {
524 this.disableProps(); 524 this.disableProps();
525 this.upload_file_props.hidden = true; 525 this.upload_file_props.hidden = true;
526 }else{ 526 }else{
527 var inactives = f.state!='pending'; 527 var inactives = f.state!='pending';
528 this.upload_filename.value = f.file; this.upload_filename.disabled = inactives; 528 this.upload_filename.value = f.file; this.upload_filename.disabled = inactives;
529 this.upload_title.value = f.title; this.upload_title.disabled = inactives; 529 this.upload_title.value = f.title; this.upload_title.disabled = inactives;
530 this.upload_file_preview.src = 'file:///'+f.file; 530 this.upload_file_preview.src = 'file:///'+f.file;
531 this.upload_tags.value = f.tags; this.upload_tags.disabled = inactives; 531 this.upload_tags.value = f.tags; this.upload_tags.disabled = inactives;
532 this.upload_is_public.checked = f.is_public; this.upload_is_public.disabled = inactives; 532 this.upload_is_public.checked = f.is_public; this.upload_is_public.disabled = inactives;
533 this.upload_is_friends.checked = f.is_friend; this.upload_is_friends.disabled = inactives; 533 this.upload_is_friends.checked = f.is_friend; this.upload_is_friends.disabled = inactives;
534 this.upload_is_family.checked = f.is_family; this.upload_is_family.disabled = inactives; 534 this.upload_is_family.checked = f.is_family; this.upload_is_family.disabled = inactives;
535 if(f.state=='failed') { 535 if(f.state=='failed') {
536 this.upload_failure.textContent=((f.flickr_errcode<0)?'':f.flickr_errcode+': ')+f.flickr_errmsg; 536 this.upload_failure.textContent=((f.flickr_errcode<0)?'':f.flickr_errcode+': ')+f.flickr_errmsg;
537 this.upload_failure.hidden = false; 537 this.upload_failure.hidden = false;
538 }else{ 538 }else{
539 this.upload_failure.hidden = true; 539 this.upload_failure.hidden = true;
540 } 540 }
541 this.upload_file_props.hidden = false; 541 this.upload_file_props.hidden = false;
542 } 542 }
543 }else{ 543 }else{
544 var ftitle = null; var onetitle = true; 544 var ftitle = null; var onetitle = true;
545 var ftags = null; var onetag = true; 545 var ftags = null; var onetag = true;
546 var fs = 0; 546 var fs = 0;
547 for(var ff in this.files) { 547 for(var ff in this.files) {
548 if(this.selection.isSelected(ff) && this.files[ff].state=='pending' ) { 548 if(this.selection.isSelected(ff) && this.files[ff].state=='pending' ) {
549 ++fs; 549 ++fs;
550 if(ftitle==null) { 550 if(ftitle==null) {
551 ftitle = this.files[ff].title; 551 ftitle = this.files[ff].title;
552 }else if(ftitle!=this.files[ff].title) { 552 }else if(ftitle!=this.files[ff].title) {
553 onetitle = false; 553 onetitle = false;
554 } 554 }
555 if(ftags==null) { 555 if(ftags==null) {
556 ftags = this.files[ff].tags; 556 ftags = this.files[ff].tags;
557 }else if(ftags!=this.files[ff].tags) { 557 }else if(ftags!=this.files[ff].tags) {
558 onetag = false; 558 onetag = false;
559 } 559 }
560 } 560 }
561 } 561 }
562 if(fs) { 562 if(fs) {
563 this.upload_filename.value=''; 563 this.upload_filename.value='';
564 this.upload_filename.disabled = true; 564 this.upload_filename.disabled = true;
565 if(onetitle) 565 if(onetitle)
566 this.upload_title.value = ftitle; 566 this.upload_title.value = ftitle;
567 this.upload_title.disabled = false; 567 this.upload_title.disabled = false;
568 if(onetag) 568 if(onetag)
569 this.upload_tags.value = ftags; 569 this.upload_tags.value = ftags;
570 this.upload_tags.disabled = false; 570 this.upload_tags.disabled = false;
571 this.upload_file_preview.src = null; 571 this.upload_file_preview.src = null;
572 this.upload_failure.hidden = true; 572 this.upload_failure.hidden = true;
573 this.upload_file_props.hidden = false; 573 this.upload_file_props.hidden = false;
574 }else 574 }else
575 this.disableProps(); 575 this.disableProps();
576 this.upload_file_props.hidden = true; 576 this.upload_file_props.hidden = true;
577 } 577 }
578 }, 578 },
579 propsToSel: function(prop) { 579 propsToSel: function(prop) {
580 if(this.selection.count<=0) return; 580 if(this.selection.count<=0) return;
581 for(var ff in this.files) { 581 for(var ff in this.files) {
582 if(this.selection.isSelected(ff) && this.files[ff].state=='pending') { 582 if(this.selection.isSelected(ff) && this.files[ff].state=='pending') {
583 if(prop=='filename') this.files[ff].file = this.upload_filename.value; 583 if(prop=='filename') this.files[ff].file = this.upload_filename.value;
584 if(prop=='title') this.files[ff].title = this.upload_title.value; 584 if(prop=='title') this.files[ff].title = this.upload_title.value;
585 if(prop=='tags') this.files[ff].tags = this.upload_tags.value; 585 if(prop=='tags') this.files[ff].tags = this.upload_tags.value;
586 if(prop=='is_public') this.files[ff].is_public = this.upload_is_public.checked; 586 if(prop=='is_public') this.files[ff].is_public = this.upload_is_public.checked;
587 if(prop=='is_friends') this.files[ff].is_friend = this.upload_is_friends.checked; 587 if(prop=='is_friends') this.files[ff].is_friend = this.upload_is_friends.checked;
588 if(prop=='is_family') this.files[ff].is_family = this.upload_is_family.checked; 588 if(prop=='is_family') this.files[ff].is_family = this.upload_is_family.checked;
589 this.tree.invalidateRow(ff); 589 this.tree.invalidateRow(ff);
590 } 590 }
591 } 591 }
592 }, 592 },
593 593
594 on_upload: function() { 594 on_upload: function() {
595 this.selToProps(); 595 this.selToProps();
596 this.batch_ids = new Array(); 596 this.batch_ids = new Array();
597 this.upload_progress.value=0; 597 this.upload_progress.value=0;
598 this.upload_progress.setAttribute('hidden','false'); 598 this.upload_progress.setAttribute('hidden','false');
599 this.upload_worker(); 599 this.upload_worker();
600 }, 600 },
601 on_clear: function() { 601 on_clear: function() {
602 this.clear_list(); 602 this.clear_list();
603 }, 603 },
604 on_remove: function() { 604 on_remove: function() {
605 if(this.selection.count) { 605 if(this.selection.count) {
606 this.tree.beginUpdateBatch(); 606 this.tree.beginUpdateBatch();
607 for(var i=this.files.length-1;i>=0;--i) { 607 for(var i=this.files.length-1;i>=0;--i) {
608 if(this.selection.isSelected(i)) { 608 if(this.selection.isSelected(i)) {
609 this.files.splice(i,1); 609 this.files.splice(i,1);
610 this.rowCount--; 610 this.rowCount--;
611 } 611 }
612 } 612 }
613 this.tree.endUpdateBatch(); 613 this.tree.endUpdateBatch();
614 this.selection.clearSelection(); 614 this.selection.clearSelection();
615 } 615 }
616 }, 616 },
617 on_add: function() { 617 on_add: function() {
618 var ifp = Components.interfaces.nsIFilePicker; 618 var ifp = Components.interfaces.nsIFilePicker;
619 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(ifp); 619 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(ifp);
620 fp.init(window, "Select a File", ifp.modeOpenMultiple); 620 fp.init(window, "Select a File", ifp.modeOpenMultiple);
621 fp.appendFilters(ifp.filterImages); 621 fp.appendFilters(ifp.filterImages);
622 var rv = fp.show(); 622 var rv = fp.show();
623 if(rv==ifp.returnOK) { 623 if(rv==ifp.returnOK) {
624 var ff = fp.files; 624 var ff = fp.files;
625 while(ff.hasMoreElements()) { 625 while(ff.hasMoreElements()) {
626 var f = ff.getNext(); 626 var f = ff.getNext();
627 f.QueryInterface(Components.interfaces.nsIFile); 627 f.QueryInterface(Components.interfaces.nsIFile);
628 this.add(f.path); 628 this.add(f.path);
629 } 629 }
630 } 630 }
631 },
632 on_cmd_open: function(ev) {
633 if(this.selection.currentIndex<0) return;
634 var f = this.files[this.selection.currentIndex];
635 if(f.photoid) {
636 this.fireflix.openTab(
637 this.fireflix.flickr.make_uploader_edit_url(f.photoid)
638 );
639 }else{
640 this.fireflix.openTab( 'file://'+f.file);
641 }
631 } 642 }
632 }, 643 },
633 644
634 on_set_props: function() { 645 on_set_props: function() {
635 var pset = this.photosets.sets[this.photosets.selection.currentIndex]; 646 var pset = this.photosets.sets[this.photosets.selection.currentIndex];
636 window.openDialog( 647 window.openDialog(
637 "chrome://fireflix/content/photoset-props.xul", 648 "chrome://fireflix/content/photoset-props.xul",
638 null, "dependent,modal,dialog,chrome", this, 649 null, "dependent,modal,dialog,chrome", this,
639 pset ); 650 pset );
640 if(pset.dirty) { 651 if(pset.dirty) {
641 var _this = this; 652 var _this = this;
642 this.flickr.api_call( 653 this.flickr.api_call(
643 { 654 {
644 method: 'flickr.photosets.editMeta', 655 method: 'flickr.photosets.editMeta',
645 auth_token: 'default', 656 auth_token: 'default',
646 photoset_id: pset.id, 657 photoset_id: pset.id,
647 title: pset.title, 658 title: pset.title,
648 description: pset.description 659 description: pset.description
649 }, function(xr) { 660 }, function(xr) {
650 pset.dirty = false; 661 pset.dirty = false;
651 _this.flickr.api_call( 662 _this.flickr.api_call(
652 { 663 {
653 method: 'flickr.photosets.getPhotos', 664 method: 'flickr.photosets.getPhotos',
654 auth_token: 'default', 665 auth_token: 'default',
655 photoset_id: pset.id 666 photoset_id: pset.id
656 }, function(xr) { 667 }, function(xr) {
657 var x = xr.responseXML; 668 var x = xr.responseXML;
658 var xp = x.evaluate( 669 var xp = x.evaluate(
659 '/rsp/photoset/photo', x, null, 670 '/rsp/photoset/photo', x, null,
660 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); 671 XPathResult.ORDERED_NODE_ITERATOR_TYPE, null );
661 var phids = new Array(); 672 var phids = new Array();
662 var priph = null; 673 var priph = null;
663 var n; while(n=xp.iterateNext()) { 674 var n; while(n=xp.iterateNext()) {
664 var pid = n.getAttribute('id'); 675 var pid = n.getAttribute('id');
665 phids.push( pid ); 676 phids.push( pid );
666 if(pid==pset.primary && n.getAttribute('isprimary')!='1') 677 if(pid==pset.primary && n.getAttribute('isprimary')!='1')
667 priph = pid; 678 priph = pid;
668 } 679 }
669 if(priph) { 680 if(priph) {
670 _this.flickr.api_call( 681 _this.flickr.api_call(
671 { 682 {
672 method: 'flickr.photosets.editPhotos', 683 method: 'flickr.photosets.editPhotos',
673 auth_token: 'default', 684 auth_token: 'default',
674 photoset_id: pset.id, 685 photoset_id: pset.id,
675 primary_photo_id: priph, 686 primary_photo_id: priph,
676 photo_ids: phids.join(',') 687 photo_ids: phids.join(',')
677 }, function() { }, function(x,s,c,m) { /* flickr.photosets.editPhotos */ 688 }, function() { }, function(x,s,c,m) { /* flickr.photosets.editPhotos */
678 _this.flickr_failure(x,s,c,m); 689 _this.flickr_failure(x,s,c,m);
679 } 690 }
680 ); 691 );
681 } 692 }
682 }, function(x,s,c,m) { /* flickr.photosets.getPhotos */ 693 }, function(x,s,c,m) { /* flickr.photosets.getPhotos */
683 _this.flickr_failure(x,s,c,m); 694 _this.flickr_failure(x,s,c,m);
684 } 695 }
685 ); 696 );
686 }, function(x,s,c,m) { /* flickr.photosets.editMeta */ 697 }, function(x,s,c,m) { /* flickr.photosets.editMeta */
687 _this.flickr_failure(x,s,c,m); 698 _this.flickr_failure(x,s,c,m);
688 } 699 }
689 ); 700 );
690 } 701 }
691 }, 702 },
692 on_refresh_sets: function() { 703 on_refresh_sets: function() {
693 this.refresh_sets(); 704 this.refresh_sets();
694 }, 705 },
695 on_cmd_sets_html: function(csfx,ev) { 706 on_cmd_sets_html: function(csfx,ev) {
696 var uti = csfx.charAt(0); var utl = csfx.charAt(1); 707 var uti = csfx.charAt(0); var utl = csfx.charAt(1);
697 var rv = this.build_html(this.photoset.photos,uti,utl); 708 var rv = this.build_html(this.photoset.photos,uti,utl);
698 this.popup_content(rv); 709 this.popup_content(rv);
699 }, 710 },
700 on_cmd_setphotos_html: function(csfx,ev) { 711 on_cmd_setphotos_html: function(csfx,ev) {
701 var uti = csfx.charAt(0); var utl = csfx.charAt(1); 712 var uti = csfx.charAt(0); var utl = csfx.charAt(1);
702 var rv = ''; 713 var rv = '';
703 for(var p in this.photoset.photos) { 714 for(var p in this.photoset.photos) {
704 if(this.photoset.selection.isSelected(p)) 715 if(this.photoset.selection.isSelected(p))
705 rv += this.photo_html(this.photoset.photos[p],uti,utl)+'\n'; 716 rv += this.photo_html(this.photoset.photos[p],uti,utl)+'\n';
706 } 717 }
707 this.popup_content(rv); 718 this.popup_content(rv);
708 }, 719 },
709 720
710 on_cmd_uploads_html: function(csfx,ev) { 721 on_cmd_uploads_html: function(csfx,ev) {
711 var uti = csfx.charAt(0); var utl = csfx.charAt(1); 722 var uti = csfx.charAt(0); var utl = csfx.charAt(1);
712 var pids = new Array(); 723 var pids = new Array();
713 for(var f in this.uploads.files) { 724 for(var f in this.uploads.files) {
714 if(this.uploads.selection.isSelected(f)) 725 if(this.uploads.selection.isSelected(f))
715 if(this.uploads.files[f].photoid) 726 if(this.uploads.files[f].photoid)
716 pids.push(this.uploads.files[f].photoid); 727 pids.push(this.uploads.files[f].photoid);
717 } 728 }
718 var pp = this.uploads.rowCount*2; if(pp>500) pp = 500; 729 var pp = this.uploads.rowCount*2; if(pp>500) pp = 500;
719 var _this = this; 730 var _this = this;
720 this.flickr.api_call( 731 this.flickr.api_call(
721 { 732 {
722 method: 'flickr.photos.search', 733 method: 'flickr.photos.search',
723 auth_token: 'default', 734 auth_token: 'default',
724 extras: 'original_format', 735 extras: 'original_format',
725 user_id: 'me', 736 user_id: 'me',
726 per_page: pp 737 per_page: pp
727 }, 738 },
728 function(xr) { 739 function(xr) {
729 var x = xr.responseXML; 740 var x = xr.responseXML;
730 var rv = ''; 741 var rv = '';
731 for(var pn in pids) { 742 for(var pn in pids) {
732 var p = pids[pn]; 743 var p = pids[pn];
733 var pp = new Photo(xp_node('/rsp/photos/photo[@id='+p+']',x)); 744 var pp = new Photo(xp_node('/rsp/photos/photo[@id='+p+']',x));
734 rv += _this.photo_html(pp,uti,utl)+'\n'; 745 rv += _this.photo_html(pp,uti,utl)+'\n';
735 } 746 }
736 _this.popup_content(rv); 747 _this.popup_content(rv);
737 }, function(x,s,c,m) { 748 }, function(x,s,c,m) {
738 _this.flickr_failure(x,s,c,m); 749 _this.flickr_failure(x,s,c,m);
739 } 750 }
740 ); 751 );
741 }, 752 },
742 753
743 /* 754 /*
744 * 755 *
745 */ 756 */
746 foundphotos: { 757 foundphotos: {
747 fireflix: null, 758 fireflix: null,
748 init: function(f) { 759 init: function(f) {
749 this.fireflix = f; 760 this.fireflix = f;
750 pull_elements(this,document,[ 761 pull_elements(this,document,[
751 'search_for','search_tags','search_mine', 762 'search_for','search_tags','search_mine',
752 'searchresult_props','search_photo', 763 'searchresult_props','search_photo',
753 'searchresult_title','searchresult_description', 764 'searchresult_title','searchresult_description',
754 'search_page','cmd_search_prev_page','cmd_search_next_page' 765 'search_page','cmd_search_prev_page','cmd_search_next_page'
755 ]); 766 ]);
756 document.getElementById('searchresults').view = this; 767 document.getElementById('searchresults').view = this;
757 }, 768 },
758 photos: new Array(), 769 photos: new Array(),
759 rowCount: 0, 770 rowCount: 0,
760 getCellText: function(r,c) { 771 getCellText: function(r,c) {
761 var p = this.photos[r]; 772 var p = this.photos[r];
762 if(c.id=='sr_title') return p.title; 773 if(c.id=='sr_title') return p.title;
763 return c.id; 774 return c.id;
764 }, 775 },
765 setTree: function(t) { this.tree = t }, 776 setTree: function(t) { this.tree = t },
766 isContainer: function(r) { return false }, 777 isContainer: function(r) { return false },
767 isSeparator: function(r) { return false }, 778 isSeparator: function(r) { return false },
768 isSorted: function(r) { return false }, 779 isSorted: function(r) { return false },
769 getLevel: function(r) { return 0 }, 780 getLevel: function(r) { return 0 },
770 getImageSrc: function(r,c) { return null }, 781 getImageSrc: function(r,c) { return null },
771 getRowProperties: function(r,p) { }, 782 getRowProperties: function(r,p) { },
772 getCellProperties: function(cid,cel,p) { }, 783 getCellProperties: function(cid,cel,p) { },
773 getColumnProperties: function(cid,cel,p) { }, 784 getColumnProperties: function(cid,cel,p) { },
774 cycleHeader: function(cid,e) { }, 785 cycleHeader: function(cid,e) { },
775 getParentIndex: function(r) { return -1 }, 786 getParentIndex: function(r) { return -1 },
776 drop: function(r,o) { }, 787 drop: function(r,o) { },
777 canDropBeforeAfter: function(r,b) { return false }, 788 canDropBeforeAfter: function(r,b) { return false },
778 789
779 importXPR: function(xp) { 790 importXPR: function(xp) {
780 this.selection.clearSelection(); 791 this.selection.clearSelection();
781 this.selection.currentIndex = -1; 792 this.selection.currentIndex = -1;
782 this.searchresult_props.hidden = true; 793 this.searchresult_props.hidden = true;
783 this.tree.beginUpdateBatch(); 794 this.tree.beginUpdateBatch();
784 this.photos = new Array(); 795 this.photos = new Array();
785 var n; while(n=xp.iterateNext()) { 796 var n; while(n=xp.iterateNext()) {
786 this.photos.push(new Photo(n)); 797 this.photos.push(new Photo(n));
787 } 798 }
788 this.rowCount = this.photos.length; 799 this.rowCount = this.photos.length;
789 this.tree.endUpdateBatch(); 800 this.tree.endUpdateBatch();
790 }, 801 },
791 paging: { 802 paging: {
792 pars: null, 803 pars: null,
793 page: null, pages: null, perpage: null, total: null 804 page: null, pages: null, perpage: null, total: null
794 }, 805 },
795 search_photos: function() { 806 search_photos: function() {
796 var pars = { 807 var pars = {
797 method: 'flickr.photos.search', 808 method: 'flickr.photos.search',
798 auth_token: 'default', 809 auth_token: 'default',
799 extras: 'license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo' 810 extras: 'license,date_upload,date_taken,owner_name,icon_server,original_format,last_update,geo'
800 }; 811 };
801 if(this.search_mine.checked) 812 if(this.search_mine.checked)
802 pars.user_id='me'; 813 pars.user_id='me';
803 if(this.search_tags.checked) { 814 if(this.search_tags.checked) {
804 pars.tags=this.search_for.value.split(/ +/).join(','); 815 pars.tags=this.search_for.value.split(/ +/).join(',');
805 }else{ 816 }else{
806 pars.text=this.search_for.value; 817 pars.text=this.search_for.value;
807 } 818 }
808 this.paging.pars = new Object(); 819 this.paging.pars = new Object();
809 this.paging.page = null; this.paging.pages = null; 820 this.paging.page = null; this.paging.pages = null;
810 this.paging.perpage = null; this.paging.total = null; 821 this.paging.perpage = null; this.paging.total = null;
811 for(var p in pars) this.paging.pars[p] = pars[p]; 822 for(var p in pars) this.paging.pars[p] = pars[p];
812 this.perform_search(pars); 823 this.perform_search(pars);
813 }, 824 },
814 perform_search: function(p) { 825 perform_search: function(p) {
815 var _this = this; 826 var _this = this;
816 this.fireflix.flickr.api_call( p, 827 this.fireflix.flickr.api_call( p,
817 function(xr) { 828 function(xr) {
818 var x = xr.responseXML; 829 var x = xr.responseXML;
819 var xp = xp_nodes('/rsp/photos/photo',x); 830 var xp = xp_nodes('/rsp/photos/photo',x);
820 _this.importXPR(xp); 831 _this.importXPR(xp);
821 _this.tree.ensureRowIsVisible(0); 832 _this.tree.ensureRowIsVisible(0);
822 xp = xp_node('/rsp/photos',x); 833 xp = xp_node('/rsp/photos',x);
823 _this.paging.page = parseInt(xp.getAttribute('page')); 834 _this.paging.page = parseInt(xp.getAttribute('page'));
824 _this.paging.pages = parseInt(xp.getAttribute('pages')); 835 _this.paging.pages = parseInt(xp.getAttribute('pages'));
825 _this.paging.perpage = parseInt(xp.getAttribute('perpage')); 836 _this.paging.perpage = parseInt(xp.getAttribute('perpage'));
826 _this.paging.total = parseInt(xp.getAttribute('total')); 837 _this.paging.total = parseInt(xp.getAttribute('total'));
827 _this.update_paging(); 838 _this.update_paging();
828 _this.on_select(); 839 _this.on_select();
829 }, function(x,s,c,m) { 840 }, function(x,s,c,m) {
830 _this.fireflix.flickr_failure(x,s,c,m); 841 _this.fireflix.flickr_failure(x,s,c,m);
831 } 842 }
832 ); 843 );
833 }, 844 },
834 on_cmd_prev: function(ev) { 845 on_cmd_prev: function(ev) {
835 var pars = new Object(); 846 var pars = new Object();
836 for(var p in this.paging.pars) pars[p] = this.paging.pars[p]; 847 for(var p in this.paging.pars) pars[p] = this.paging.pars[p];
837 pars.page=this.paging.page-1; pars.per_page=this.paging.perpage; 848 pars.page=this.paging.page-1; pars.per_page=this.paging.perpage;
838 this.perform_search(pars); 849 this.perform_search(pars);
839 }, 850 },
840 on_cmd_next: function(ev) { 851 on_cmd_next: function(ev) {
841 var pars = new Object(); 852 var pars = new Object();
842 for(var p in this.paging.pars) pars[p] = this.paging.pars[p]; 853 for(var p in this.paging.pars) pars[p] = this.paging.pars[p];
843 pars.page=this.paging.page+1; pars.per_page=this.paging.perpage; 854 pars.page=this.paging.page+1; pars.per_page=this.paging.perpage;
844 this.perform_search(pars); 855 this.perform_search(pars);
845 }, 856 },
846 update_paging: function() { 857 update_paging: function() {
847 if(! (this.paging.pars && this.paging.page && this.paging.pages) ) { 858 if(! (this.paging.pars && this.paging.page && this.paging.pages) ) {
848 this.search_page.value=''; this.search_page.hidden = true; 859 this.search_page.value=''; this.search_page.hidden = true;
849 this.cmd_search_prev_page.setAttribute('disabled','true'); 860 this.cmd_search_prev_page.setAttribute('disabled','true');
850 this.cmd_search_next_page.setAttribute('disabled','true'); 861 this.cmd_search_next_page.setAttribute('disabled','true');
851 }else{ 862 }else{
852 this.search_page.value=this.fireflix.loc_strings.getFormattedString('search_page',[this.paging.page,this.paging.pages]); 863 this.search_page.value=this.fireflix.loc_strings.getFormattedString('search_page',[this.paging.page,this.paging.pages]);
853 this.search_page.hidden=false; 864 this.search_page.hidden=false;
854 this.cmd_search_prev_page.setAttribute('disabled',(this.paging.page>1)?'false':'true'); 865 this.cmd_search_prev_page.setAttribute('disabled',(this.paging.page>1)?'false':'true');
855 this.cmd_search_next_page.setAttribute('disabled',(this.paging.page<this.paging.pages)?'false':'true'); 866 this.cmd_search_next_page.setAttribute('disabled',(this.paging.page<this.paging.pages)?'false':'true');
856 } 867 }
857 }, 868 },
858 render_description_frame: function(content) { 869 render_description_frame: function(content) {
859 this.searchresult_description.innerHTML = ''; 870 this.searchresult_description.innerHTML = '';
860 if(content) { 871 if(content) {
861 var dp = new DOMParser(); 872 var dp = new DOMParser();
862 var pd = dp.parseFromString( 873 var pd = dp.parseFromString(
863 '<div xmlns="http://www.w3.org/1999/xhtml">'+content+'</div>', 'text/xml' ); 874 '<div xmlns="http://www.w3.org/1999/xhtml">'+content+'</div>', 'text/xml' );
864 var de = pd.documentElement; 875 var de = pd.documentElement;
865 if(de.tagName=='parsererror') 876 if(de.tagName=='parsererror')
866 this.searchresult_description.innerHTML=this.fireflix.loc_strings.getString('broken_description'); 877 this.searchresult_description.innerHTML=this.fireflix.loc_strings.getString('broken_description');
867 else 878 else
868 this.searchresult_description.appendChild(de); 879 this.searchresult_description.appendChild(de);
869 /* of all linking elements flickr only allows a */ 880 /* of all linking elements flickr only allows a */
870 var as = this.searchresult_description.getElementsByTagName('a'); 881 var as = this.searchresult_description.getElementsByTagName('a');
871 for(var a=0;a<as.length;++a) 882 for(var a=0;a<as.length;++a)
872 as.item(a).setAttribute('target','_blank'); 883 as.item(a).setAttribute('target','_blank');
873 } 884 }
874 }, 885 },
875 on_select: function() { 886 on_select: function() {
876 if(this.selection.currentIndex<0) { 887 if(this.selection.currentIndex<0) {
877 this.searchresult_props.hidden = true; 888 this.searchresult_props.hidden = true;
878 }else{ 889 }else{
879 var p = this.photos[this.selection.currentIndex]; 890 var p = this.photos[this.selection.currentIndex];
880 if(!p) { 891 if(!p) {
881 this.searchresult_props.hidden = true; 892 this.searchresult_props.hidden = true;
882 }else{ 893 }else{
883 this.search_photo.src = this.fireflix.flickr.make_photo_url(p,'t'); 894 this.search_photo.src = this.fireflix.flickr.make_photo_url(p,'t');
884 this.searchresult_title.value = p.title; 895 this.searchresult_title.value = p.title;
885 this.searchresult_title.tooltipText = p.title; 896 this.searchresult_title.tooltipText = p.title;
886 this.render_description_frame(null); 897 this.render_description_frame(null);
887 if(p.description==null && p.description==undefined) { 898 if(p.description==null && p.description==undefined) {
888 var pid = p.id; 899 var pid = p.id;
889 var ci = this.selection.currentIndex; 900 var ci = this.selection.currentIndex;
890 var _this = this; 901 var _this = this;
891 this.fireflix.flickr.api_call( 902 this.fireflix.flickr.api_call(
892 { 903 {
893 method: 'flickr.photos.getInfo', 904 method: 'flickr.photos.getInfo',
894 auth_token: 'default', 905 auth_token: 'default',
895 photo_id: p.id, 906 photo_id: p.id,
896 secret: p.secret 907 secret: p.secret
897 }, function(xr) { 908 }, function(xr) {
898 var pp = _this.photos[ci]; 909 var pp = _this.photos[ci];
899 if(ci==_this.selection.currentIndex && pp.id==pid) { 910 if(ci==_this.selection.currentIndex && pp.id==pid) {
900 var n = xp_node('/rsp/photo',xr.responseXML); 911 var n = xp_node('/rsp/photo',xr.responseXML);
901 pp.fromNode_(n); 912 pp.fromNode_(n);
902 _this.render_description_frame(pp.description); 913 _this.render_description_frame(pp.description);
903 } 914 }
904 }, function(x,s,c,m) { 915 }, function(x,s,c,m) {
905 _this.fireflix.flickr_failure(x,s,c,m); 916 _this.fireflix.flickr_failure(x,s,c,m);
906 } 917 }
907 ); 918 );
908 this.searchresult_props.hidden = false; 919 this.searchresult_props.hidden = false;
909 }else{ 920 }else{
910 this.render_description_frame(p.description); 921 this.render_description_frame(p.description);
911 } 922 }
912 } 923 }
913 } 924 }
914 }, 925 },
915 on_cmd_open: function(ev) { 926 on_cmd_open: function(ev) {
916 if(this.selection.currentIndex<0) 927 if(this.selection.currentIndex<0) return;
917 return;
918 var p = this.photos[this.selection.currentIndex]; 928 var p = this.photos[this.selection.currentIndex];
919 if(!p.id) 929 if(!p.id) return;
920 return;
921 this.fireflix.openTab(this.fireflix.flickr.make_photo_url(p,'p')); 930 this.fireflix.openTab(this.fireflix.flickr.make_photo_url(p,'p'));
922 } 931 }
923 }, 932 },
924 933
925 photo_html: function(p,i,l) { 934 photo_html: function(p,i,l) {
926 // TODO: add alt/title when possible 935 // TODO: add alt/title when possible
927 var rv = 936 var rv =
928 '<a href="'+this.flickr.make_photo_url(p,l)+'">' + 937 '<a href="'+this.flickr.make_photo_url(p,l)+'">' +
929 '<img src="'+this.flickr.make_photo_url(p,i)+'" />'+ 938 '<img src="'+this.flickr.make_photo_url(p,i)+'" />'+
930 '</a>'; 939 '</a>';
931 return rv; 940 return rv;
932 }, 941 },
933 build_html: function(photos,uti,utl) { 942 build_html: function(photos,uti,utl) {
934 var rv = ''; 943 var rv = '';
935 for(var i in photos) { 944 for(var i in photos) {
936 var p = photos[i]; 945 var p = photos[i];
937 rv += this.photo_html(p,uti,utl)+'\n'; 946 rv += this.photo_html(p,uti,utl)+'\n';
938 } 947 }
939 return rv; 948 return rv;
940 }, 949 },
941 950
942 popup_content: function(s) { 951 popup_content: function(s) {
943 window.openDialog( 952 window.openDialog(
944 "chrome://fireflix/content/generated-content.xul", 953 "chrome://fireflix/content/generated-content.xul",
945 null, "dialog,chrome", this, s ); 954 null, "dialog,chrome", this, s );
946 }, 955 },
947 copy_to_clipboard: function(s) { 956 copy_to_clipboard: function(s) {
948 var ch = Components.classes["@mozilla.org/widget/clipboardhelper;1"] 957 var ch = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
949 .getService(Components.interfaces.nsIClipboardHelper); 958 .getService(Components.interfaces.nsIClipboardHelper);
950 ch.copyString(s); 959 ch.copyString(s);
951 }, 960 },
952 openTab: function(l) { 961 openTab: function(l) {
953 var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService( 962 var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(
954 Components.interfaces.nsIWindowMediator ); 963 Components.interfaces.nsIWindowMediator );
955 var bw = wm.getMostRecentWindow('navigator:browser'); 964 var bw = wm.getMostRecentWindow('navigator:browser');
956 var b = bw.getBrowser(); 965 var b = bw.getBrowser();
957 var t = b.addTab(l); 966 var t = b.addTab(l);
958 b.selectedTab = t; 967 b.selectedTab = t;
959 }, 968 },
960 969
961 build_menus: function() { 970 build_menus: function() {
962 this.append_html_menu( 971 this.append_html_menu(
963 document.getElementById('sets_html_menu'), 972 document.getElementById('sets_html_menu'),
964 'stm_','m_bop','cmdset_sets','cmd_sets_html' 973 'stm_','m_bop','cmdset_sets','cmd_sets_html'
965 ); 974 );
966 this.append_html_menu( 975 this.append_html_menu(
967 document.getElementById('setphotos_html_menu'), 976 document.getElementById('setphotos_html_menu'),
968 'stm_','m_bop','cmdset_setphotos','cmd_setphotos_html' 977 'stm_','m_bop','cmdset_setphotos','cmd_setphotos_html'
969 ); 978 );
970 this.append_html_menu( 979 this.append_html_menu(
971 document.getElementById('uploads_html_menu'), 980 document.getElementById('uploads_html_menu'),
972 'stm_','m_bop','cmdset_uploads','cmd_uploads_html' 981 'stm_','m_bop','cmdset_uploads','cmd_uploads_html'
973 ); 982 );
974 return; 983 return;
975 }, 984 },
976 append_html_menu: function(m,imgt,lnkt,csid,cpfx) { 985 append_html_menu: function(m,imgt,lnkt,csid,cpfx) {
977 var mp = m.appendChild(document.createElement('menupopup')); 986 var mp = m.appendChild(document.createElement('menupopup'));
978 var t; 987 var t;
979 t=mp.appendChild(document.createElement('menuitem')); 988 t=mp.appendChild(document.createElement('menuitem'));
980 t.setAttribute('label',this.loc_strings.getString('menutitle_Images')); 989 t.setAttribute('label',this.loc_strings.getString('menutitle_Images'));
981 t.setAttribute('class','menuhead');t.setAttribute('disabled','true'); 990 t.setAttribute('class','menuhead');t.setAttribute('disabled','true');
982 mp.appendChild(document.createElement('menuseparator')); 991 mp.appendChild(document.createElement('menuseparator'));
983 var cs = document.getElementById(csid); 992 var cs = document.getElementById(csid);
984 for(var iti=0;iti<imgt.length;++iti) { 993 for(var iti=0;iti<imgt.length;++iti) {
985 t = mp.appendChild(document.createElement('menu')); 994 t = mp.appendChild(document.createElement('menu'));
986 t.setAttribute('label',this.loc_strings.getString('urltype_'+imgt.charAt(iti))); 995 t.setAttribute('label',this.loc_strings.getString('urltype_'+imgt.charAt(iti)));
987 var smp = t.appendChild(document.createElement('menupopup')); 996 var smp = t.appendChild(document.createElement('menupopup'));
988 t=smp.appendChild(document.createElement('menuitem')); 997 t=smp.appendChild(document.createElement('menuitem'));
989 t.setAttribute('label',this.loc_strings.getString('menutitle_Links')); 998 t.setAttribute('label',this.loc_strings.getString('menutitle_Links'));
990 t.setAttribute('class','menuhead');t.setAttribute('disabled','true'); 999 t.setAttribute('class','menuhead');t.setAttribute('disabled','true');
991 smp.appendChild(document.createElement('menuseparator')); 1000 smp.appendChild(document.createElement('menuseparator'));
992 for(var lti=0;lti<lnkt.length;++lti) { 1001 for(var lti=0;lti<lnkt.length;++lti) {
993 var csfx = imgt.charAt(iti)+lnkt.charAt(lti); 1002 var csfx = imgt.charAt(iti)+lnkt.charAt(lti);
994 t=smp.appendChild(document.createElement('menuitem')); 1003 t=smp.appendChild(document.createElement('menuitem'));
995 t.setAttribute('label',this.loc_strings.getString('urltype_'+lnkt.charAt(lti))); 1004 t.setAttribute('label',this.loc_strings.getString('urltype_'+lnkt.charAt(lti)));
996 t.setAttribute('command',cpfx+'_'+csfx); 1005 t.setAttribute('command',cpfx+'_'+csfx);
997 t=cs.appendChild(document.createElement('command')); 1006 t=cs.appendChild(document.createElement('command'));
998 t.setAttribute('id',cpfx+'_'+csfx); 1007 t.setAttribute('id',cpfx+'_'+csfx);
999 t.setAttribute('oncommand','fireflix.on_'+cpfx+"('"+csfx+"',event)"); 1008 t.setAttribute('oncommand','fireflix.on_'+cpfx+"('"+csfx+"',event)");
1000 } 1009 }
1001 } 1010 }
1002 return mp; 1011 return mp;
1003 }, 1012 },
1004 1013
1005 flickr_failure: function(x,s,c,m) { 1014 flickr_failure: function(x,s,c,m) {
1006 if(c==98) { // Invalid auth token 1015 if(c==98) { // Invalid auth token
1007 this.flickr.reset_token(); 1016 this.flickr.reset_token();
1008 this.set_auth_state(false,false); 1017 this.set_auth_state(false,false);
1009 return; 1018 return;
1010 } 1019 }
1011 // TODO: is that beauty? 1020 // TODO: is that beauty?
1012 alert('flickr api call failed\n'+c+' '+m); 1021 alert('flickr api call failed\n'+c+' '+m);
1013 } 1022 }
1014 1023
1015}; 1024};
diff --git a/content/flickr.js b/content/flickr.js
index b8360c1..e09d5f0 100644
--- a/content/flickr.js
+++ b/content/flickr.js
@@ -1,356 +1,361 @@
1/* 1/*
2 * Photoset 2 * Photoset
3 */ 3 */
4 4
5function Photoset(s) { 5function Photoset(s) {
6 if(s instanceof Photoset) { 6 if(s instanceof Photoset) {
7 for(var p in s) this[p]=s[p]; 7 for(var p in s) this[p]=s[p];
8 }else 8 }else
9 this.fromNode(s); 9 this.fromNode(s);
10} 10}
11Photoset.prototype = { 11Photoset.prototype = {
12 id: null, 12 id: null,
13 primary: null, 13 primary: null,
14 secret: null, 14 secret: null,
15 server: null, 15 server: null,
16 photos: null, 16 photos: null,
17 title: null, 17 title: null,
18 description: null, 18 description: null,
19 fromNode: function(n) { 19 fromNode: function(n) {
20 this.id = n.getAttribute('id'); 20 this.id = n.getAttribute('id');
21 this.primary = n.getAttribute('primary'); 21 this.primary = n.getAttribute('primary');
22 this.secret = n.getAttribute('secret'); 22 this.secret = n.getAttribute('secret');
23 this.server = n.getAttribute('server'); 23 this.server = n.getAttribute('server');
24 this.photos = n.getAttribute('photos'); 24 this.photos = n.getAttribute('photos');
25 this.title = n.getElementsByTagName('title').item(0).firstChild.nodeValue; 25 this.title = n.getElementsByTagName('title').item(0).firstChild.nodeValue;
26 this.description = n.getElementsByTagName('description').item(0).firstChild; 26 this.description = n.getElementsByTagName('description').item(0).firstChild;
27 if(this.description) this.description = this.description.nodeValue; 27 if(this.description) this.description = this.description.nodeValue;
28 } 28 }
29}; 29};
30 30
31/* 31/*
32 * Photo 32 * Photo
33 */ 33 */
34function Photo(s) { 34function Photo(s) {
35 if(s instanceof Photo) { 35 if(s instanceof Photo) {
36 for(var p in s) this[p]=s[p]; 36 for(var p in s) this[p]=s[p];
37 }else 37 }else
38 this.fromNode(s); 38 this.fromNode(s);
39} 39}
40Photo.prototype = { 40Photo.prototype = {
41 id: null, secret: null, 41 id: null, secret: null,
42 server: null, 42 server: null,
43 title: null, 43 title: null,
44 isprimary: null, 44 isprimary: null,
45 license: null, 45 license: null,
46 dateupload: null, datetaken: null, datetakengranularity: null, 46 dateupload: null, datetaken: null, datetakengranularity: null,
47 ownername: null, 47 ownername: null,
48 iconserver: null, 48 iconserver: null,
49 originalformat: null, 49 originalformat: null,
50 lastupdate: null, 50 lastupdate: null,
51 fromNode: function(n) { 51 fromNode: function(n) {
52 this.id = n.getAttribute('id'); this.secret = n.getAttribute('secret'); 52 this.id = n.getAttribute('id'); this.secret = n.getAttribute('secret');
53 this.server = n.getAttribute('server'); 53 this.server = n.getAttribute('server');
54 this.title = n.getAttribute('title'); 54 this.title = n.getAttribute('title');
55 this.isprimary = n.getAttribute('isprimary'); 55 this.isprimary = n.getAttribute('isprimary');
56 this.license = n.getAttribute('license'); 56 this.license = n.getAttribute('license');
57 this.dateupload = n.getAttribute('dateupload'); 57 this.dateupload = n.getAttribute('dateupload');
58 this.datetaken = n.getAttribute('datetaken'); this.datetakengranularity = n.getAttribute('datetakengranularity'); 58 this.datetaken = n.getAttribute('datetaken'); this.datetakengranularity = n.getAttribute('datetakengranularity');
59 this.ownername = n.getAttribute('ownername'); 59 this.ownername = n.getAttribute('ownername');
60 this.iconserver = n.getAttribute('iconserver'); 60 this.iconserver = n.getAttribute('iconserver');
61 this.originalformat = n.getAttribute('originalformat'); 61 this.originalformat = n.getAttribute('originalformat');
62 this.lastupdate = n.getAttribute('lastupdate'); 62 this.lastupdate = n.getAttribute('lastupdate');
63 }, 63 },
64 fromNode_: function(n) { 64 fromNode_: function(n) {
65 var t; 65 var t;
66 // TODO: @rotation @isfavorite 66 // TODO: @rotation @isfavorite
67 this.owner = {}; 67 this.owner = {};
68 t = n.getElementsByTagName('owner').item(0); 68 t = n.getElementsByTagName('owner').item(0);
69 if(t) { 69 if(t) {
70 this.owner.nsid=t.getAttribute('nsid'); 70 this.owner.nsid=t.getAttribute('nsid');
71 this.owner.username=t.getAttribute('username'); 71 this.owner.username=t.getAttribute('username');
72 this.owner.realname=t.getAttribute('realname'); 72 this.owner.realname=t.getAttribute('realname');
73 this.owner.location=t.getAttribute.location; 73 this.owner.location=t.getAttribute.location;
74 } 74 }
75 t = n.getElementsByTagName('description').item(0); 75 t = n.getElementsByTagName('description').item(0);
76 if(t && t.firstChild) { 76 if(t && t.firstChild) {
77 this.description = t.firstChild.nodeValue; 77 this.description = t.firstChild.nodeValue;
78 } 78 }
79 // TODO: visibility/@ispublic visibility/@isfriend visibility/@isfamily 79 // TODO: visibility/@ispublic visibility/@isfriend visibility/@isfamily
80 // TODO: dates/@posted dates/@taken dates/@takengranularity dates/@lastupdate 80 // TODO: dates/@posted dates/@taken dates/@takengranularity dates/@lastupdate
81 // TODO: permissions/@permcomment permsiions/@permaddmeta 81 // TODO: permissions/@permcomment permsiions/@permaddmeta
82 // TODO: editability/@canaddcomment editability/@canaddmeta 82 // TODO: editability/@canaddcomment editability/@canaddmeta
83 // TODO: comments 83 // TODO: comments
84 // TODO: notes/note/@id notes/note/@author notes/note/@authorname 84 // TODO: notes/note/@id notes/note/@author notes/note/@authorname
85 // TODO: notes/note/@x notes/note/@y notes/note/@w notes/note/@h 85 // TODO: notes/note/@x notes/note/@y notes/note/@w notes/note/@h
86 // TODO: notes/note 86 // TODO: notes/note
87 // TODO: tags/tag/@id tags/tag/@author tags/tag/@raw tags/tag 87 // TODO: tags/tag/@id tags/tag/@author tags/tag/@raw tags/tag
88 // TODO: urls/url/@type urls/url 88 // TODO: urls/url/@type urls/url
89 } 89 }
90}; 90};
91 91
92function Flickr() { } 92function Flickr() { }
93Flickr.prototype = { 93Flickr.prototype = {
94 94
95 rest_url: 'http://www.flickr.com/services/rest/', 95 rest_url: 'http://www.flickr.com/services/rest/',
96 auth_url: 'http://flickr.com/services/auth/', 96 auth_url: 'http://flickr.com/services/auth/',
97 photo_url: 'http://static.flickr.com/', 97 photo_url: 'http://static.flickr.com/',
98 photos_url: 'http://www.flickr.com/photos/', 98 photos_url: 'http://www.flickr.com/photos/',
99 upload_url: 'http://www.flickr.com/services/upload/', 99 upload_url: 'http://www.flickr.com/services/upload/',
100 uploader_edit_url: 'http://www.flickr.com/tools/uploader_edit.gne',
100 101
101 api_sig: function(paramstr) { 102 api_sig: function(paramstr) {
102 return MD5(toutf8(this.api_shs+paramstr)); 103 return MD5(toutf8(this.api_shs+paramstr));
103 }, 104 },
104 api_call_url: function(params,url) { 105 api_call_url: function(params,url) {
105 params.api_key = this.api_key; 106 params.api_key = this.api_key;
106 var pp = new Array(); 107 var pp = new Array();
107 for(var p in params) { 108 for(var p in params) {
108 pp.push(p); 109 pp.push(p);
109 } 110 }
110 var pstr = ''; 111 var pstr = '';
111 var rv = (url?url:this.rest_url)+'?'; 112 var rv = (url?url:this.rest_url)+'?';
112 for(var p in pp.sort()) { 113 for(var p in pp.sort()) {
113 var pn = pp[p]; 114 var pn = pp[p];
114 pstr += pn+params[pn]; 115 pstr += pn+params[pn];
115 rv += pn+'='+params[pn]+'&'; 116 rv += pn+'='+params[pn]+'&';
116 } 117 }
117 rv += 'api_sig='+this.api_sig(pstr); 118 rv += 'api_sig='+this.api_sig(pstr);
118 return rv; 119 return rv;
119 }, 120 },
120 api_call: function(params, on_success, on_failure) { 121 api_call: function(params, on_success, on_failure) {
121 if(params.auth_token == 'default') 122 if(params.auth_token == 'default')
122 params.auth_token = this.token; 123 params.auth_token = this.token;
123 var x = new XMLHttpRequest(); 124 var x = new XMLHttpRequest();
124 x.open("GET",this.api_call_url(params)); 125 x.open("GET",this.api_call_url(params));
125 x.onreadystatechange=function() { 126 x.onreadystatechange=function() {
126 if(x.readyState!=4) return false; 127 if(x.readyState!=4) return false;
127 if(x.status==200) { 128 if(x.status==200) {
128 var stat = x.responseXML.firstChild.getAttribute('stat'); 129 var stat = x.responseXML.firstChild.getAttribute('stat');
129 if(stat=='ok') { 130 if(stat=='ok') {
130 if(on_success) on_success(x); 131 if(on_success) on_success(x);
131 }else{ 132 }else{
132 var e = x.responseXML.getElementsByTagName('err').item(0); 133 var e = x.responseXML.getElementsByTagName('err').item(0);
133 var ecode = e.getAttribute('code'); 134 var ecode = e.getAttribute('code');
134 var emsg = e.getAttribute('msg'); 135 var emsg = e.getAttribute('msg');
135 dump(params.method+' failed: '+ecode+' '+emsg+'\n'); 136 dump(params.method+' failed: '+ecode+' '+emsg+'\n');
136 if(on_failure) on_failure(x,stat,ecode,emsg); 137 if(on_failure) on_failure(x,stat,ecode,emsg);
137 } 138 }
138 }else{ 139 }else{
139 if(on_failure) on_failure(x); 140 if(on_failure) on_failure(x);
140 } 141 }
141 return true; 142 return true;
142 } 143 }
143 x.send(null); 144 x.send(null);
144 return true; 145 return true;
145 }, 146 },
146 147
147 frob: null, 148 frob: null,
148 authorize_0: function(perms, on_s, on_f) { 149 authorize_0: function(perms, on_s, on_f) {
149 var _this = this; 150 var _this = this;
150 this.api_call( 151 this.api_call(
151 { method: 'flickr.auth.getFrob' }, 152 { method: 'flickr.auth.getFrob' },
152 function(x) { 153 function(x) {
153 _this.frob = xp_str('/rsp/frob',x.responseXML); 154 _this.frob = xp_str('/rsp/frob',x.responseXML);
154 var u = _this.api_call_url( 155 var u = _this.api_call_url(
155 { frob: _this.frob, perms: perms?perms:'delete' }, _this.auth_url ); 156 { frob: _this.frob, perms: perms?perms:'delete' }, _this.auth_url );
156 if(on_s) on_s(x,_this.frob,u); 157 if(on_s) on_s(x,_this.frob,u);
157 }, function(x,s,c,m) { 158 }, function(x,s,c,m) {
158 if(on_f) on_f(x,s,c,m); 159 if(on_f) on_f(x,s,c,m);
159 } 160 }
160 ); 161 );
161 }, 162 },
162 token: null, 163 token: null,
163 perms: null, 164 perms: null,
164 user: null, 165 user: null,
165 authorize_1: function(on_s, on_f) { 166 authorize_1: function(on_s, on_f) {
166 var _this = this; 167 var _this = this;
167 this.api_call( 168 this.api_call(
168 { method: 'flickr.auth.getToken', frob: this.frob }, 169 { method: 'flickr.auth.getToken', frob: this.frob },
169 function(x) { 170 function(x) {
170 _this.token = xp_str('/rsp/auth/token',x.responseXML); 171 _this.token = xp_str('/rsp/auth/token',x.responseXML);
171 _this.perms = xp_str('/rsp/auth/perms',x.responseXML); 172 _this.perms = xp_str('/rsp/auth/perms',x.responseXML);
172 var u = xp_node('/rsp/auth/user',x.responseXML); 173 var u = xp_node('/rsp/auth/user',x.responseXML);
173 _this.user = { 174 _this.user = {
174 nsid: u.getAttribute('nsid'), 175 nsid: u.getAttribute('nsid'),
175 username: u.getAttribute('username'), 176 username: u.getAttribute('username'),
176 fullname: u.getAttribute('fullname') 177 fullname: u.getAttribute('fullname')
177 }; 178 };
178 if(on_s) on_s(x); 179 if(on_s) on_s(x);
179 }, function(x,s,c,m) { 180 }, function(x,s,c,m) {
180 if(on_f) on_f(x,s,c,m); 181 if(on_f) on_f(x,s,c,m);
181 } 182 }
182 ); 183 );
183 }, 184 },
184 185
185 prefs: Components.classes['@mozilla.org/preferences-service;1'].getService( 186 prefs: Components.classes['@mozilla.org/preferences-service;1'].getService(
186 Components.interfaces.nsIPrefBranch 187 Components.interfaces.nsIPrefBranch
187 ), 188 ),
188 prefs_root: 'net.klever.kin.flickr', 189 prefs_root: 'net.klever.kin.flickr',
189 save_token: function() { 190 save_token: function() {
190 // TODO: don't clear when there's nothing to clear or catch exceptions 191 // TODO: don't clear when there's nothing to clear or catch exceptions
191 if(this.token) 192 if(this.token)
192 this.prefs.setCharPref(this.prefs_root+'.auth_token',this.token); 193 this.prefs.setCharPref(this.prefs_root+'.auth_token',this.token);
193 else 194 else
194 this.prefs.clearUserPref(this.prefs_root+'.auth_token'); 195 this.prefs.clearUserPref(this.prefs_root+'.auth_token');
195 if(this.perms) 196 if(this.perms)
196 this.prefs.setCharPref(this.prefs_root+'.auth_perms',this.perms); 197 this.prefs.setCharPref(this.prefs_root+'.auth_perms',this.perms);
197 else 198 else
198 this.prefs.clearUserPref(this.prefs_root+'.auth_perms'); 199 this.prefs.clearUserPref(this.prefs_root+'.auth_perms');
199 if(this.user && this.user.nsid!=null && this.user.nsid!=undefined) 200 if(this.user && this.user.nsid!=null && this.user.nsid!=undefined)
200 this.prefs.setCharPref(this.prefs_root+'.auth_user.nsid',this.user.nsid); 201 this.prefs.setCharPref(this.prefs_root+'.auth_user.nsid',this.user.nsid);
201 else 202 else
202 this.prefs.clearUserPref(this.prefs_root+'.auth_user.nsid'); 203 this.prefs.clearUserPref(this.prefs_root+'.auth_user.nsid');
203 if(this.user && this.user.username!=null && this.user.username!=undefined) 204 if(this.user && this.user.username!=null && this.user.username!=undefined)
204 this.prefs.setCharPref(this.prefs_root+'.auth_user.username',this.user.username); 205 this.prefs.setCharPref(this.prefs_root+'.auth_user.username',this.user.username);
205 else 206 else
206 this.prefs.clearUserPref(this.prefs_root+'.auth_user.username'); 207 this.prefs.clearUserPref(this.prefs_root+'.auth_user.username');
207 if(this.user && this.user.fullname!=null && this.user.fullname!=undefined) 208 if(this.user && this.user.fullname!=null && this.user.fullname!=undefined)
208 this.prefs.setCharPref(this.prefs_root+'.auth_user.fullname',this.user.fullname); 209 this.prefs.setCharPref(this.prefs_root+'.auth_user.fullname',this.user.fullname);
209 else 210 else
210 this.prefs.clearUserPref(this.prefs_root+'.auth_user.fullname'); 211 this.prefs.clearUserPref(this.prefs_root+'.auth_user.fullname');
211 }, 212 },
212 _reset_token: function() { 213 _reset_token: function() {
213 this.token = null; this.perms = null; this.user = null; 214 this.token = null; this.perms = null; this.user = null;
214 return false; 215 return false;
215 }, 216 },
216 load_token: function() { 217 load_token: function() {
217 try { 218 try {
218 if(this.prefs.getPrefType(this.prefs_root+'.auth_token')!=this.prefs.PREF_STRING) 219 if(this.prefs.getPrefType(this.prefs_root+'.auth_token')!=this.prefs.PREF_STRING)
219 return this._reset_token(); 220 return this._reset_token();
220 this.token = this.prefs.getCharPref(this.prefs_root+'.auth_token'); 221 this.token = this.prefs.getCharPref(this.prefs_root+'.auth_token');
221 if(this.prefs.getPrefType(this.prefs_root+'.auth_perms')!=this.prefs.PREF_STRING) 222 if(this.prefs.getPrefType(this.prefs_root+'.auth_perms')!=this.prefs.PREF_STRING)
222 return this._reset_token(); 223 return this._reset_token();
223 this.perms = this.prefs.getCharPref(this.prefs_root+'.auth_perms'); 224 this.perms = this.prefs.getCharPref(this.prefs_root+'.auth_perms');
224 if(this.prefs.getPrefType(this.prefs_root+'.auth_user.nsid')!=this.prefs.PREF_STRING) 225 if(this.prefs.getPrefType(this.prefs_root+'.auth_user.nsid')!=this.prefs.PREF_STRING)
225 return this._reset_token(); 226 return this._reset_token();
226 this.user = new Object(); 227 this.user = new Object();
227 this.user.nsid = this.prefs.getCharPref(this.prefs_root+'.auth_user.nsid'); 228 this.user.nsid = this.prefs.getCharPref(this.prefs_root+'.auth_user.nsid');
228 if(this.prefs.getPrefType(this.prefs_root+'.auth_user.username')!=this.prefs.PREF_STRING) 229 if(this.prefs.getPrefType(this.prefs_root+'.auth_user.username')!=this.prefs.PREF_STRING)
229 return this._reset_token(); 230 return this._reset_token();
230 this.user.username = this.prefs.getCharPref(this.prefs_root+'.auth_user.username'); 231 this.user.username = this.prefs.getCharPref(this.prefs_root+'.auth_user.username');
231 if(this.prefs.getPrefType(this.prefs_root+'.auth_user.fullname')!=this.prefs.PREF_STRING) 232 if(this.prefs.getPrefType(this.prefs_root+'.auth_user.fullname')!=this.prefs.PREF_STRING)
232 return this._reset_token(); 233 return this._reset_token();
233 this.user.fullname = this.prefs.getCharPref(this.prefs_root+'.auth_user.fullname'); 234 this.user.fullname = this.prefs.getCharPref(this.prefs_root+'.auth_user.fullname');
234 }catch(e) { return this._reset_token(); } 235 }catch(e) { return this._reset_token(); }
235 return true; 236 return true;
236 }, 237 },
237 reset_token: function() { 238 reset_token: function() {
238 this._reset_token(); 239 this._reset_token();
239 this.save_token(); 240 this.save_token();
240 }, 241 },
241 242
242 get_photo_url: function(ser,id,sec,sfx,ext) { 243 get_photo_url: function(ser,id,sec,sfx,ext) {
243 var rv = this.photo_url + ser + '/' + id + '_' + sec; 244 var rv = this.photo_url + ser + '/' + id + '_' + sec;
244 if(sfx && sfx!='_') rv += '_'+sfx; 245 if(sfx && sfx!='_') rv += '_'+sfx;
245 rv += ext?'.'+ext:'.jpg'; 246 rv += ext?'.'+ext:'.jpg';
246 return rv; 247 return rv;
247 }, 248 },
248 get_image_url: function(o,sfx) { 249 get_image_url: function(o,sfx) {
249 return this.get_photo_url( 250 return this.get_photo_url(
250 o.server, 251 o.server,
251 (o instanceof Photoset)? o.primary : o.id, 252 (o instanceof Photoset)? o.primary : o.id,
252 o.secret, 253 o.secret,
253 sfx, 254 sfx,
254 (sfx=='o')?o.originalformat:null 255 (sfx=='o')?o.originalformat:null
255 ); 256 );
256 }, 257 },
257 get_photo_page_url: function(p) { 258 get_photo_page_url: function(p) {
258 if(p instanceof Photo) { 259 if(p instanceof Photo) {
259 // TODO: track photoset and user owner id from there? 260 // TODO: track photoset and user owner id from there?
260 // The approach below is sheerly wrong. 261 // The approach below is sheerly wrong.
261 var o = this.user.nsid; 262 var o = this.user.nsid;
262 if(p.owner && p.owner.nsid) o = p.owner.nsid; 263 if(p.owner && p.owner.nsid) o = p.owner.nsid;
263 var rv = this.photos_url + o +'/' + p.id; 264 var rv = this.photos_url + o +'/' + p.id;
264 return rv; 265 return rv;
265 }else // TODO: take owner into account? 266 }else // TODO: take owner into account?
266 return this.photos_url + this.user.nsid + '/' + p; 267 return this.photos_url + this.user.nsid + '/' + p;
267 }, 268 },
268 make_photo_url: function(p,sfx) { 269 make_photo_url: function(p,sfx) {
269 if(sfx=='p') 270 if(sfx=='p')
270 return this.get_photo_page_url(p); 271 return this.get_photo_page_url(p);
271 else 272 else
272 return this.get_image_url(p,sfx); 273 return this.get_image_url(p,sfx);
273 }, 274 },
274 make_photoset_url: function(ps) { 275 make_photoset_url: function(ps) {
275 // TODO: allow for using someone else's photoset? 276 // TODO: allow for using someone else's photoset?
276 return this.photos_url+this.user.nsid+'/sets/'+ps.id; 277 return this.photos_url+this.user.nsid+'/sets/'+ps.id;
277 }, 278 },
279 make_uploader_edit_url: function(pid) {
280 // TODO: handle arrays
281 return this.uploader_edit_url+'?ids='+pid;
282 },
278 283
279 upload_file: function(f,fa,on_success,on_failure) { 284 upload_file: function(f,fa,on_success,on_failure) {
280 try { 285 try {
281 var fi = Components.classes["@mozilla.org/file/local;1"] 286 var fi = Components.classes["@mozilla.org/file/local;1"]
282 .createInstance(Components.interfaces.nsILocalFile); 287 .createInstance(Components.interfaces.nsILocalFile);
283 fi.initWithPath( f ); 288 fi.initWithPath( f );
284 var st = Components.classes["@mozilla.org/network/file-input-stream;1"] 289 var st = Components.classes["@mozilla.org/network/file-input-stream;1"]
285 .createInstance(Components.interfaces.nsIFileInputStream); 290 .createInstance(Components.interfaces.nsIFileInputStream);
286 st.init(fi,0x01,00004,null); 291 st.init(fi,0x01,00004,null);
287 var bis = Components.classes["@mozilla.org/binaryinputstream;1"] 292 var bis = Components.classes["@mozilla.org/binaryinputstream;1"]
288 .createInstance(Components.interfaces.nsIBinaryInputStream); 293 .createInstance(Components.interfaces.nsIBinaryInputStream);
289 bis.setInputStream(st); 294 bis.setInputStream(st);
290 295
291 // allocate and initialize temp storage string 296 // allocate and initialize temp storage string
292 var pbs = Components.classes["@mozilla.org/storagestream;1"] 297 var pbs = Components.classes["@mozilla.org/storagestream;1"]
293 .createInstance(Components.interfaces.nsIStorageStream); 298 .createInstance(Components.interfaces.nsIStorageStream);
294 pbs.init(1024,10000000,null); 299 pbs.init(1024,10000000,null);
295 // create output stream 300 // create output stream
296 var pbos = pbs.getOutputStream(0); 301 var pbos = pbs.getOutputStream(0);
297 // and a binaryoutputstream interface 302 // and a binaryoutputstream interface
298 var pbbos = Components.classes["@mozilla.org/binaryoutputstream;1"] 303 var pbbos = Components.classes["@mozilla.org/binaryoutputstream;1"]
299 .createInstance(Components.interfaces.nsIBinaryOutputStream); 304 .createInstance(Components.interfaces.nsIBinaryOutputStream);
300 pbbos.setOutputStream(pbos); 305 pbbos.setOutputStream(pbos);
301 306
302 /* create POST body */ 307 /* create POST body */
303 var boundarytoken = 'kadaroloongazaduviaxamma'; 308 var boundarytoken = 'kadaroloongazaduviaxamma';
304 var boundary = '--'+boundarytoken; 309 var boundary = '--'+boundarytoken;
305 var b = ''; 310 var b = '';
306 311
307 var parms = { api_key: this.api_key, auth_token: this.token }; 312 var parms = { api_key: this.api_key, auth_token: this.token };
308 for(var p in fa) parms[p] = fa[p]; 313 for(var p in fa) parms[p] = fa[p];
309 var pns = new Array(); 314 var pns = new Array();
310 for(var p in parms) pns.push(p); 315 for(var p in parms) pns.push(p);
311 var pstr = ''; 316 var pstr = '';
312 for(var p in pns.sort()) { 317 for(var p in pns.sort()) {
313 var pn = pns[p]; 318 var pn = pns[p];
314 pstr += pn+parms[pn]; 319 pstr += pn+parms[pn];
315 b += boundary+'\nContent-Disposition: form-data; name="'+pn+'"\n\n'+toutf8(parms[pn])+'\n'; 320 b += boundary+'\nContent-Disposition: form-data; name="'+pn+'"\n\n'+toutf8(parms[pn])+'\n';
316 } 321 }
317 b += boundary+'\nContent-Disposition: form-data; name="api_sig"\n\n'+this.api_sig(pstr)+'\n'; 322 b += boundary+'\nContent-Disposition: form-data; name="api_sig"\n\n'+this.api_sig(pstr)+'\n';
318 b += boundary+'\nContent-Disposition: form-data; name="photo"; filename="'+f+'"\nContent-Type: image/jpeg\nContent-Transfer-Encoding: binary\n\n'; 323 b += boundary+'\nContent-Disposition: form-data; name="photo"; filename="'+f+'"\nContent-Type: image/jpeg\nContent-Transfer-Encoding: binary\n\n';
319 pbbos.writeBytes(b,b.length); 324 pbbos.writeBytes(b,b.length);
320 var bisbytes = bis.available(); 325 var bisbytes = bis.available();
321 pbbos.writeBytes(bis.readBytes(bisbytes),bisbytes); 326 pbbos.writeBytes(bis.readBytes(bisbytes),bisbytes);
322 pbbos.writeBytes('\n'+boundary+'--',3+boundary.length); bis.close(); st.close(); 327 pbbos.writeBytes('\n'+boundary+'--',3+boundary.length); bis.close(); st.close();
323 328
324 pbbos.close(); pbos.close(); 329 pbbos.close(); pbos.close();
325 330
326 var x = new XMLHttpRequest(); 331 var x = new XMLHttpRequest();
327 x.open("POST",this.upload_url); 332 x.open("POST",this.upload_url);
328 x.setRequestHeader('Content-Type', 'multipart/form-data; boundary="'+boundarytoken+'"'); 333 x.setRequestHeader('Content-Type', 'multipart/form-data; boundary="'+boundarytoken+'"');
329 x.setRequestHeader('Connection','close'); 334 x.setRequestHeader('Connection','close');
330 x.setRequestHeader('Content-Length',b.length); 335 x.setRequestHeader('Content-Length',b.length);
331 x.onreadystatechange=function() { 336 x.onreadystatechange=function() {
332 if(x.readyState!=4) return false; 337 if(x.readyState!=4) return false;
333 if(x.status==200) { 338 if(x.status==200) {
334 var stat = x.responseXML.firstChild.getAttribute('stat'); 339 var stat = x.responseXML.firstChild.getAttribute('stat');
335 if(stat=='ok') { 340 if(stat=='ok') {
336 var pid = xp_str('/rsp/photoid',x.responseXML); 341 var pid = xp_str('/rsp/photoid',x.responseXML);
337 if(on_success) on_success(x,pid); 342 if(on_success) on_success(x,pid);
338 }else{ 343 }else{
339 var e = x.responseXML.getElementsByTagName('err').item(0); 344 var e = x.responseXML.getElementsByTagName('err').item(0);
340 var ecode = e.getAttribute('code'); 345 var ecode = e.getAttribute('code');
341 var emsg = e.getAttribute('msg'); 346 var emsg = e.getAttribute('msg');
342 dump('upload failed: '+ecode+' '+emsg+'\n'); 347 dump('upload failed: '+ecode+' '+emsg+'\n');
343 if(on_failure) on_failure(x,stat,ecode,emsg); 348 if(on_failure) on_failure(x,stat,ecode,emsg);
344 } 349 }
345 }else{ 350 }else{
346 if(on_failure) on_failure(x); 351 if(on_failure) on_failure(x);
347 } 352 }
348 return true; 353 return true;
349 }; 354 };
350 x.send(pbs.newInputStream(0)); 355 x.send(pbs.newInputStream(0));
351 }catch(e) { 356 }catch(e) {
352 if(on_failure) on_failure(e,null,-1,e.message); 357 if(on_failure) on_failure(e,null,-1,e.message);
353 } 358 }
354 } 359 }
355 360
356}; 361};