Commits

Aaron Toth committed 0119eeb

using headers for auth, and more large changes.

Comments (0)

Files changed (20)

     "id" : "me.aaront.pinnned",
     "version" : "0.7.0",
     "vendor" : "Aaron Toth",
+    "vendorurl" : "http://aaront.me",
     "type" : "web",
     "main" : "index.html",
     "title" : "Pinnned",
 enyo.depends(
     "source/Pinnned.js",
 
+    // Libraries
+    "library/base64.js",
+
     // Views
     "source/views/Main.js",
     "source/views/Preferences.js",
     // Dialogs
     "source/dialogs/AddAccount.js",
     "source/dialogs/Date.js",
+    "source/dialogs/Error.js",
     "source/dialogs/RegisterAccount.js",
     "source/dialogs/Tag.js",
 

framework_config.json

 {
-    "logLevel" : 99
+    "logLevel": 99,
+    "timingEnabled": true,
+    "logEvents": true,
+    "debuggingEnabled": true,
+    "escapeHTMLInTemplates": true
 }
Add a comment to this file

images/delicious.png

Old
Old image
New
New image
Add a comment to this file

images/pin.png

Old
Old image
New
New image
Add a comment to this file

images/pinboard.png

Old
Old image
New
New image
Added
New image

library/base64.js

+/**
+*
+*  Base64 encode / decode
+*  http://www.webtoolkit.info/
+*
+**/
+
+var Base64 = {
+
+	// private property
+	_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+
+	// public method for encoding
+	encode : function (input) {
+		var output = "";
+		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+		var i = 0;
+
+		input = Base64._utf8_encode(input);
+
+		while (i < input.length) {
+
+			chr1 = input.charCodeAt(i++);
+			chr2 = input.charCodeAt(i++);
+			chr3 = input.charCodeAt(i++);
+
+			enc1 = chr1 >> 2;
+			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+			enc4 = chr3 & 63;
+
+			if (isNaN(chr2)) {
+				enc3 = enc4 = 64;
+			} else if (isNaN(chr3)) {
+				enc4 = 64;
+			}
+
+			output = output +
+			this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
+			this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+
+		}
+
+		return output;
+	},
+
+	// public method for decoding
+	decode : function (input) {
+		var output = "";
+		var chr1, chr2, chr3;
+		var enc1, enc2, enc3, enc4;
+		var i = 0;
+
+		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+		while (i < input.length) {
+
+			enc1 = this._keyStr.indexOf(input.charAt(i++));
+			enc2 = this._keyStr.indexOf(input.charAt(i++));
+			enc3 = this._keyStr.indexOf(input.charAt(i++));
+			enc4 = this._keyStr.indexOf(input.charAt(i++));
+
+			chr1 = (enc1 << 2) | (enc2 >> 4);
+			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+			chr3 = ((enc3 & 3) << 6) | enc4;
+
+			output = output + String.fromCharCode(chr1);
+
+			if (enc3 != 64) {
+				output = output + String.fromCharCode(chr2);
+			}
+			if (enc4 != 64) {
+				output = output + String.fromCharCode(chr3);
+			}
+
+		}
+
+		output = Base64._utf8_decode(output);
+
+		return output;
+
+	},
+
+	// private method for UTF-8 encoding
+	_utf8_encode : function (string) {
+		string = string.replace(/\r\n/g,"\n");
+		var utftext = "";
+
+		for (var n = 0; n < string.length; n++) {
+
+			var c = string.charCodeAt(n);
+
+			if (c < 128) {
+				utftext += String.fromCharCode(c);
+			}
+			else if((c > 127) && (c < 2048)) {
+				utftext += String.fromCharCode((c >> 6) | 192);
+				utftext += String.fromCharCode((c & 63) | 128);
+			}
+			else {
+				utftext += String.fromCharCode((c >> 12) | 224);
+				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+				utftext += String.fromCharCode((c & 63) | 128);
+			}
+
+		}
+
+		return utftext;
+	},
+
+	// private method for UTF-8 decoding
+	_utf8_decode : function (utftext) {
+		var string = "";
+		var i = 0;
+		var c = c1 = c2 = 0;
+
+		while ( i < utftext.length ) {
+
+			c = utftext.charCodeAt(i);
+
+			if (c < 128) {
+				string += String.fromCharCode(c);
+				i++;
+			}
+			else if((c > 191) && (c < 224)) {
+				c2 = utftext.charCodeAt(i+1);
+				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+				i += 2;
+			}
+			else {
+				c2 = utftext.charCodeAt(i+1);
+				c3 = utftext.charCodeAt(i+2);
+				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+				i += 3;
+			}
+
+		}
+
+		return string;
+	}
+
+}

source/dialogs/AddAccount.js

         ]},
         {kind: "HFlexBox", style: "padding-top: 6px;", components: [
             {kind: "Button", flex: 1, caption: "Cancel", onclick: "doCancel"},
-            {kind: "Button", flex: 1, className: "enyo-button-affirmative", caption: "Submit", onclick: "doSubmit"}
+            {name: "saveButton", kind: "ActivityButton", flex: 1, className: "enyo-button-affirmative", caption: "Submit", onclick: "submitAccount"}
         ]},
         {name: "accountUtilities", kind: "me.aaront.AccountUtilities"}
     ],
     },
     registerAccount: function(inSender) {
         this.doRegister();
+    },
+    submitAccount: function(inSender) {
+        inSender.setActive(true);
+        this.doSubmit();
+    },
+    setButtonActive: function(isActive) {
+        this.$.saveButton.setActive(isActive);
     }
 });

