@widgetic/editor 3.10.33 → 3.10.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@widgetic/editor",
3
- "version": "3.10.33",
3
+ "version": "3.10.38",
4
4
  "scripts": {
5
5
  "start": "webpack --config webpack.config.js --watch --progress",
6
6
  "build": "webpack --config webpack.config.js",
@@ -65,7 +65,8 @@
65
65
  },
66
66
  "dependencies": {
67
67
  "http-server": "^0.11.1",
68
- "json-logic-js": "^1.2.2"
68
+ "json-logic-js": "^1.2.2",
69
+ "soundcloud": "^3.3.2"
69
70
  },
70
71
  "volta": {
71
72
  "node": "12.22.2"
@@ -48,10 +48,14 @@ class Browser extends Controller
48
48
 
49
49
  constructor: ->
50
50
  super
51
-
51
+ # console.log("Default Browser CTR:", @Service, @title, @options)
52
52
  @service = new @Service @title, @options
53
53
  @serviceTitle or= @service.title
54
- @delay => @tab.count @content.length
54
+
55
+ # show how many content items the user has selected on this source
56
+ @currentContent = []
57
+ # @delay => @tab.count @content.length
58
+
55
59
 
56
60
  @addNavBar()
57
61
  @intent = $ Intent @service.options
@@ -86,10 +90,21 @@ class Browser extends Controller
86
90
  Auth request and event handler
87
91
  ###
88
92
  auth: (e) ->
93
+ # console.log("Default browser auth:", e)
89
94
  return if String(@el.attr 'authenticated') is 'true'
90
95
  @service.auth e?.type is 'click'
91
96
 
92
97
  onAuth: (@authenticated) =>
98
+ # console.log("Default browser onAuth:", @authenticated)
99
+ # reset lists of content
100
+ @currentContent = []
101
+
102
+ # show currentSource count
103
+ if @authenticated then @updateCurrentCount()
104
+ # clear current content count
105
+ else
106
+ @tab.count 0
107
+
93
108
  @el.attr {@authenticated}
94
109
  @setFolder @service.root if @authenticated
95
110
  @$trigger "editor:browser:auth", service: @Service.name, authenticated: (@authenticated is true)
@@ -120,30 +135,78 @@ class Browser extends Controller
120
135
  @refreshing = true
121
136
  @setFolder(@currentFolder) if @currentFolder
122
137
 
138
+ # update the current authenticated user's selected items count
139
+ updateCurrentCount: =>
140
+ # console.log("Update count:", @content, @currentContent)
141
+ @tab.count @content.filter((a) => @currentContent.some((b) => a.id == b.id)).length
142
+
123
143
  onFolderRefresh: (children, opts = {}) =>
124
- if opts.hard
125
- @empty().$addClass 'loading'
144
+ # console.log("onFolderRefresh:", children, opts.root)
145
+
146
+ # on first root folder refresh: get entire list of content update selected items count
147
+ if opts.root
148
+ # console.log("onFolderRefresh update count:", children, opts.root, @service)
149
+
150
+ # reset lists of content
151
+ rootChildren = []
152
+ subfoldersChildren = []
153
+
154
+ # create the list of "root subfolders files" and the list of "root files"
155
+ children.map((child) =>
156
+ if child.type == "folder" then subfoldersChildren = subfoldersChildren.concat(child.children.map((subChild) => @service.newEntry('audio', subChild, child.id)))
157
+ else rootChildren.push(child)
158
+ )
159
+ # console.log("on Root refresh:", rootChildren, subfoldersChildren)
160
+
161
+ # if loading subfolders children for the first time
162
+ if subfoldersChildren.length && !@currentContent.length
163
+ # console.log("LOAD SUBFOLDERS FILES!")
164
+ @currentContent = @currentContent.concat(subfoldersChildren)
165
+
166
+ # if loading files children: filter those that are already in currentContent(that are subfoldersFiles)
167
+ if rootChildren.length
168
+ # console.log("LOAD ROOT FILES:", rootChildren)
169
+ children = rootChildren = rootChildren.filter((child) => !@currentContent.some((subChild) => subChild.id == child.id));
170
+ @currentContent = @currentContent.concat(rootChildren)
171
+
172
+ # console.log("on Root refresh:", @content, @currentContent);
173
+
174
+ # show currentSource count
175
+ @updateCurrentCount()
176
+
177
+ # clear empty children in current folder
178
+ if opts.hard then @empty().$addClass 'loading'
179
+
180
+ # turn refreshing off
126
181
  @refreshing = false
127
182
 
183
+ # hide loader
128
184
  @$removeClass('loading')
185
+
186
+ # save the new children in current folder's array
129
187
  @currentFolder.children = @currentFolder.children.concat children
130
188
  # children = @children()
131
189
 
190
+ # show no item icon if no children
132
191
  @el.toggleClass 'no-items', !children.length and !@children().length
133
- # append the child when it isnt hidden
192
+
193
+ # append the new children when they are not hidden to the browser canvas
134
194
  for item in children when not /^\.[^\.]/.test item.name
195
+ # prepare options
135
196
  opts=
136
197
  item : item
137
198
  getPreview : (item) => @service.preview item
138
199
  getURL : (item, _c) => @service.getURL item, _c
139
200
  count : @getContentItemsInFolder(item) if isFolder = item.type is 'folder'
140
201
  selected : !!@content.filter((i)-> i.path is item.path).length unless isFolder
141
-
202
+ # create controller
142
203
  controller = new Controllers[item.type] opts
143
204
  @append controller
144
205
  @listenTo controller, 'select', @setFolder if item.type is 'folder'
145
206
 
146
207
  # children.forEach (child) -> child.release()
208
+
209
+ # update scroll and start lazy load
147
210
  @scroll().update()
148
211
  @lazyLoad()
149
212
 
@@ -189,17 +252,21 @@ class Browser extends Controller
189
252
  addEntry: (item) ->
190
253
  itm = it for it in @content when it.path is item.path
191
254
  return if @content.indexOf(itm) isnt -1
192
- @tab.count @content.push item
255
+ @content.push item
256
+ # show currentSource count
257
+ @updateCurrentCount()
193
258
 
194
259
  removeEntry: (item) ->
195
260
  itm = it for it in @content when it.path is item.path
196
261
  @content.splice @content.indexOf(itm), 1
197
- @tab.count @content.length
262
+ # show currentSource count
263
+ @updateCurrentCount()
198
264
 
199
265
  for child in @children() when child.item.type in ['folder', 'button'] or child.isActive?()
200
266
  child.update @getOptions child.item
201
267
 
202
268
  recount: ->
269
+ # console.log("Default Browser recount:", @children())
203
270
  child.update @getOptions child.item for child in @children()
204
271
 
205
272
  getOptions: (item) =>
@@ -26,13 +26,18 @@ export default class ContentServiceWithEvents extends EventsMixin(Service) {
26
26
  }
27
27
 
28
28
  toggleItem(composition, service, id, value, extra = {}, metadata = {}) {
29
+
29
30
  const item = this.getItemsByService(service)
30
31
  .filter(item => item.metadata.id === id)
31
32
  .pop();
33
+ // console.log("Content toggleItem:", id, item)
32
34
 
35
+ // remove item
33
36
  if (item) {
34
37
  item.destroy();
35
- } else {
38
+ }
39
+ // add item
40
+ else {
36
41
  this.addItem(
37
42
  composition,
38
43
  value,
@@ -30,7 +30,7 @@ export default class UploadService extends EventsMixin(Service) {
30
30
  constructor(user, token) {
31
31
  super();
32
32
  this.user = user.id;
33
- this.maxFilesize = user.premium ? 100 : 25;
33
+ this.maxFilesize = user.premium ? 250 : 100;
34
34
  this.token = token;
35
35
 
36
36
  this.files = [];
@@ -69,35 +69,44 @@ class Content extends Tabs
69
69
  @meta = @composition.contentMeta()
70
70
  @browserOptions = @meta.browser?.options
71
71
 
72
-
72
+ # add browser for the upload source
73
73
  @addBrowser UploadBrowser
74
74
 
75
+ # read other sources and filter the ones that don't work anymore
75
76
  sources = @meta.browser?.sources
76
- # console.log("content editor:", sources);
77
+ # console.log('Editor Content sources:', sources);
77
78
  if sources
79
+ delete sources.facebook
78
80
  delete sources.websearch
79
81
  delete sources.blogvio
80
82
  delete sources.dropbox
81
83
  delete sources.flickr
82
84
  delete sources["google-drive"]
83
85
 
86
+ # add a browser(legacy) for all alternative source
84
87
  @legacyAddBrowser source, key for key, source of sources
85
88
 
89
+ # add a browser(legacy) for the direct-input source
86
90
  if @meta.input
87
91
  @append @input = new DirectInput {control:@meta.input, @composition}
88
92
  @browsers['input'] = @input
89
93
  @listenTo @input, 'canAdd', @contentCanAdd
94
+
95
+ # console.log('Editor Content @browsers:', @browsers)
90
96
 
97
+ # add content listeners
91
98
  @listenTo ContentModel, 'destroy', @onItemDestroy
92
99
  @listenTo ContentModel, 'update', @_onItemUpdate
93
100
  @listenTo ContentModel, 'create', @_onItemCreate
94
101
  @listenTo ContentModel, 'change', => @el.toggleClass 'has-reached-max', @composition.maxContentReached()
95
102
 
103
+ # activate the first tab
96
104
  @children()[0].active()
97
105
 
98
106
  @trigger 'initialized'
99
107
 
100
108
  addBrowser: (Browser) =>
109
+ # console.log("addBrowser:", Browser)
101
110
  return unless Browser.isCompatible @browserOptions?.types
102
111
  browser = new Browser { filetypes: @browserOptions?.types }
103
112
 
@@ -140,6 +149,7 @@ class Content extends Tabs
140
149
  Service = window.require service.module or 'editor/content/service/default'
141
150
  content = @composition.getContent().filter((i)->i.metadata?.service is serviceName).map((i)->i.metadata)
142
151
  Browser = window.require service.browser or Service.browser
152
+ # console.log("legacyAddBrowser:", Browser, Service, content)
143
153
 
144
154
  @browsers[serviceName] = browser = new Browser
145
155
  content: content
@@ -186,7 +196,7 @@ class Content extends Tabs
186
196
  # TODO: use Content service
187
197
  ###
188
198
  contentAdd: (item) =>
189
- # console.log("Editor Content Tab onContentAdded:", item);
199
+ # console.log('Editor Content Tab onContentAdded:', item);
190
200
  props= {}
191
201
  props[attr] = item[attr] for attr, opts of @meta.attributes when item[attr]?
192
202
  props.metadata = item
@@ -203,10 +213,13 @@ class Content extends Tabs
203
213
  TODO: use Content service
204
214
  ###
205
215
  contentRemove: (item) =>
216
+
206
217
  @stopListening ContentModel, 'destroy', @onItemDestroy
207
218
  removedContent = ContentModel.all().filter((i) =>
208
- i.metadata is item and i.composition_id is @composition.id
219
+ # console.log("contentRemove filter:", i)
220
+ i.metadata?.id is item.id and i.composition_id is @composition.id
209
221
  )
222
+ # console.log('Editor Content contentRemove:', item, ContentModel.all(), removedContent)
210
223
  removedContent[0]?.destroy()
211
224
  @listenTo ContentModel, 'destroy', @onItemDestroy
212
225
 
@@ -38,6 +38,7 @@ class InstagramService extends Service
38
38
 
39
39
  _auth: (interactive=true) ->
40
40
  # console.log("Editor ISTG service _auth method:", interactive, api);
41
+ # if authenticated get user info to show it in the browser
41
42
  if api.token?
42
43
  @getUser(api.token)
43
44
  .then (result) =>
@@ -48,6 +49,7 @@ class InstagramService extends Service
48
49
  # console.log("Editor getUser error:", error)
49
50
  @deauth()
50
51
  # console.log("Editor INSTG service _auth method:", interactive, api);
52
+ # if not authenticated open popup
51
53
  !@authenticated and interactive and @showAuthPopup()
52
54
 
53
55
  showAuthPopup: ->
@@ -45,6 +45,7 @@ class InstagramService extends Service
45
45
 
46
46
  _auth: (interactive=true) ->
47
47
  # console.log("Editor INSTG service _auth method:", interactive, api);
48
+ # if authenticated get user info to show it in the browser
48
49
  if api.token?
49
50
  @getUser(api.token)
50
51
  .then (result) =>
@@ -57,6 +58,7 @@ class InstagramService extends Service
57
58
  @deauth()
58
59
 
59
60
  # console.log("Editor INSTG service _auth method:", interactive, api);
61
+ # if not authenticated open popup
60
62
  !@authenticated and interactive and @showAuthPopup()
61
63
 
62
64
  showAuthPopup: ->
@@ -1,49 +1,163 @@
1
1
  Service = require '../../../browser/model'
2
2
  Entry = require '../../../browser/model/entry'
3
- SC = require '../../../core/services/soundcloud'
3
+
4
+ # SoundCloud config
5
+ widgetic_backend_url = 'https://widgetic.com/wservices/soundcloud/'
6
+ SC = require('soundcloud')
7
+ config = {
8
+ api_url: 'https://api.soundcloud.com'
9
+ # for '/connect' endpoint
10
+ client_id : 'aed0aa63baf747a83ad0b6b246acddca'
11
+ # client_secret: '3173e3098379153d42084aba06fe3ec4',
12
+ redirect_uri: widgetic_backend_url + 'connect',
13
+ tracks_url: widgetic_backend_url + 'tracks',
14
+ # response_type: 'code',
15
+
16
+ # for '/oauth2/token' endpoint
17
+ grant_type: 'refresh_token',
18
+ }
19
+ SC.initialize(config);
20
+
21
+ # add local config options used in this file only
22
+ SC.client_id = config.client_id
23
+ SC.api_url = config.api_url
24
+ SC.tracks_url = config.tracks_url
25
+ try SC.auth_token = localStorage.getItem 'soundcloudAuthToken'
26
+ try SC.userId = localStorage.getItem 'soundcloudUserId'
4
27
 
5
28
  class SoundCloudService extends Service
6
29
  constructor: ->
7
30
  super
8
- @authenticated = false
31
+ # console.log('Soundcloud Service CTR:', @title, @options)
32
+
33
+ SCGet: (path) ->
34
+ url = "#{SC.api_url}" + path
35
+ # console.log("SCGet path:", path, SC.auth_token)
36
+ $.ajax(url: url, type: 'GET', dataType: 'json', headers: {'Authorization': 'OAuth ' + SC.auth_token})
37
+
38
+ auth: (interactive) =>
39
+ # console.log("SoundCloud on auth:", SC.auth_token, SC.userId);
40
+
41
+ # show popup to authenticate
42
+ if !SC.userId and interactive then @showAuthPopup()
9
43
 
10
- auth: (interactive) => SC.ready().then =>
11
- SC.connect @checkAuth if interactive
12
- @checkAuth()
44
+ # trigger auth event to show folders or connect button in browser
45
+ else @checkAuth()
46
+
47
+ showAuthPopup: ->
48
+ # console.log("SC showAuthPopup:", SC)
49
+ SC.connect()
50
+ .then((response) =>
51
+ # console.log("SC did connect:", response);
52
+ # get auth_token
53
+ SC.auth_token = response.oauth_token
54
+ try localStorage.setItem 'soundcloudAuthToken', SC.auth_token
55
+ # console.log("SC did connect:", SC);
56
+
57
+ # get user info
58
+ @SCGet("/me")
59
+ .then((response) =>
60
+ # console.log("SC getUser result:", response)
61
+ SC.userId = response.id
62
+ try localStorage.setItem 'soundcloudUserId', SC.userId
63
+ @checkAuth();
64
+ ).catch (error) =>
65
+ console.log("Editor getUser error:", error)
66
+ @deauth()
67
+ ).catch (error) =>
68
+ console.log 'SC Connect Error: ' + error.message
69
+ @deauth()
13
70
 
14
71
  checkAuth: =>
15
- @trigger 'auth', @authenticated = SC.isConnected()
72
+ # console.log 'checkAuth:', SC.userId
73
+ @trigger 'auth', SC.userId != null
74
+
75
+ deauth: ->
76
+ # remove auth_token
77
+ SC.auth_token = null
78
+ try localStorage.removeItem 'soundcloudAuthToken'
16
79
 
80
+ # remove user
81
+ SC.userId = null
82
+ try localStorage.removeItem 'soundcloudUserId'
83
+
84
+ # trigger auth event
85
+ @checkAuth();
86
+
87
+ # SoundCloud Files explorer methods
17
88
  refresh: (@currentFolder) ->
18
- @fetchPlaylists() if @currentFolder.root
19
- @fetchTracks @currentFolder.id
89
+ # console.log("Soundcloud service refresh:", @currentFolder)
90
+ # if root folder: load subfolders(playlists) and then files
91
+ if @currentFolder.root then @fetchPlaylists()
92
+
93
+ # if subfolder: load files(tracks) inside
94
+ else @fetchTracks @currentFolder.id
20
95
 
21
96
  fetchPlaylists: =>
22
- SC.get '/me/playlists', (playlists) =>
23
- @trigger 'refresh', playlists.map @newEntry.bind @, 'folder'
97
+ # console.log("fetchPlaylists!");
98
+ @SCGet("/users/#{SC.userId}/playlists")
99
+ .then((playlists) =>
100
+ # console.log("fetchPlaylists result:", playlists);
101
+
102
+ # trigger refresh event to show in browser the playlists folders
103
+ @trigger 'refresh', (playlists.map @newEntry.bind @, 'folder'), {root: true}
104
+
105
+ # load tracks of root folder
106
+ @fetchTracks @currentFolder.id
107
+ ).catch (error) =>
108
+ console.log 'Fetch Playlist error: ' + error.message
24
109
 
25
- fetchTracks: (id) =>
26
- path = if id then "/playlists/#{id}" else '/me'
110
+ fetchTracks: (playlistId) =>
111
+ # console.log("fetchTracks for playlist:", playlistId)
112
+ # check if a playlist or entire list of tracks of the current user
113
+ path = if playlistId then "/playlists/#{playlistId}" else "/users/#{SC.userId}/tracks"
114
+ path += "?access=playable"
115
+
27
116
 
28
- SC.get path+'/tracks', (tracks) =>
29
- @trigger 'refresh', tracks.map @newEntry.bind @, 'audio'
117
+ @SCGet(path)
118
+ .then((result) =>
119
+ # console.log("fetchTracks result:", result)
30
120
 
31
- newEntry: (type, item) =>
32
- path = @currentFolder.path
33
- path += '/' unless @currentFolder.root
121
+ # if root then read directly the tracks
122
+ tracks = result
123
+
124
+ # if a playlist then get the tracks inside
125
+ if result.tracks then tracks = result.tracks
126
+
127
+ # trigger event to refresh in browser
128
+ @trigger 'refresh', (tracks.map((track) => @newEntry('audio', track))), {root: (if playlistId then false else true)}
129
+ ).catch (error) =>
130
+ console.log 'Fetch Tracks error: ' + error.message
131
+
132
+ newEntry: (type, item, parentId) =>
133
+ # console.log("newEntry:", type, item, parentId)
134
+ if !parentId
135
+ path = @currentFolder.path
136
+ path += '/' unless @currentFolder.root
137
+ else path = parentId + '/'
34
138
  path += item.id
139
+ # console.log("newEntry:", path, item.id, type)
140
+ if type == "folder" then children = item.tracks
35
141
  {artwork_url, id, duration, title, stream_url} = item
36
142
  new Entry $.extend {}, {
37
143
  service: @
38
- type, path, artwork_url, id, duration, title, stream_url
144
+ type, path, artwork_url, id, children, duration: duration/1000, title, stream_url
39
145
  name: item.title
40
146
  }
41
147
 
42
148
  getURL: (entry, callback) ->
43
- callback "#{entry.stream_url}?client_id=#{SC.clientId()}"
149
+ # old method
150
+ # callback "#{entry.stream_url}?client_id=#{SC.client_id}"
44
151
 
45
- deauth: ->
46
- SC.disconnect()
47
- @trigger 'auth', @authenticated = SC.isConnected()
152
+ # new 2021 api track path through widgetic endpoint
153
+ callback "#{SC.tracks_url}?id=#{entry.id}&atoken=#{SC.auth_token}"
154
+
155
+ # new 2021 api get method
156
+ # @SCGet("/tracks/#{entry.id}/streams")
157
+ # .done((streams) =>
158
+ # console.log("fetchTrackStreams result:", streams);
159
+ # # callback streams.http_mp3_128_url
160
+ # ).fail (error) =>
161
+ # console.log 'Fetch Track Streams error: ' + error
48
162
 
49
163
  module.exports = SoundCloudService
@@ -1,34 +0,0 @@
1
- client_id = 'aed0aa63baf747a83ad0b6b246acddca'
2
- redirect_uri = "#{window.location.origin}/connect/soundcloud"
3
- response_type = 'code'
4
-
5
- lsAuthKey = 'wdtc-sc-at'
6
- loadSDK = -> $.getScript "//connect.soundcloud.com/sdk/sdk-3.2.2.js"
7
-
8
- initPromise = null
9
- initSDK = ->
10
- console.log("SC initSDK");
11
- initPromise or= loadSDK().then( ->
12
- console.log("SC loadSDK callback:", SC);
13
- SC.initialize {client_id, redirect_uri, response_type}
14
- ).then ->
15
- callSC = (method, args...) -> SC[method] args...
16
- for own key, _ of SC when !sdk[key] and typeof SC[key] is 'function'
17
- sdk[key] = callSC.bind SC, key
18
- console.log("SC initialize callback:", localStorage.getItem lsAuthKey)
19
-
20
- # SC.accessToken key if (key = localStorage.getItem lsAuthKey)?
21
-
22
- module.exports = sdk =
23
- ready: initSDK
24
-
25
- connect: (callback) ->
26
- SC.connect ->
27
- # localStorage.setItem lsAuthKey, SC.accessToken()
28
- callback()
29
-
30
- disconnect: ->
31
- SC.disconnect()
32
- localStorage.removeItem lsAuthKey
33
-
34
- clientId: -> client_id