From f831c84e3e86ff28ba224d4a8084c4f7a41bfa7b Mon Sep 17 00:00:00 2001 From: EragonJ Date: Mon, 27 Oct 2014 00:01:09 +0800 Subject: [PATCH] Drop websql and store plain file in dataPath 1. Drop websql because it's hard to debug and maintain 2. Use nedb as our db backend (nosql friendly API). Because nedb will create plain file as db in dataPath, we can debug Atraci more easily 3. fix a bug that when creating playlist, if you type enter (on mac), then Atraci would jump to white screen without any reason and --- coffee/_history.coffee | 98 +++++++------ coffee/_playlist.coffee | 314 +++++++++++++++++++++++----------------- coffee/app.coffee | 27 ++-- js/node-main.js | 2 +- package.json | 15 +- 5 files changed, 266 insertions(+), 190 deletions(-) diff --git a/coffee/_history.coffee b/coffee/_history.coffee index e39efd6..d3ee874 100644 --- a/coffee/_history.coffee +++ b/coffee/_history.coffee @@ -1,55 +1,65 @@ -# Init preparation (should be improved later) -db.transaction (tx) -> - tx.executeSql( - 'CREATE TABLE IF NOT EXISTS history ' + - '(artist, title, cover_url_medium, cover_url_large, last_played)' - ) - class History @clear: (success) -> - db.transaction (tx) -> - tx.executeSql 'DROP TABLE history' - success?() + db.history.remove({}, { multi: true }, (error) -> + if error + console.log("History.clear remove erorr :") + console.log(error) + success?() + else + success?() + ) @addTrack: (artist, title, cover_url_medium, cover_url_large) -> unix_timestamp = Math.round((new Date()).getTime() / 1000) - db.transaction (tx) -> - tx.executeSql( - 'CREATE TABLE IF NOT EXISTS history ' + - '(artist, title, cover_url_medium, cover_url_large, last_played)' - ) - - tx.executeSql( - 'DELETE FROM history WHERE artist = ? and title = ?', [artist, title] - ) - - tx.executeSql( - 'INSERT INTO history ' + - '(artist, title, cover_url_medium, cover_url_large, last_played) ' + - 'VALUES (?, ?, ?, ?, ?)', - [artist, title, cover_url_medium, cover_url_large, unix_timestamp] - ) + db.history.remove({ + artist: artist, + title: title + }, {}, (error, numRemoved) -> + if error + console.log("History.addTrack remove erorr :") + console.log(error) + else + db.history.insert({ + artist: artist, + title: title, + cover_url_medium: cover_url_medium, + cover_url_large: cover_url_large, + last_played: unix_timestamp + }, (error) -> + if error + console.log("History.addTrack insert erorr :") + console.log(error) + ) + ) @removeTrack: (artist, title) -> - db.transaction (tx) -> - tx.executeSql( - 'DELETE FROM history WHERE artist = ? and title = ?', [artist, title] - ) + db.history.remove({ + artist: artist, + title: title + }, {}, (error) -> + if error + console.log("History.removeTrack remove erorr :") + console.log(error) + ) @getTracks: (success) -> - tracks = [] - db.transaction (tx) -> - tx.executeSql( - 'SELECT * FROM history ORDER BY last_played DESC LIMIT 150', [], - (tx, results) -> - i = 0 - while i < results.rows.length - tracks.push results.rows.item(i) - i++ - success? tracks - ) + db.history.find({}).sort({ + last_played: -1 + }).limit(150).exec((error, foundTracks) -> + if error + console.log("History.getTracks find erorr :") + console.log(error) + success?([]) + else + success?(foundTracks) + ) @countTracks: (success) -> - db.transaction (tx) -> - tx.executeSql 'SELECT COUNT(*) AS cnt FROM history', [], (tx, results) -> - success? results.rows.item(0).cnt + db.history.count({}, (error, count) -> + if error + console.log("History.countTracks count erorr :") + console.log(error) + success?(0) + else + success?(count) + ) diff --git a/coffee/_playlist.coffee b/coffee/_playlist.coffee index e1382e5..2c18f95 100644 --- a/coffee/_playlist.coffee +++ b/coffee/_playlist.coffee @@ -9,8 +9,11 @@ class PlaylistPanel @playlistPopup = $('.new') @playlistName = $('#playListName') @positionTarget = $('body') - - + @playlistPanel.keydown((e) -> + if e.keyCode is $.ui.keyCode.ENTER + saveButton = $(@).parent().find('.ui-dialog-buttonpane button:last') + saveButton.click() + ) @playlistPanel.dialog autoOpen: false, height: 220, @@ -49,19 +52,22 @@ class PlaylistPanel if youtubePlaylistId playlistName = l10n.get('playlist') + '-' + youtubePlaylistId.substr(0, 5) - Playlists.create(playlistName, youtubePlaylistId) - Playlists.getAll((playlists) -> - sidebar.populatePlaylists(playlists) + Playlists.create(playlistName, youtubePlaylistId, -> + Playlists.getAll((playlists) -> + sidebar.populatePlaylists(playlists) + ) + userTracking.event('Playlist', 'Create', + youtubePlaylistId).send() ) - userTracking.event('Playlist', 'Create', - youtubePlaylistId).send() else playlistName = Utils.filterSymbols(str) - Playlists.create(playlistName) - Playlists.getAll((playlists) -> - sidebar.populatePlaylists(playlists) + Playlists.create(playlistName, '', -> + Playlists.getAll((playlists) -> + sidebar.populatePlaylists(playlists) + ) + userTracking.event( + "Playlist", "Create", playlistName).send() ) - userTracking.event("Playlist", "Create", playlistName).send() $('#playListName').val("") else alertify.alert("This playlist name already exists") @@ -95,96 +101,137 @@ class PlaylistPanel __playlists = [] class Playlists - - @initDB: -> - # Init preparation (should be improved later) - db.transaction (tx) -> - tx.executeSql( - 'CREATE TABLE IF NOT EXISTS playlists' + - '(name, platform_id, created, position)' - ) - tx.executeSql( - 'ALTER TABLE playlists ADD platform_id DEFAULT ""' - ) - - tx.executeSql( - 'ALTER TABLE playlists ADD position DEFAULT 1' - ) - @clear = (success) -> - db.transaction (tx) -> - tx.executeSql 'DROP TABLE playlist_tracks' - tx.executeSql 'DROP TABLE playlists' - success?() + db.playlist.remove({}, { multi: true }, (error) -> + if error + console.log("Playlists.clear remove playlist erorr :") + console.log(error) + success?() + else + db.track.remove({}, { multi: true }, (error) -> + if error + console.log("Playlists.clear remove track erorr :") + console.log(error) + success?() + else + success?() + ) + ) @addTrack: (artist, title, cover_url_medium, cover_url_large, playlist) -> unix_timestamp = Math.round((new Date()).getTime() / 1000) - db.transaction (tx) -> - tx.executeSql( - 'CREATE TABLE IF NOT EXISTS playlist_tracks ' + - '(artist, title, cover_url_medium, cover_url_large, playlist, added)' - ) - tx.executeSql( - 'DELETE FROM playlist_tracks WHERE ' + - 'artist = ? and title = ? and playlist = ?', - [artist, title, playlist] - ) - tx.executeSql( - 'INSERT INTO playlist_tracks ' + - '(artist, title, cover_url_medium, cover_url_large, playlist, added) '+ - 'VALUES (?, ?, ?, ?, ?, ?)', - [artist, title, cover_url_medium, cover_url_large, - playlist, unix_timestamp] - ) + + db.track.remove({ + artist: artist, + title: title, + playlist: playlist + }, {}, (error) -> + if error + console.log("Playlists.addTrack remove track erorr :") + console.log(error) + else + db.track.insert({ + artist: artist, + title: title, + cover_url_medium: cover_url_medium, + cover_url_large: cover_url_large, + playlist: playlist, + added: unix_timestamp + }, (error) -> + if error + console.log("Playlists.addTrack insert track erorr :") + console.log(error) + ) + ) @updatePlaylistPos: (playlistName, position) -> - db.transaction (tx) -> - tx.executeSql( - 'update playlists set ' + - 'position = ? WHERE name = ?', [position, playlistName] - ) + db.playlist.update({ + name: playlistName + }, { + $set: { + position: position + } + }, {}, (error) -> + if error + console.log("Playlists.updatePlaylistPos update playlist erorr :") + console.log(error) + ) @removeTrack: (artist, title, playlist) -> - db.transaction (tx) -> - tx.executeSql( - 'DELETE FROM playlist_tracks WHERE ' + - 'artist = ? and title = ? and playlist = ?', [artist, title, playlist] - ) + db.track.remove({ + artist: artist, + title: title, + playlist: playlist + }, {}, (error) -> + if error + console.log("Playlists.removeTrack remove track erorr :") + console.log(error) + ) - @create: (name, platform_id = '') -> + @create: (name, platform_id = '', success) -> unix_timestamp = Math.round((new Date()).getTime() / 1000) - db.transaction (tx) -> - tx.executeSql 'DELETE FROM playlists WHERE name = ?', [name] - tx.executeSql( - 'INSERT INTO playlists (name, platform_id, created, position)' + - 'VALUES (?, ?, ?, 0)', - [name, platform_id, unix_timestamp] - ) + db.playlist.remove({ + name: name + }, {}, (error) -> + if error + console.log("Playlists.create remove playlist erorr :") + console.log(error) + else + db.playlist.insert({ + name: name, + platform_id: platform_id, + created: unix_timestamp, + position: 0 + }, (error) -> + if error + console.log("Playlists.create create playlist erorr :") + console.log(error) + else + success?() + ) + ) @delete: (name) -> - db.transaction (tx) -> - tx.executeSql 'DELETE FROM playlists WHERE name = ?', [name] - tx.executeSql 'DELETE FROM playlist_tracks WHERE playlist = ?', [name] + db.playlist.remove({ + name: name + }, {}, (error) -> + if error + console.log("Playlists.delete remove playlist erorr :") + console.log(error) + else + db.track.remove({ + playlist: name + }, {}, (error) -> + if error + console.log("Playlists.delete remove track erorr :") + console.log(error) + ) + ) @export: (name) -> exportDump = [] #Insert Signature to identify playlist files - exportDump.push "Atraci:ImportedPlaylist:"+name - db.transaction (tx) -> - tx.executeSql( - 'SELECT * FROM playlist_tracks WHERE playlist = ?', - [name], (tx, results) -> - i = 0 - while i < results.rows.length - exportDump.push results.rows.item(i) - i++ - success? exportDump - fs.writeFile name + "Playlist.atpl", - JSON.stringify(exportDump), (error) -> - console.error("Error writing file", error) if error - alertify.log "Exported " + name + "Playlist.json" + - " to: " + process.cwd() - ) + exportDump.push('Atraci:ImportedPlaylist:' + name) + + db.track.find({ + playlist: name + }, (error, foundTracks) -> + if error + console.log("Playlists.export find track erorr :") + console.log(error) + else + i = 0 + + while i < foundTracks.length + exportDump.push(foundTracks[i]) + i++ + + fs.writeFile name + "Playlist.atpl", + JSON.stringify(exportDump), (error) -> + console.error("Error writing file", error) if error + alertify.log "Exported " + name + "Playlist.json" + + " to: " + process.cwd() + ) @import: (name) -> objects = [] @@ -223,55 +270,64 @@ class Playlists return @getAll = (success) -> - playlists = [] - db.transaction (tx) -> - tx.executeSql( - 'SELECT * FROM playlists ORDER BY position ASC', [], (tx, results) -> - i = 0 - while i < results.rows.length - playlists.push results.rows.item(i) - i++ - __playlists = playlists - success? playlists - ) + db.playlist.find({}).sort({ + position: 1 + }).exec((error, foundPlaylists) -> + if error + console.log("Playlists.getAll find playlist erorr :") + console.log(error) + success?([]) + else + __playlists = foundPlaylists + success?(foundPlaylists) + ) @getTracksForPlaylist = (playlist, success) -> - tracks = [] - db.transaction (tx) -> - tx.executeSql( - 'SELECT * FROM playlist_tracks WHERE playlist = ? ORDER BY added ASC', - [playlist], (tx, results) -> - i = 0 - while i < results.rows.length - tracks.push results.rows.item(i) - i++ - success? tracks - ) + db.track.find({ + playlist: playlist + }).sort({ + added: 1 + }).exec((error, foundTracks) -> + if error + console.log("Playlists.getTracksForPlaylist find track erorr :") + console.log(error) + success?([]) + else + success?(foundTracks) + ) - @getPlaylistNameExist: (name, callback) -> - db.transaction((tx) -> - tx.executeSql( - 'SELECT name FROM playlists WHERE name = ?', - [name], (tx, results) -> - callback(results.rows.length) - ) + @getPlaylistNameExist: (name, success) -> + db.playlist.find({ + name: name + }, (error, foundPlaylists) -> + if error + console.log("Playlists.getPlaylistNameExist find playlist erorr :") + console.log(error) + success?(0) + else + success?(foundPlaylists.length) ) @rename: (name, new_name) -> + db.playlist.update({ + name: playlistName + }, { + $set: { + name: new_name + } + }, {}, (error) -> + if error + console.log("Playlists.rename update playlist erorr :") + console.log(error) + else + Playlists.getTracksForPlaylist(name, ((tracks) -> + i = 0 + while i < tracks.length + Playlists.addTrack( + tracks[i].artist, tracks[i].title, tracks[i].cover_url_medium, + tracks[i].cover_url_large, new_name) + i++ + )) - db.transaction((tx) -> - tx.executeSql( - 'UPDATE playlists SET name = ? WHERE name = ?', [new_name, name] - ) + Playlists.delete(name) ) - - Playlists.getTracksForPlaylist(name, ((tracks) -> - i = 0 - while i < tracks.length - Playlists.addTrack( - tracks[i].artist, tracks[i].title, tracks[i].cover_url_medium, - tracks[i].cover_url_large, new_name) - i++ - )) - - Playlists.delete(name) diff --git a/coffee/app.coffee b/coffee/app.coffee index e378e53..3abe3ee 100644 --- a/coffee/app.coffee +++ b/coffee/app.coffee @@ -1,5 +1,6 @@ # Load native UI library gui = require('nw.gui') +path = require('path') # Get auto update libraries pkg = require('../package.json') @@ -21,9 +22,22 @@ win.focus() # Show the window when the app opens win.show() -# Open Web SQL Database -# https://github.com/rogerwang/node-webkit/wiki/Save-persistent-data-in-app -db = openDatabase('AtraciDB', '1.0', '', 10 * 1024 * 1024) +# DB +Datastore = require('nedb') + +db = {} +db.playlist = new Datastore( + filename: path.join(require('nw.gui').App.dataPath, 'playlist.db') + autoload: true +) +db.history = new Datastore( + filename: path.join(require('nw.gui').App.dataPath, 'history.db') + autoload: true +) +db.track = new Datastore( + filename: path.join(require('nw.gui').App.dataPath, 'track.db') + autoload: true +) # Cancel all new windows (Middle clicks / New Tab) win.on "new-win-policy", (frame, url, policy) -> @@ -73,11 +87,6 @@ $ -> window.sidebar = new Sidebar window.playlistPanel = new PlaylistPanel - #Initialize the playlists DB - setTimeout( -> - Playlists.initDB() - , 1000) - splash = gui.Window.open 'splash.html', { position: 'center', width: 600, @@ -183,4 +192,4 @@ $ -> "on " + getOperatingSystem() cb filename , newManifest - true \ No newline at end of file + true diff --git a/js/node-main.js b/js/node-main.js index ed0e2e4..f1af562 100644 --- a/js/node-main.js +++ b/js/node-main.js @@ -9,4 +9,4 @@ process.on('uncaughtException', function(error) { window.userTracking.event("Error", "uncaughtException", window.getOperatingSystem(), error).send() }, 500); }, 200); -}); \ No newline at end of file +}); diff --git a/package.json b/package.json index 1f1c479..341eeaa 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "request": "~2.40.0", "ytdl": "~0.3.3", "universal-analytics": "~0.3.4", - "node-uuid": "~1.4.1" + "node-uuid": "~1.4.1", + "nedb": "~0.11.1" }, "devDependencies": { "grunt": "~0.4.5", @@ -41,14 +42,14 @@ "grunt-regex-replace": "~0.2.6", "grunt-shell": "~1.0.1", "grunt-coffeelint": "0.0.13", - "node-webkit-updater" : "0.0.14", - "tarball-extract" : "0.0.3" + "node-webkit-updater": "0.0.14", + "tarball-extract": "0.0.3" }, "manifestUrl": "https://raw.githubusercontent.com/Atraci/Atraci/master/package.json", - "packages" : { + "packages": { "win": "https://github.com/Atraci/Atraci/releases/download/0.6.5/Atraci.exe", - "linux64" : "https://github.com/Atraci/Atraci/releases/download/0.6.5/Atraci-linux64.tar.gz", - "linux32" : "https://github.com/Atraci/Atraci/releases/download/0.6.5/Atraci-linux32.tar.gz", - "mac" : "https://github.com/Atraci/Atraci/releases/download/0.6.5/Atraci-mac.zip" + "linux64": "https://github.com/Atraci/Atraci/releases/download/0.6.5/Atraci-linux64.tar.gz", + "linux32": "https://github.com/Atraci/Atraci/releases/download/0.6.5/Atraci-linux32.tar.gz", + "mac": "https://github.com/Atraci/Atraci/releases/download/0.6.5/Atraci-mac.zip" } }