source/dialogs/Error.js

+enyo.kind({
+    name: "me.aaront.Error",
+    kind: enyo.ModalDialog,
+    caption: "Error",
+    lazy: false,
+    events: {
+        onClose: ""
+    },
+    components: [
+        {name: "errorContent", className: "enyo-text-error warning-icon"},
+        {kind: "Button", caption: "OK", onclick: "closePopup", className: "enyo-button-negative", style: "margin-top: 15px;"}
+    ],
+    errorParser: {
+        "Forbidden": $L("The account login is incorrect")
+    },
+    create: function() {
+        this.inherited(arguments);
+    },
+    gotError: function(errorText) {
+        this.$.errorContent.setContent(this.errorParser.hasOwnProperty(errorText) ? this.errorParser[errorText] : errorText);
+    },
+    closePopup: function(inSender) {
+        this.doClose();
+        inSender.container.close();
+    }
+});

source/dialogs/RegisterAccount.js

     components: [
         {content: "Register for an Account", flex: 2, style: "font-size: 26px; padding: 6px;"},
         {kind: "RowGroup", caption: "Compatible Services", components: [
-            {kind: "RowItem", onclick: "pinboard", components: [
+            {kind: "RowItem", onclick: "pinboard", tapHighlight: true, components: [
                 {kind: "Image", src: "images/pinboard.png", width: "40px", style: "float: left; padding-right: 20px;"},
                 {content: "Pinboard", flex: 1, style: "height: 30px; padding-top: 6px;"}
             ]},
-            {kind: "RowItem", onclick: "delicious", components: [
+            {kind: "RowItem", onclick: "delicious", tapHighlight: true, components: [
                 {kind: "Image", src: "images/delicious.png", width: "40px", style: "float: left; padding-right: 20px;"},
                 {content: "Delicious", flex: 1, style: "height: 30px; padding-top: 6px;"}
             ]}

source/panels/AccountsPanel.js

         {name: "header", kind: "Header", className: "accounts-header"},
         {kind: "Scroller", flex: 1, components: [
             {name: "accountsList", kind: "VirtualRepeater", onSetupRow: "setupAccountRow", components: [
-                {kind: "Item", className: "account-item", layoutKind: "HFlexLayout", onclick: "selectAccount", components: [
+                {kind: "Item", className: "account-item", tapHighlight: true, layoutKind: "HFlexLayout", onclick: "selectAccount", components: [
                     {name: "serviceIcon", kind: "Image"},
                     {kind: "VFlexBox", className: "account-username-service-box", flex: 1, components: [
                         {name: "username", className: "account-item-username", flex: 1},
                 ]},
                 {name: "accountDrawer", open: false, kind: "Drawer", components: [
                     {name: "accountOptions", kind: "VirtualRepeater", className: "account-option", onSetupRow: "setupOptionRow", components: [
-                        {kind: "Item", className: "account-option-item", layoutKind: "HFlexLayout", onclick: "accountOptionClicked", components: [
+                        {kind: "Item", className: "account-option-item", tapHighlight: true, layoutKind: "HFlexLayout", onclick: "accountOptionClicked", components: [
                             {name: "icon", className: "account-option-icon", kind: "Image"},
                             {name: "description", className: "account-option-description", flex: 1}
                         ]}

source/panels/BookmarksPanel.js

         ]},
         {name: "bookmarksList", kind: "VirtualList", flex: 1, onSetupRow: "setupBookmarksRow", components: [
             {kind: "Divider"},
-            {kind: "Item", layoutKind: "VFlexLayout", className: "bookmark-item", onclick: "bookmarkClicked", flex: 1, components: [
+            {kind: "Item", layoutKind: "VFlexLayout", className: "bookmark-item", tapHighlight: true, onclick: "bookmarkClicked", flex: 1, components: [
                 {name: "description"},
                 {name: "time", className: "bookmark-time"}
             ]}
             ]},
             {kind: "Spacer", flex: 1}
         ]},
-        {name: "bmarkAlchemy", kind: "me.aaront.BmarkAlchemy", onResults: "gotBookmarks"}
+        {name: "bmarkAlchemy", kind: "me.aaront.BmarkAlchemy", onResults: "gotBookmarks", onErrorClosed: "errorClosed"}
     ],
     create: function() {
         this.inherited(arguments);
-        this.headerContentChanged();
+        this.headerTextChanged();
         this.bookmarks = [];
         this.$.bookmarksList.render();
         this.currentSort = 0;
     },
-    headerContentChanged: function() {
+    headerTextChanged: function() {
         this.$.header.setContent(this.headerText);
     },
     loadDataChanged: function() {
         });
         this.$.bookmarksList.refresh();
         this.currentSort = 0;
+    },
+    errorClosed: function(inSender) {
+        this.$.spinnerLarge.hide();
+        this.$.scrim.hide();
     }
 });

source/services/bookmarks/BmarkAlchemy.js

     name: "me.aaront.BmarkAlchemy",
     kind: enyo.Component,
     events: {
-        onResults: ""
+        onResults: "",
+        onErrorClosed: ""
     },
     components: [
         {name: "accountUtilities", kind: "me.aaront.AccountUtilities"},
-        {name: "pinboardApi", kind: "me.aaront.PinboardApi", onResults: "doResults"},
-        {name: "deliciousApi", kind: "me.aaront.DeliciousApi", onResults: "doResults"}
+        {name: "pinboardApi", kind: "me.aaront.PinboardApi", onResults: "doResults", onBookmarksFailure: "gotBookmarksFailure", onTagsFailure: "gotTagsFailure"},
+        {name: "deliciousApi", kind: "me.aaront.DeliciousApi", onResults: "doResults", onBookmarksFailure: "gotBookmarksFailure", onTagsFailure: "gotTagsFailure"},
+        {name: "error", kind: "me.aaront.Error", onClose: "doErrorClosed"}
     ],
     create: function() {
         this.inherited(arguments);
         this.serviceEnum = this.$.accountUtilities.getServiceNameToNumber();
-   },
-   getAllBookmarks: function(account) {
-     switch(account.service) {
-         case this.serviceEnum.pinboard:
-            this.$.pinboardApi.getAllBookmarks(account);
-            break;
-         case this.serviceEnum.delicious:
-            this.$.deliciousApi.getAllBookmarks(account);
-     }
-   },
-   getBookmarksByDate: function(options) {
-     switch(options.service) {
-         case this.serviceEnum.pinboard:
-            this.$.pinboardApi.getBookmarksByDate(options);
-            break;
-         case this.serviceEnum.delicious:
-            this.$.deliciousApi.getBookmarksByDate(options);
-     }
-   },
-   getBookmarksByTag: function(options) {
-     switch(options.service) {
-         case this.serviceEnum.pinboard:
-            this.$.pinboardApi.getBookmarksByTag(options);
-            break;
-         case this.serviceEnum.delicious:
-            this.$.deliciousApi.getBookmarksByTag(options);
-     }
-   },
-   getAllTags: function(account) {
-     switch(account.service) {
-         case this.serviceEnum.pinboard:
-            this.$.pinboardApi.getAllTags(account);
-            break;
-         case this.serviceEnum.delicious:
-            this.$.deliciousApi.getAllTags(account);
-     }
-   }
+    },
+    getAllBookmarks: function(account) {
+        switch(account.service) {
+            case this.serviceEnum.pinboard:
+                this.$.pinboardApi.getAllBookmarks(account);
+                break;
+            case this.serviceEnum.delicious:
+                this.$.deliciousApi.getAllBookmarks(account);
+        }
+    },
+    getBookmarksByDate: function(options) {
+        switch(options.service) {
+            case this.serviceEnum.pinboard:
+                this.$.pinboardApi.getBookmarksByDate(options);
+                break;
+            case this.serviceEnum.delicious:
+                this.$.deliciousApi.getBookmarksByDate(options);
+        }
+    },
+    getBookmarksByTag: function(options) {
+        switch(options.service) {
+            case this.serviceEnum.pinboard:
+                this.$.pinboardApi.getBookmarksByTag(options);
+                break;
+            case this.serviceEnum.delicious:
+                this.$.deliciousApi.getBookmarksByTag(options);
+        }
+    },
+    getAllTags: function(account) {
+        switch(account.service) {
+            case this.serviceEnum.pinboard:
+                this.$.pinboardApi.getAllTags(account);
+                break;
+            case this.serviceEnum.delicious:
+                this.$.deliciousApi.getAllTags(account);
+        }
+    },
+    gotBookmarksFailure: function(inSender, inResponse, inRequest) {
+        this.$.error.validateComponents();
+        this.$.error.gotError(inRequest.xhr.statusText);
+        this.$.error.openAtCenter();
+    }
 });

source/services/bookmarks/DeliciousApi.js

     name: "me.aaront.DeliciousApi",
     kind: enyo.Component,
     events: {
-        onResults: ""
+        onResults: "",
+        onBookmarksFailure: "",
+        onTagsFailure: ""
     },
     components: [
         {name: "getBookmarks", kind: "WebService", handleAs: "xml", contentType: "application/xml", onSuccess: "gotBookmarks", onFailure: "gotBookmarksFailure"},
     create: function() {
         this.inherited(arguments);
     },
-    getAllBookmarks: function(account) {
-        var url = 'https://'+ account.username + ':'+ account.password + '@' + 'api.del.icio.us/v1/posts/all';
+    callBookmarks: function(account, url) {
         this.$.getBookmarks.setUrl(url);
+        var authHeader = Base64.encode("DDDD" + ":" + account.password);
+        this.$.getBookmarks.setHeaders({ Authorization : "Basic " + authHeader });
         this.$.getBookmarks.call();
     },
+    callTags: function(account, url) {
+        this.$.getTags.setUrl(url);
+        var authHeader = Base64.encode(account.username + ":" + account.password);
+        this.$.getTags.setHeaders({ Authorization : "Basic " + authHeader });
+        this.$.getTags.call();
+    },
+    getAllBookmarks: function(account) {
+        var url = 'https://api.del.icio.us/v1/posts/all';
+        this.callBookmarks(account, url);
+    },
     getBookmarksByDate: function(options) {
-        var url = 'https://'+ options.username + ':'+ options.password + '@' + 'api.del.icio.us/v1/posts/all?fromdt=' + options.fromDate + '&todt=' + options.toDate;
-        this.$.getBookmarks.setUrl(url);
-        this.$.getBookmarks.call();
+        var url = 'https://api.del.icio.us/v1/posts/all?fromdt=' + options.fromDate + '&todt=' + options.toDate;
+        this.callBookmarks(options, url);
     },
     getBookmarksByTag: function(options) {
-        var url = 'https://'+ options.username + ':'+ options.password + '@' + 'api.del.icio.us/v1/posts/all?tag=' + options.tag;
-        this.$.getBookmarks.setUrl(url);
-        this.$.getBookmarks.call();
+        var url = 'https://api.del.icio.us/v1/posts/all?tag=' + options.tag;
+        this.callBookmarks(options, url);
     },
     getAllTags: function(account) {
-        var url = 'https://'+ account.username + ':'+ account.password + '@' + 'api.del.icio.us/v1/tags/get';
-        this.$.getTags.setUrl(url);
-        this.$.getTags.call();
+        var url = 'https://api.del.icio.us/v1/tags/get';
+        this.callTags(account, url);
     },
     gotBookmarks: function(inSender, inResponse, inRequest) {
         var xmldom = new DOMParser().parseFromString(inRequest.xhr.responseText, "text/xml");

source/services/bookmarks/PinboardApi.js

     name: "me.aaront.PinboardApi",
     kind: enyo.Component,
     events: {
-        onResults: ""
+        onResults: "",
+        onBookmarksFailure: "",
+        onTagsFailure: ""
     },
     components: [
-        {name: "getBookmarks", kind: "WebService", handleAs: "xml", contentType: "application/xml", onSuccess: "gotBookmarks", onFailure: "gotBookmarksFailure"},
-        {name: "getTags", kind: "WebService", handleAs: "xml", contentType: "application/xml", onSuccess: "gotTags", onFailure: "gotBookmarksFailure"}
+        {name: "getBookmarks", kind: "WebService", handleAs: "xml", contentType: "application/xml", onSuccess: "gotBookmarks", onFailure: "doBookmarksFailure"},
+        {name: "getTags", kind: "WebService", handleAs: "xml", contentType: "application/xml", onSuccess: "gotTags", onFailure: "doTagsFailure"}
     ],
     create: function() {
         this.inherited(arguments);
     },
-    getAllBookmarks: function(account) {
-        var url = 'https://'+ account.username + ':'+ account.password + '@' + 'api.pinboard.in/v1/posts/all';
+    callBookmarks: function(account, url) {
         this.$.getBookmarks.setUrl(url);
+        var authHeader = Base64.encode(account.username + ":" + account.password);
+        this.$.getBookmarks.setHeaders({ Authorization : "Basic " + authHeader });
         this.$.getBookmarks.call();
     },
+    callTags: function(account, url) {
+        this.$.getTags.setUrl(url);
+        var authHeader = Base64.encode(account.username + ":" + account.password);
+        this.$.getTags.setHeaders({ Authorization : "Basic " + authHeader });
+        this.$.getTags.call();
+    },
+    getAllBookmarks: function(account) {
+        var url = 'https://api.pinboard.in/v1/posts/all';
+        this.callBookmarks(account, url);
+    },
     getBookmarksByDate: function(options) {
-        var url = 'https://'+ options.username + ':'+ options.password + '@' + 'api.pinboard.in/v1/posts/all&fromdt=' + options.fromDate + '&todt=' + options.toDate;
-        this.$.getBookmarks.setUrl(url);
-        this.$.getBookmarks.call();
+        var url = 'https://api.pinboard.in/v1/posts/all&fromdt=' + options.fromDate + '&todt=' + options.toDate;
+        this.callBookmarks(options, url);
     },
     getBookmarksByTag: function(options) {
-        var url = 'https://'+ options.username + ':'+ options.password + '@' + 'api.pinboard.in/v1/posts/all&tag=' + options.tag;
-        this.$.getBookmarks.setUrl(url);
-        this.$.getBookmarks.call();
+        var url = 'https://api.pinboard.in/v1/posts/all&tag=' + options.tag;
+        this.callBookmarks(options, url);
     },
     getAllTags: function(account) {
-        var url = 'https://'+ account.username + ':'+ account.password + '@' + 'api.pinboard.in/v1/tags/get';
-        this.$.getTags.setUrl(url);
-        this.$.getTags.call();
+        var url = 'https://api.pinboard.in/v1/tags/get';
+        this.callTags(account, url);
     },
     gotBookmarks: function(inSender, inResponse, inRequest) {
         var xmldom = new DOMParser().parseFromString(inRequest.xhr.responseText, "text/xml");

source/views/Main.js

                 {name: "accountsPanel", kind: "me.aaront.AccountsPanel", flex: 1, onSelectAccount: "accountSelected"}
             ]},
             {name: "middle", kind: "SlidingView", width: "320px", peekWidth: 60, components: [
-                {name: "bookmarksPanel", kind: "me.aaront.BookmarksPanel", flex: 1, headerText: "Bookmarks", onSelectBookmark: "bookmarkSelected"}
+                {name: "bookmarksPanel", kind: "me.aaront.BookmarksPanel", flex: 1, onSelectBookmark: "bookmarkSelected"}
             ]},
             {name: "right", kind: "SlidingView", flex: 1, dismissable: true, onResize: "viewerResize", components: [
                 {name: "viewerPanel", kind: "me.aaront.Viewer", flex: 1}
                 break;
             default:
                 this.currentState.page = "all";
+                this.$.bookmarksPanel.setHeaderText(this.currentState.page.toUpperCase());
                 this.$.bookmarksPanel.setLoadData(this.currentState);
         }
     },
     tagSubmitted: function(inSender) {
         this.closePopup(inSender);
         this.currentState.tag = inSender.tag();
+        this.$.bookmarksPanel.setHeaderText(this.currentState.page.toLocaleUpperCase() + ": " + this.currentState.tag)
         this.$.bookmarksPanel.setLoadData(this.currentState);
     },
     dateSubmitted: function(inSender) {
         this.closePopup(inSender);
         this.currentState.fromDate = this.toISODateString(inSender.fromDate());
         this.currentState.toDate = this.toISODateString(inSender.toDate());
+        this.$.bookmarksPanel.setHeaderText(this.currentState.page.toUpperCase())
         this.$.bookmarksPanel.setLoadData(this.currentState);
     },
     toISODateString: function(date) {

source/views/Preferences.js

         this.doCancel();
     },
     addAccountSubmitted: function(inSender) {
+        inSender.setButtonActive(false);
         this.closePopup(inSender);
         var account = {
             service: inSender.service(),

source/views/Welcome.js

         };
         this.$.accountUtilities.addAccount(account);
         var allAccounts = this.$.accountUtilities.getAccounts();
-        console.log(allAccounts);
         this.doDone(allAccounts);
     }
 });

styles/Pinnned.css

 
 .dark-bg {
     background: #444 url('../images/background-accountslist.png') left top repeat;
+}
+
+.enyo-text-error {
+    font-size: 0.8em;
+    padding-top: 5px;
+    padding-left: 50px;
+}
+
+.enyo-text-error.warning-icon {
+    margin-left: 7px;
+    padding-left: 30px;
+}
+
+.warning-icon {
+    background: url(../images/warning.png) 0 0 no-repeat;
+    height: 25px;
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.