├── .bowerrc ├── .codeclimate.yml ├── .csscomb.json ├── .csslintrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .jshintignore ├── .jshintrc ├── App ├── fonts │ ├── SourceSansPro-Regular.ttf │ ├── SourceSansPro-Semibold.ttf │ ├── flat-ui-icons-regular.eot │ ├── flat-ui-icons-regular.svg │ ├── flat-ui-icons-regular.ttf │ ├── flat-ui-icons-regular.woff │ ├── lato │ │ ├── lato-black.eot │ │ ├── lato-black.svg │ │ ├── lato-black.ttf │ │ ├── lato-black.woff │ │ ├── lato-bold.eot │ │ ├── lato-bold.svg │ │ ├── lato-bold.ttf │ │ ├── lato-bold.woff │ │ ├── lato-bolditalic.eot │ │ ├── lato-bolditalic.svg │ │ ├── lato-bolditalic.ttf │ │ ├── lato-bolditalic.woff │ │ ├── lato-italic.eot │ │ ├── lato-italic.svg │ │ ├── lato-italic.ttf │ │ ├── lato-italic.woff │ │ ├── lato-light.eot │ │ ├── lato-light.svg │ │ ├── lato-light.ttf │ │ ├── lato-light.woff │ │ ├── lato-regular.eot │ │ ├── lato-regular.svg │ │ ├── lato-regular.ttf │ │ └── lato-regular.woff │ └── pinbored │ │ ├── OpenSans-Bold.ttf │ │ ├── OpenSans-BoldItalic.ttf │ │ ├── OpenSans-ExtraBold.ttf │ │ ├── OpenSans-ExtraBoldItalic.ttf │ │ ├── OpenSans-Italic.ttf │ │ ├── OpenSans-Light.ttf │ │ ├── OpenSans-LightItalic.ttf │ │ ├── OpenSans-Regular.ttf │ │ ├── OpenSans-Semibold.ttf │ │ └── OpenSans-SemiboldItalic.ttf ├── images │ ├── demo │ │ ├── browser-2x.png │ │ ├── browser-author.jpg │ │ ├── browser-pic-1.jpg │ │ ├── browser-pic-2.jpg │ │ ├── browser-pic-3.jpg │ │ ├── browser-pic-4.jpg │ │ ├── browser-pic-5.jpg │ │ ├── browser-pic-6.jpg │ │ ├── browser.png │ │ ├── html-icon.png │ │ ├── logo-mask-2x.png │ │ ├── logo-mask.png │ │ └── video.jpg │ ├── footer │ │ └── logo.png │ ├── icons │ │ ├── png │ │ │ ├── Book.png │ │ │ ├── Calendar.png │ │ │ ├── Chat.png │ │ │ ├── Clipboard.png │ │ │ ├── Compas.png │ │ │ ├── Gift-Box.png │ │ │ ├── Infinity-Loop.png │ │ │ ├── Mail.png │ │ │ ├── Map.png │ │ │ ├── Pensils.png │ │ │ ├── Pocket.png │ │ │ ├── Retina-Ready.png │ │ │ ├── Toilet-Paper.png │ │ │ └── Watches.png │ │ └── svg │ │ │ ├── book.svg │ │ │ ├── calendar.svg │ │ │ ├── chat.svg │ │ │ ├── clipboard.svg │ │ │ ├── clocks.svg │ │ │ ├── compas.svg │ │ │ ├── gift-box.svg │ │ │ ├── loop.svg │ │ │ ├── mail.svg │ │ │ ├── map.svg │ │ │ ├── paper-bag.svg │ │ │ ├── pencils.svg │ │ │ ├── retina.svg │ │ │ └── toilet-paper.svg │ ├── login │ │ ├── icon.png │ │ ├── imac-2x.png │ │ └── imac.png │ ├── pinbored │ │ ├── icons │ │ │ ├── pinbored-icon-128.png │ │ │ ├── pinbored-icon-144.png │ │ │ ├── pinbored-icon-32.png │ │ │ └── pinbored-icon-48.png │ │ └── logo │ │ │ ├── pinbored-icon-black.png │ │ │ ├── pinbored-icon.png │ │ │ ├── pinbored-logo-transparent-text.png │ │ │ ├── pinbored-logo-transparent.png │ │ │ └── pinbored.psd │ ├── switch │ │ ├── mask-square.png │ │ └── mask.png │ ├── tile │ │ ├── ribbon-2x.png │ │ └── ribbon.png │ ├── todo │ │ ├── done-2x.png │ │ ├── done.png │ │ ├── search-2x.png │ │ ├── search.png │ │ ├── todo-2x.png │ │ └── todo.png │ └── video │ │ ├── fullscreen-2x.png │ │ ├── fullscreen.png │ │ ├── pause-2x.png │ │ ├── pause.png │ │ ├── play-2x.png │ │ ├── play.png │ │ ├── poster.jpg │ │ ├── volume-full-2x.png │ │ ├── volume-full.png │ │ ├── volume-off-2x.png │ │ └── volume-off.png ├── index.html ├── index.template.html ├── package.json ├── scripts │ ├── app.js │ ├── config │ │ └── config-node-nwjs.js │ ├── constants │ │ ├── config.js │ │ └── events.js │ ├── controllers │ │ ├── about.js │ │ ├── appstatus.js │ │ ├── behaviours │ │ │ ├── baseview.js │ │ │ └── searchableview.js │ │ ├── bookmarkitem.js │ │ ├── login.js │ │ ├── mainnav.js │ │ ├── overview.js │ │ ├── settings.js │ │ ├── tagitem.js │ │ ├── tags.js │ │ └── tools.js │ ├── directives │ │ ├── btnloading.js │ │ ├── ngenter.js │ │ └── stopevent.js │ ├── filters │ │ ├── bookmarkfulltextfilter.js │ │ ├── bookmarktagsfilter.js │ │ ├── highlightfilter.js │ │ ├── offsetfilter.js │ │ ├── tagfulltextfilter.js │ │ └── wordcutfilter.js │ ├── services │ │ ├── appconfigservice.js │ │ ├── appstatusservice.js │ │ ├── bookmarkservice.js │ │ ├── modalservice.js │ │ ├── pinboardservice.js │ │ ├── tagservice.js │ │ ├── usersessionservice.js │ │ └── utilservice.js │ └── tests │ │ ├── bookmarkitem_TEST.js │ │ ├── login_TEST.js │ │ ├── pinboardservice_TEST.js │ │ ├── usersessionservice_TEST.js │ │ └── utilservice_TEST.js ├── styles │ ├── app-behaviour.css │ ├── app-styling.css │ ├── app-viewcontainer.css │ ├── override-autocomplete.css │ ├── override-bootstrap.css │ ├── override-browser.css │ ├── override-flatui-pagination.css │ ├── override-flatui.css │ ├── override-gridster.css │ ├── override-ng-tags-input.css │ ├── override-noresponsive.css │ ├── override-splashmodal.old │ ├── view-about.css │ ├── view-bookmarkitem.css │ ├── view-common.css │ ├── view-login.css │ ├── view-mainnav.css │ ├── view-modal.css │ ├── view-overview.css │ ├── view-settings.css │ ├── view-tags.css │ └── view-tools.css ├── templates │ └── modal-about-template.html ├── uib │ └── template │ │ ├── accordion │ │ ├── accordion-group.html │ │ └── accordion.html │ │ ├── alert │ │ └── alert.html │ │ ├── carousel │ │ ├── carousel.html │ │ └── slide.html │ │ ├── datepicker │ │ ├── datepicker.html │ │ ├── day.html │ │ ├── month.html │ │ ├── popup.html │ │ └── year.html │ │ ├── modal │ │ ├── backdrop.html │ │ └── window.html │ │ ├── pager │ │ └── pager.html │ │ ├── pagination │ │ └── pagination.html │ │ ├── popover │ │ ├── popover-html.html │ │ ├── popover-template.html │ │ └── popover.html │ │ ├── progressbar │ │ ├── bar.html │ │ ├── progress.html │ │ └── progressbar.html │ │ ├── rating │ │ └── rating.html │ │ ├── tabs │ │ ├── tab.html │ │ └── tabset.html │ │ ├── timepicker │ │ └── timepicker.html │ │ ├── tooltip │ │ ├── tooltip-html-popup.html │ │ ├── tooltip-popup.html │ │ └── tooltip-template-popup.html │ │ └── typeahead │ │ ├── typeahead-match.html │ │ └── typeahead-popup.html └── views │ ├── about.html │ ├── login.html │ ├── overview.html │ ├── partials │ ├── components │ │ └── taginput.html │ ├── items │ │ ├── BookmarkItem.html │ │ └── tagitem.html │ ├── mainnav.html │ └── search │ │ ├── searchbar-buttons.html │ │ ├── searchbar-extra-bookmarks.html │ │ ├── searchbar-extra-tags.html │ │ ├── searchbar-fulltext.html │ │ ├── searchbar-paging.html │ │ └── searchbar-tags.html │ ├── settings.html │ ├── tags.html │ └── tools.html ├── CONTRIBUTE.md ├── Gruntfile.js ├── LICENSE ├── README.md ├── Resources ├── pinbored-credits.html ├── pinbored-icon.icns └── pinbored-icon.png ├── bower.json ├── karma.conf.js ├── package.json └── sources ├── 451574509.jpg ├── bookmark-icon-1-614x460.png ├── bookmark-icon-3.png ├── pinbored-icon.psd ├── pinbored-logo-github.png ├── pinbored-logo-github.psd └── pinbored-logo.psd /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "App/bower_components" 3 | } -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | csslint: 4 | enabled: true 5 | checks: 6 | compatible-vendor-prefixes: 7 | enabled: false 8 | box-sizing: 9 | enabled: false 10 | duplication: 11 | enabled: true 12 | config: 13 | languages: 14 | - javascript 15 | exclude_fingerprints: 16 | - 0e7f6c4aa17eb0e1de10eed3169e4a1b 17 | eslint: 18 | enabled: true 19 | exclude_fingerprints: 20 | - d71c866dcb8d670c5e540a820329340c 21 | checks: 22 | no-alert: 23 | enabled: false 24 | fixme: 25 | enabled: true 26 | checks: 27 | TODO: 28 | enabled: false 29 | ratings: 30 | paths: 31 | - "**.css" 32 | - "**.js" 33 | exclude_paths: ['App/scripts/tests'] 34 | -------------------------------------------------------------------------------- /.csscomb.json: -------------------------------------------------------------------------------- 1 | { 2 | "remove-empty-rulesets": true, 3 | "always-semicolon": true, 4 | "color-case": "upper", 5 | "block-indent": " ", 6 | "color-shorthand": true, 7 | "element-case": "lower", 8 | "eof-newline": true, 9 | "leading-zero": true, 10 | "quotes": "single", 11 | "sort-order-fallback": "abc", 12 | "space-before-colon": " ", 13 | "space-after-colon": " ", 14 | "space-before-combinator": " ", 15 | "space-after-combinator": " ", 16 | "space-between-declarations": "\n", 17 | "space-before-opening-brace": " ", 18 | "space-after-opening-brace": "\n", 19 | "space-after-selector-delimiter": "\n", 20 | "space-before-selector-delimiter": "", 21 | "space-before-closing-brace": "\n", 22 | "strip-spaces": true, 23 | "tab-size": true, 24 | "unitless-zero": true, 25 | "vendor-prefix-align": true 26 | } -------------------------------------------------------------------------------- /.csslintrc: -------------------------------------------------------------------------------- 1 | --exclude-exts=.min.css 2 | --ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*{.,-}min.js 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | ecmaFeatures: 2 | modules: true 3 | jsx: false 4 | 5 | env: 6 | amd: true 7 | browser: true 8 | es6: true 9 | jquery: true 10 | node: true 11 | 12 | # http://eslint.org/docs/rules/ 13 | rules: 14 | # Possible Errors 15 | comma-dangle: [2, never] 16 | no-cond-assign: 2 17 | no-console: 0 18 | no-constant-condition: 2 19 | no-control-regex: 2 20 | no-debugger: 2 21 | no-dupe-args: 2 22 | no-dupe-keys: 2 23 | no-duplicate-case: 2 24 | no-empty: 2 25 | no-empty-character-class: 2 26 | no-ex-assign: 2 27 | no-extra-boolean-cast: 2 28 | no-extra-parens: 0 29 | no-extra-semi: 2 30 | no-func-assign: 2 31 | no-inner-declarations: [2, functions] 32 | no-invalid-regexp: 2 33 | no-irregular-whitespace: 2 34 | no-negated-in-lhs: 2 35 | no-obj-calls: 2 36 | no-regex-spaces: 2 37 | no-sparse-arrays: 2 38 | no-unexpected-multiline: 2 39 | no-unreachable: 2 40 | use-isnan: 2 41 | valid-jsdoc: 0 42 | valid-typeof: 2 43 | 44 | # Best Practices 45 | accessor-pairs: 2 46 | block-scoped-var: 0 47 | complexity: [2, 6] 48 | consistent-return: 0 49 | curly: 0 50 | default-case: 0 51 | dot-location: 0 52 | dot-notation: 0 53 | eqeqeq: 2 54 | guard-for-in: 2 55 | no-alert: 2 56 | no-caller: 2 57 | no-case-declarations: 2 58 | no-div-regex: 2 59 | no-else-return: 0 60 | no-empty-label: 2 61 | no-empty-pattern: 2 62 | no-eq-null: 2 63 | no-eval: 2 64 | no-extend-native: 2 65 | no-extra-bind: 2 66 | no-fallthrough: 2 67 | no-floating-decimal: 0 68 | no-implicit-coercion: 0 69 | no-implied-eval: 2 70 | no-invalid-this: 0 71 | no-iterator: 2 72 | no-labels: 0 73 | no-lone-blocks: 2 74 | no-loop-func: 2 75 | no-magic-number: 0 76 | no-multi-spaces: 0 77 | no-multi-str: 0 78 | no-native-reassign: 2 79 | no-new-func: 2 80 | no-new-wrappers: 2 81 | no-new: 2 82 | no-octal-escape: 2 83 | no-octal: 2 84 | no-proto: 2 85 | no-redeclare: 2 86 | no-return-assign: 2 87 | no-script-url: 2 88 | no-self-compare: 2 89 | no-sequences: 0 90 | no-throw-literal: 0 91 | no-unused-expressions: 2 92 | no-useless-call: 2 93 | no-useless-concat: 2 94 | no-void: 2 95 | no-warning-comments: 0 96 | no-with: 2 97 | radix: 2 98 | vars-on-top: 0 99 | wrap-iife: 2 100 | yoda: 0 101 | 102 | # Strict 103 | strict: 0 104 | 105 | # Variables 106 | init-declarations: 0 107 | no-catch-shadow: 2 108 | no-delete-var: 2 109 | no-label-var: 2 110 | no-shadow-restricted-names: 2 111 | no-shadow: 0 112 | no-undef-init: 2 113 | no-undef: 0 114 | no-undefined: 0 115 | no-unused-vars: 0 116 | no-use-before-define: 0 117 | 118 | # Node.js and CommonJS 119 | callback-return: 2 120 | global-require: 2 121 | handle-callback-err: 2 122 | no-mixed-requires: 0 123 | no-new-require: 0 124 | no-path-concat: 2 125 | no-process-exit: 2 126 | no-restricted-modules: 0 127 | no-sync: 0 128 | 129 | # Stylistic Issues 130 | array-bracket-spacing: 0 131 | block-spacing: 0 132 | brace-style: 0 133 | camelcase: 0 134 | comma-spacing: 0 135 | comma-style: 0 136 | computed-property-spacing: 0 137 | consistent-this: 0 138 | eol-last: 0 139 | func-names: 0 140 | func-style: 0 141 | id-length: 0 142 | id-match: 0 143 | indent: 0 144 | jsx-quotes: 0 145 | key-spacing: 0 146 | linebreak-style: 0 147 | lines-around-comment: 0 148 | max-depth: 0 149 | max-len: 0 150 | max-nested-callbacks: 0 151 | max-params: 0 152 | max-statements: [2, 30] 153 | new-cap: 0 154 | new-parens: 0 155 | newline-after-var: 0 156 | no-array-constructor: 0 157 | no-bitwise: 0 158 | no-continue: 0 159 | no-inline-comments: 0 160 | no-lonely-if: 0 161 | no-mixed-spaces-and-tabs: 0 162 | no-multiple-empty-lines: 0 163 | no-negated-condition: 0 164 | no-nested-ternary: 0 165 | no-new-object: 0 166 | no-plusplus: 0 167 | no-restricted-syntax: 0 168 | no-spaced-func: 0 169 | no-ternary: 0 170 | no-trailing-spaces: 0 171 | no-underscore-dangle: 0 172 | no-unneeded-ternary: 0 173 | object-curly-spacing: 0 174 | one-var: 0 175 | operator-assignment: 0 176 | operator-linebreak: 0 177 | padded-blocks: 0 178 | quote-props: 0 179 | quotes: 0 180 | require-jsdoc: 0 181 | semi-spacing: 0 182 | semi: 0 183 | sort-vars: 0 184 | space-after-keywords: 0 185 | space-before-blocks: 0 186 | space-before-function-paren: 0 187 | space-before-keywords: 0 188 | space-in-parens: 0 189 | space-infix-ops: 0 190 | space-return-throw-case: 0 191 | space-unary-ops: 0 192 | spaced-comment: 0 193 | wrap-regex: 0 194 | 195 | # ECMAScript 6 196 | arrow-body-style: 0 197 | arrow-parens: 0 198 | arrow-spacing: 0 199 | constructor-super: 0 200 | generator-star-spacing: 0 201 | no-arrow-condition: 0 202 | no-class-assign: 0 203 | no-const-assign: 0 204 | no-dupe-class-members: 0 205 | no-this-before-super: 0 206 | no-var: 0 207 | object-shorthand: 0 208 | prefer-arrow-callback: 0 209 | prefer-const: 0 210 | prefer-reflect: 0 211 | prefer-spread: 0 212 | prefer-template: 0 213 | require-yield: 0 214 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Build 2 | cache 3 | coverage 4 | inspiration 5 | node_modules 6 | 7 | App/bower_components 8 | App/bower_components_dist 9 | App/node_modules 10 | 11 | App_release/ 12 | Release/ 13 | 14 | scrabblepad.txt 15 | .tmp 16 | .sass-cache 17 | project.sublime-project 18 | project.sublime-workspace 19 | project3.sublime-project 20 | project3.sublime-workspace 21 | karma.report.html 22 | npm-debug.log 23 | 24 | .DS_Store 25 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | /App/scripts/tests/**/*.js -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "loopfunc" : false, 3 | "devel" : false, 4 | "node" : true, 5 | "browser" : true, 6 | "esnext" : true, 7 | "bitwise" : true, 8 | "camelcase": false, 9 | "curly" : true, 10 | "eqeqeq" : true, 11 | "immed" : true, 12 | "indent" : 2, 13 | "latedef" : true, 14 | "newcap" : true, 15 | "noarg" : true, 16 | "quotmark" : "single", 17 | "regexp" : true, 18 | "undef" : true, 19 | "unused" : true, 20 | "strict" : false, 21 | "trailing" : false, 22 | "smarttabs": false, 23 | "white" : false, 24 | "globals" : { 25 | "$" : false, 26 | "angular" : false, 27 | "browser" : false, 28 | "repeater" : false, 29 | "element" : false, 30 | "inject" : false, 31 | "afterEach" : false, 32 | "beforeEach" : false, 33 | "confirm" : false, 34 | "context" : false, 35 | "describe" : false, 36 | "expect" : false, 37 | "it" : false, 38 | "xit" : false, 39 | "pending" : false, 40 | "jasmine" : false, 41 | "JSHINT" : false, 42 | "mostRecentAjaxRequest": false, 43 | "qq" : false, 44 | "runs" : false, 45 | "spyOn" : false, 46 | "spyOnEvent" : false, 47 | "waitsFor" : false, 48 | "xdescribe" : false, 49 | 50 | "Appstatusservice" : false 51 | } 52 | } -------------------------------------------------------------------------------- /App/fonts/SourceSansPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/SourceSansPro-Regular.ttf -------------------------------------------------------------------------------- /App/fonts/SourceSansPro-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/SourceSansPro-Semibold.ttf -------------------------------------------------------------------------------- /App/fonts/flat-ui-icons-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/flat-ui-icons-regular.eot -------------------------------------------------------------------------------- /App/fonts/flat-ui-icons-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/flat-ui-icons-regular.ttf -------------------------------------------------------------------------------- /App/fonts/flat-ui-icons-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/flat-ui-icons-regular.woff -------------------------------------------------------------------------------- /App/fonts/lato/lato-black.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-black.eot -------------------------------------------------------------------------------- /App/fonts/lato/lato-black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-black.ttf -------------------------------------------------------------------------------- /App/fonts/lato/lato-black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-black.woff -------------------------------------------------------------------------------- /App/fonts/lato/lato-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-bold.eot -------------------------------------------------------------------------------- /App/fonts/lato/lato-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-bold.ttf -------------------------------------------------------------------------------- /App/fonts/lato/lato-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-bold.woff -------------------------------------------------------------------------------- /App/fonts/lato/lato-bolditalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-bolditalic.eot -------------------------------------------------------------------------------- /App/fonts/lato/lato-bolditalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-bolditalic.ttf -------------------------------------------------------------------------------- /App/fonts/lato/lato-bolditalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-bolditalic.woff -------------------------------------------------------------------------------- /App/fonts/lato/lato-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-italic.eot -------------------------------------------------------------------------------- /App/fonts/lato/lato-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-italic.ttf -------------------------------------------------------------------------------- /App/fonts/lato/lato-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-italic.woff -------------------------------------------------------------------------------- /App/fonts/lato/lato-light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-light.eot -------------------------------------------------------------------------------- /App/fonts/lato/lato-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-light.ttf -------------------------------------------------------------------------------- /App/fonts/lato/lato-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-light.woff -------------------------------------------------------------------------------- /App/fonts/lato/lato-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-regular.eot -------------------------------------------------------------------------------- /App/fonts/lato/lato-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-regular.ttf -------------------------------------------------------------------------------- /App/fonts/lato/lato-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/lato/lato-regular.woff -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-BoldItalic.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-ExtraBold.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-Italic.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-Light.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-LightItalic.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /App/fonts/pinbored/OpenSans-SemiboldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/fonts/pinbored/OpenSans-SemiboldItalic.ttf -------------------------------------------------------------------------------- /App/images/demo/browser-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-2x.png -------------------------------------------------------------------------------- /App/images/demo/browser-author.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-author.jpg -------------------------------------------------------------------------------- /App/images/demo/browser-pic-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-pic-1.jpg -------------------------------------------------------------------------------- /App/images/demo/browser-pic-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-pic-2.jpg -------------------------------------------------------------------------------- /App/images/demo/browser-pic-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-pic-3.jpg -------------------------------------------------------------------------------- /App/images/demo/browser-pic-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-pic-4.jpg -------------------------------------------------------------------------------- /App/images/demo/browser-pic-5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-pic-5.jpg -------------------------------------------------------------------------------- /App/images/demo/browser-pic-6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser-pic-6.jpg -------------------------------------------------------------------------------- /App/images/demo/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/browser.png -------------------------------------------------------------------------------- /App/images/demo/html-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/html-icon.png -------------------------------------------------------------------------------- /App/images/demo/logo-mask-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/logo-mask-2x.png -------------------------------------------------------------------------------- /App/images/demo/logo-mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/logo-mask.png -------------------------------------------------------------------------------- /App/images/demo/video.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/demo/video.jpg -------------------------------------------------------------------------------- /App/images/footer/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/footer/logo.png -------------------------------------------------------------------------------- /App/images/icons/png/Book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Book.png -------------------------------------------------------------------------------- /App/images/icons/png/Calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Calendar.png -------------------------------------------------------------------------------- /App/images/icons/png/Chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Chat.png -------------------------------------------------------------------------------- /App/images/icons/png/Clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Clipboard.png -------------------------------------------------------------------------------- /App/images/icons/png/Compas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Compas.png -------------------------------------------------------------------------------- /App/images/icons/png/Gift-Box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Gift-Box.png -------------------------------------------------------------------------------- /App/images/icons/png/Infinity-Loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Infinity-Loop.png -------------------------------------------------------------------------------- /App/images/icons/png/Mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Mail.png -------------------------------------------------------------------------------- /App/images/icons/png/Map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Map.png -------------------------------------------------------------------------------- /App/images/icons/png/Pensils.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Pensils.png -------------------------------------------------------------------------------- /App/images/icons/png/Pocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Pocket.png -------------------------------------------------------------------------------- /App/images/icons/png/Retina-Ready.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Retina-Ready.png -------------------------------------------------------------------------------- /App/images/icons/png/Toilet-Paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Toilet-Paper.png -------------------------------------------------------------------------------- /App/images/icons/png/Watches.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/icons/png/Watches.png -------------------------------------------------------------------------------- /App/images/icons/svg/book.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/calendar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/chat.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/clipboard.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/clocks.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /App/images/icons/svg/compas.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/gift-box.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/loop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /App/images/icons/svg/mail.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/map.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/paper-bag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/pencils.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/retina.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/icons/svg/toilet-paper.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/images/login/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/login/icon.png -------------------------------------------------------------------------------- /App/images/login/imac-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/login/imac-2x.png -------------------------------------------------------------------------------- /App/images/login/imac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/login/imac.png -------------------------------------------------------------------------------- /App/images/pinbored/icons/pinbored-icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/icons/pinbored-icon-128.png -------------------------------------------------------------------------------- /App/images/pinbored/icons/pinbored-icon-144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/icons/pinbored-icon-144.png -------------------------------------------------------------------------------- /App/images/pinbored/icons/pinbored-icon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/icons/pinbored-icon-32.png -------------------------------------------------------------------------------- /App/images/pinbored/icons/pinbored-icon-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/icons/pinbored-icon-48.png -------------------------------------------------------------------------------- /App/images/pinbored/logo/pinbored-icon-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/logo/pinbored-icon-black.png -------------------------------------------------------------------------------- /App/images/pinbored/logo/pinbored-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/logo/pinbored-icon.png -------------------------------------------------------------------------------- /App/images/pinbored/logo/pinbored-logo-transparent-text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/logo/pinbored-logo-transparent-text.png -------------------------------------------------------------------------------- /App/images/pinbored/logo/pinbored-logo-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/logo/pinbored-logo-transparent.png -------------------------------------------------------------------------------- /App/images/pinbored/logo/pinbored.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/pinbored/logo/pinbored.psd -------------------------------------------------------------------------------- /App/images/switch/mask-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/switch/mask-square.png -------------------------------------------------------------------------------- /App/images/switch/mask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/switch/mask.png -------------------------------------------------------------------------------- /App/images/tile/ribbon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/tile/ribbon-2x.png -------------------------------------------------------------------------------- /App/images/tile/ribbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/tile/ribbon.png -------------------------------------------------------------------------------- /App/images/todo/done-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/todo/done-2x.png -------------------------------------------------------------------------------- /App/images/todo/done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/todo/done.png -------------------------------------------------------------------------------- /App/images/todo/search-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/todo/search-2x.png -------------------------------------------------------------------------------- /App/images/todo/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/todo/search.png -------------------------------------------------------------------------------- /App/images/todo/todo-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/todo/todo-2x.png -------------------------------------------------------------------------------- /App/images/todo/todo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/todo/todo.png -------------------------------------------------------------------------------- /App/images/video/fullscreen-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/fullscreen-2x.png -------------------------------------------------------------------------------- /App/images/video/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/fullscreen.png -------------------------------------------------------------------------------- /App/images/video/pause-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/pause-2x.png -------------------------------------------------------------------------------- /App/images/video/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/pause.png -------------------------------------------------------------------------------- /App/images/video/play-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/play-2x.png -------------------------------------------------------------------------------- /App/images/video/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/play.png -------------------------------------------------------------------------------- /App/images/video/poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/poster.jpg -------------------------------------------------------------------------------- /App/images/video/volume-full-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/volume-full-2x.png -------------------------------------------------------------------------------- /App/images/video/volume-full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/volume-full.png -------------------------------------------------------------------------------- /App/images/video/volume-off-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/volume-off-2x.png -------------------------------------------------------------------------------- /App/images/video/volume-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/App/images/video/volume-off.png -------------------------------------------------------------------------------- /App/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Michahell", 4 | "email": "maggelo@gmail.com", 5 | "url": "http://www.powergeek.nl/" 6 | }, 7 | "name": "pinbored", 8 | "description": "a bookmark management app built around the Pinboard.in REST service.", 9 | "version": "0.3.4", 10 | "bugs": { 11 | "url": "https://github.com/michahell/pinbored-nwjs/issues", 12 | "email": "maggelo@gmail.com" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/michahell/pinbored-nwjs.git" 17 | }, 18 | "private": true, 19 | "main": "index.html", 20 | "dependencies": { 21 | "request": "^2.69.0", 22 | "request-progress": "^2.0.1", 23 | "restler": "^3.4.0" 24 | }, 25 | "window": { 26 | "title": "Pinbored", 27 | "toolbar": true, 28 | "frame": true, 29 | "min_width": 1024, 30 | "min_height": 768, 31 | "width": 1024, 32 | "height": 768, 33 | "position": "mouse", 34 | "resizable": true 35 | }, 36 | "platformOverrides": { 37 | "win": { 38 | "window": { 39 | "frame": true, 40 | "toolbar": false 41 | } 42 | }, 43 | "linux": { 44 | "window": { 45 | "frame": true, 46 | "toolbar": false 47 | } 48 | }, 49 | "osx": { 50 | "window": { 51 | "frame": true, 52 | "toolbar": false 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /App/scripts/app.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc overview 4 | * @name pinboredWebkitApp 5 | * @description 6 | * # pinboredWebkitApp 7 | * 8 | * Main module of the application. 9 | */ 10 | 11 | angular.module('pinboredWebkitApp.shared', []); 12 | angular.module('pinboredWebkitApp.services', []); 13 | angular.module('pinboredWebkitApp.controllers', []); 14 | 15 | angular.module('pinboredWebkitApp.thirdparty', [ 16 | 'ngAnimate', 17 | 'ngSanitize', 18 | 'ui.bootstrap', // angular ui bootstrap 19 | 'fui', // flat ui bootstrap 20 | 'ngTagsInput', // angular tags component 21 | 'gridster', // gridster grid for tags screen 22 | 'ngProgress', // angular animated progress bar 23 | 'ngDialog', // angular dialog popup 24 | 'monospaced.elastic' // elastic textarea 25 | ]); 26 | 27 | angular.module('pinboredWebkitApp', [ 28 | 'ui.router', // angular ui router 29 | 'ct.ui.router.extras.core', // angular ui bootstrap extras core 30 | 'ct.ui.router.extras.sticky', // angular ui bootstrap extras sticky states 31 | 32 | 'pinboredWebkitApp.thirdparty', // depend on third party shite module 33 | 'pinboredWebkitApp.shared', // depend on shared stuff module 34 | 'pinboredWebkitApp.services', // depend on separate services module 35 | 'pinboredWebkitApp.controllers' // depend on separate controllers module 36 | ]) 37 | .config(function($stateProvider, $stickyStateProvider, $urlRouterProvider) { 38 | 39 | // $stickyStateProvider.enableDebug(true); 40 | 41 | // For any unmatched url, redirect to /overview 42 | $urlRouterProvider.otherwise("/login"); 43 | 44 | // Now set up the states 45 | $stateProvider 46 | 47 | .state('login', { 48 | url: '/login', 49 | sticky: true, 50 | views: { 51 | 'login': { 52 | templateUrl: 'views/login.html', 53 | controller: 'LoginCtrl' 54 | } 55 | } 56 | }) 57 | 58 | .state('overview', { 59 | url: '/overview', 60 | sticky: true, 61 | views: { 62 | 'overview': { 63 | templateUrl: 'views/overview.html', 64 | controller: 'OverviewCtrl' 65 | } 66 | } 67 | }) 68 | 69 | .state('tags', { 70 | url: '/tags', 71 | sticky: true, 72 | views: { 73 | 'tags': { 74 | templateUrl: 'views/tags.html', 75 | controller: 'TagsCtrl' 76 | } 77 | } 78 | }) 79 | 80 | .state('tools', { 81 | url: '/tools', 82 | sticky: true, 83 | views: { 84 | 'tools': { 85 | templateUrl: 'views/tools.html', 86 | controller: 'ToolsCtrl' 87 | } 88 | } 89 | }) 90 | 91 | .state('settings', { 92 | url: '/settings', 93 | sticky: true, 94 | views: { 95 | 'settings': { 96 | templateUrl: 'views/settings.html', 97 | controller: 'SettingsCtrl' 98 | } 99 | } 100 | }) 101 | 102 | .state('about', { 103 | url: '/about', 104 | sticky: true, 105 | views: { 106 | 'about': { 107 | templateUrl: 'views/about.html', 108 | controller: 'AboutCtrl' 109 | } 110 | } 111 | }); 112 | 113 | }) 114 | 115 | .run(function ($rootScope, $state) { 116 | $rootScope.$state = $state; 117 | }); -------------------------------------------------------------------------------- /App/scripts/config/config-node-nwjs.js: -------------------------------------------------------------------------------- 1 | 2 | // catch node-webkit errors globally 3 | // process.on('uncaughtException', function(e) { 4 | // console.info('NODE WEBKIT ERROR!', e); 5 | // }); 6 | 7 | var gui = require('nw.gui'); 8 | 9 | $(function() { 10 | 11 | function Menu(cutLabel, copyLabel, pasteLabel) { 12 | 13 | var menu = new gui.Menu(); 14 | 15 | var cut = new gui.MenuItem({label: cutLabel || 'Cut', click: function() { 16 | document.execCommand('cut'); 17 | console.log('Menu:', 'cutted to clipboard'); 18 | } 19 | }); 20 | 21 | var copy = new gui.MenuItem({label: copyLabel || 'Copy' , click: function() { 22 | document.execCommand('copy'); 23 | console.log('Menu:', 'copied to clipboard'); 24 | } 25 | }); 26 | 27 | var paste = new gui.MenuItem({label: pasteLabel || 'Paste', click: function() { 28 | document.execCommand('paste'); 29 | console.log('Menu:', 'pasted to textarea'); 30 | } 31 | }); 32 | 33 | menu.append(cut); 34 | menu.append(copy); 35 | menu.append(paste); 36 | 37 | return menu; 38 | } 39 | 40 | function fixQuirks() { 41 | 42 | var fixBackspace = function () { 43 | $(document).on('keydown', function (e) { 44 | if (e.which === 8 && !$(e.target).is("input, textarea")) { 45 | e.preventDefault(); 46 | } 47 | }); 48 | }; 49 | 50 | var fixCopyPaste = function () { 51 | var gui = window.require('nw.gui'); 52 | 53 | var mb = new gui.Menu({type: 'menubar'}); 54 | mb.createMacBuiltin('pinbored'); 55 | gui.Window.get().menu = mb; 56 | }; 57 | 58 | fixBackspace(); 59 | fixCopyPaste(); 60 | } 61 | 62 | var menu = new Menu(/* pass cut, copy, paste labels if you need i18n*/); 63 | 64 | fixQuirks(); 65 | // console.info('app config :: quirks fixed!'); 66 | 67 | $(document).on('contextmenu', function(e) { 68 | e.preventDefault(); 69 | menu.popup(e.originalEvent.x, e.originalEvent.y); 70 | }); 71 | 72 | }); -------------------------------------------------------------------------------- /App/scripts/constants/config.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc value 4 | * @name pinboredWebkitApp.Config 5 | * @description 6 | * # Config 7 | * Constant in the pinboredWebkitApp. 8 | */ 9 | angular.module('pinboredWebkitApp.shared') 10 | .constant('Config', { 11 | theme : { 12 | progressbar : { 13 | height : '3px', 14 | color : '#f1c40f' 15 | } 16 | } 17 | }); 18 | -------------------------------------------------------------------------------- /App/scripts/constants/events.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc value 4 | * @name pinboredWebkitApp.Events 5 | * @description 6 | * # Events 7 | * Constant in the pinboredWebkitApp. 8 | */ 9 | angular.module('pinboredWebkitApp.shared') 10 | .constant('Events', { 11 | app : { 12 | statusupdate : 'app:statusupdate', 13 | configchanged : 'app:configchanged' 14 | }, 15 | batch : { 16 | start : 'batch:start', // indicates a batch process started 17 | alltagsremoved : 'batch:alltagsremoved', 18 | alltagsfolded : 'batch:alltagsfolded', 19 | end : 'batch:end' // indicates a batch process ended 20 | }, 21 | user : { 22 | authenticated : 'user:authenticated', 23 | pagechanged : 'user:pagechange' 24 | }, 25 | bm : { 26 | create : 'bookmark:created', 27 | update : 'bookmark:updated', 28 | delete : 'bookmark:deleted' 29 | }, 30 | tag : { 31 | create : 'tag:created', 32 | update : 'tag:updated', 33 | delete : 'tag:deleted' 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /App/scripts/controllers/about.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc function 4 | * @name pinboredWebkitApp.controllers.controller:AboutCtrl 5 | * @description 6 | * # AboutCtrl 7 | * Controller of the pinboredWebkitApp.controllers 8 | */ 9 | angular.module('pinboredWebkitApp.controllers') 10 | .controller('AboutCtrl', 11 | ['$scope', '$controller', 12 | 'Pinboardservice', 'Usersessionservice', 'Utilservice', 13 | function ($scope, $controller, 14 | Pinboardservice, Usersessionservice, Utilservice) { 15 | 16 | // Initialize the super (controller) class and extend it. 17 | angular.extend(this, $controller('BaseViewCtrl', {$scope: $scope})); 18 | 19 | // page model 20 | $scope.model = { 21 | 22 | }; 23 | 24 | $scope.$on('$viewContentLoaded', function() { 25 | console.info('about $viewContentLoaded called'); 26 | }); 27 | 28 | $scope.$on('$destroy', function() { 29 | console.info('about $destroy called'); 30 | }); 31 | 32 | // update current page 33 | Usersessionservice.setCurrentSection('about'); 34 | 35 | }]); 36 | -------------------------------------------------------------------------------- /App/scripts/controllers/appstatus.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc function 4 | * @name pinboredWebkitApp.controllers.controller:AppStatusCtrl 5 | * @description 6 | * # AppStatusCtrl 7 | * Controller of the pinboredWebkitApp.controllers 8 | */ 9 | angular.module('pinboredWebkitApp.controllers') 10 | .controller('AppStatusCtrl', 11 | ['$scope', 'Usersessionservice', 'Events', 12 | function ($scope, Usersessionservice, Events) { 13 | 14 | $scope.status = { 15 | text : '', 16 | progress : 0, 17 | total : 0 18 | }; 19 | 20 | $scope.countingDown = 0; 21 | $scope.timeVisible = 5000; 22 | $scope.visible = false; 23 | 24 | // if app status updates in the model reflect these changes 25 | $scope.$on(Events.app.statusupdate, function(event, status) { 26 | 27 | $scope.visible = true; 28 | $scope.status = status; 29 | 30 | // reset time visible 31 | $scope.timeVisible = 5000; 32 | 33 | // set up the counting down for hiding the app status footer 34 | var countingDown = setInterval(function() { 35 | 36 | if($scope.timeVisible <= 0) { 37 | $scope.$apply($scope.visible = false); 38 | clearInterval(countingDown); 39 | countingDown = 0; 40 | $scope.timeVisible = 5000; 41 | } else { 42 | $scope.timeVisible -= 100; 43 | } 44 | 45 | }, 100); 46 | 47 | }); 48 | 49 | }]); -------------------------------------------------------------------------------- /App/scripts/controllers/behaviours/baseview.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc function 4 | * @name pinboredWebkitApp.controllers.controller:BaseViewCtrl 5 | * @description 6 | * # BaseViewCtrl 7 | * Controller of the pinboredWebkitApp.controllers 8 | */ 9 | angular.module('pinboredWebkitApp.controllers') 10 | .controller('BaseViewCtrl', 11 | ['$scope', '$location', 'Appconfigservice', 'Usersessionservice', 'Events', 12 | function ($scope, $location, Appconfigservice, Usersessionservice, Events) { 13 | 14 | // if not authenticated, redirect to login page 15 | if (Usersessionservice.isAuthenticated() === false) { 16 | $location.path('/login'); 17 | return; 18 | } 19 | 20 | // if logged off, redirect to login page as well 21 | $scope.$on(Events.user.authenticated, function() { // args: event, data 22 | if(Usersessionservice.authenticated === false) { 23 | $location.path('/login'); 24 | return; 25 | } 26 | }); 27 | 28 | $scope.appconfig = {}; // gets populated by Appconfigservice ! 29 | 30 | $scope.onAppconfigChanged = function() { 31 | $scope.appconfig = Appconfigservice.getConfig(); 32 | }; 33 | 34 | $scope.$on('$viewContentLoaded', function() { 35 | // console.info('base view controller $viewContentLoaded called'); 36 | // force local $scope copy of app config obj. 37 | $scope.onAppconfigChanged(); 38 | 39 | // @exclude 40 | window.$scope = $scope; 41 | // @endexclude 42 | }); 43 | 44 | $scope.$on('$destroy', function() { 45 | // console.info('base view controller $destroy called'); 46 | }); 47 | 48 | // set event hooks / listeners 49 | $scope.$on(Events.app.configchanged, $scope.onAppconfigChanged); 50 | 51 | }]); 52 | -------------------------------------------------------------------------------- /App/scripts/controllers/login.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc function 4 | * @name pinboredWebkitApp.controllers.controller:LoginCtrl 5 | * @description 6 | * # LoginCtrl 7 | * Controller of the pinboredWebkitApp.controllers 8 | */ 9 | angular.module('pinboredWebkitApp.controllers') 10 | .controller('LoginCtrl', 11 | ['$q', '$scope', '$controller', '$location', '$timeout', 'Usersessionservice', 'Pinboardservice', 12 | 'Modalservice', 'Utilservice', 13 | function ($q, $scope, $controller, $location, $timeout, Usersessionservice, Pinboardservice, 14 | Modalservice, Utilservice) { 15 | 16 | // Initialize the super (controller) class and extend it. 17 | angular.extend(this, $controller('BaseViewCtrl', {$scope: $scope})); 18 | 19 | $scope.model = { 20 | busy : false, 21 | loginAnimation : null, 22 | username : '', 23 | password : '', 24 | forwardState : '/overview' 25 | }; 26 | 27 | $scope.loginEnter = function(keyEvent) { 28 | if (keyEvent.which === 13) { 29 | $scope.login($scope.model.username, $scope.model.password); 30 | } 31 | }; 32 | 33 | $scope.getUserToken = function (username, password) { 34 | var deferred = $q.defer(); 35 | 36 | Pinboardservice.getUserToken(username, password) 37 | .then(function(result) { 38 | if (result) { 39 | // Unauthorized 40 | if(Number(result) === 401) { // a number indicates we failed, no login... 41 | console.warn('failed, not logged in. ', result); 42 | deferred.reject(Number(result)); 43 | // Service Unavailable 44 | } else if(Number(result) >= 500 && Number(result) <= 510) { 45 | console.warn('service unavailable.'); 46 | deferred.reject(Number(result)); 47 | // Authorized (request success) 48 | } else if(result !== {} && result.result.length === 20) { // now we get a string token back, OMGtyping. 49 | console.info('logged in.'); 50 | deferred.resolve(result.result); 51 | } 52 | } 53 | }) 54 | .catch(function(reason) { 55 | console.warn('Failed, not logged in. ', reason); 56 | $scope.model.loginAnimation = false; 57 | deferred.reject('Failed, not logged in. ', reason); 58 | }); 59 | 60 | return deferred.promise; 61 | }; 62 | 63 | $scope.login = function(username, password) { 64 | $scope.model.busy = true; 65 | 66 | if(!_.isEmpty(username) && !_.isEmpty(password)) { 67 | Pinboardservice.checkConnection() 68 | .then(function() { // urlAdresses 69 | // console.log(urlAdresses); 70 | return $scope.getUserToken(username, password); 71 | }) 72 | .then(function(userTokenID) { 73 | // set some stuff in Usersessionservice 74 | Usersessionservice.setAuthenticated($scope.model.username, userTokenID); 75 | // show loginbox outro anim 76 | $scope.model.loginAnimation = true; 77 | // reroute to main after anim out time 78 | $timeout(function() { 79 | $location.path($scope.model.forwardState); 80 | }, 1000); 81 | }) 82 | .catch(function(failure) { 83 | $scope.model.loginAnimation = false; 84 | $scope.model.busy = false; 85 | $timeout(function() { 86 | $scope.model.loginAnimation = null; 87 | }, 1000); 88 | console.warn(failure); 89 | if(failure === '') { 90 | Modalservice.confirm('No internet connection', 'It seems there is no internet connection. Retry (OK) or go offline (cancel) ?') 91 | .then(function() { 92 | // retry login 93 | $scope.login($scope.model.username, $scope.model.password); 94 | }) 95 | } 96 | }) 97 | 98 | } else { 99 | // todo error no input 100 | Modalservice.alert('Insufficient input', 'Please fill out both username and password.'); 101 | } 102 | }; 103 | 104 | $scope.$on('$viewContentLoaded', function() { 105 | console.info('login $viewContentLoaded called'); 106 | 107 | // add entrance classes. 108 | $timeout(function() { 109 | $scope.model.loginAnimation = 'login'; 110 | $timeout(function() { 111 | $scope.model.loginAnimation = null; 112 | }, 1500); 113 | }, 750); 114 | }); 115 | 116 | $scope.$on("$destroy", function() { 117 | console.info('login $destroy called'); 118 | }); 119 | 120 | }]); 121 | -------------------------------------------------------------------------------- /App/scripts/controllers/mainnav.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc function 4 | * @name pinboredWebkitApp.controllers.controller:MainCtrl 5 | * @description 6 | * # MainCtrl 7 | * Controller of the pinboredWebkitApp.controllers 8 | */ 9 | angular.module('pinboredWebkitApp.controllers') 10 | .controller('MainNavCtrl', 11 | ['$scope', '$location', 'ngDialog', 'Usersessionservice', 'Appstatusservice', 'Events', 12 | function ($scope, $location, ngDialog, Usersessionservice, Appstatusservice, Events) { 13 | 14 | // page model 15 | $scope.model = { 16 | showNav : false, 17 | activeSection : '', 18 | username : 'user', 19 | navItems : [ 20 | { name: 'overview' }, 21 | { name: 'tags' }, 22 | // { name: 'tools' }, 23 | // { name: 'statistics' }, 24 | { name: 'settings' } 25 | // { name: 'about' } 26 | ], 27 | userMenuItems : [ 28 | { name : 'about', action : 'about' }, 29 | { name : 'log out', action : 'logout' } 30 | ], 31 | selectedUserMenuItem : null 32 | }; 33 | 34 | // Load native UI library 35 | var gui = require('nw.gui'); 36 | 37 | // root scope listeners 38 | $scope.$on(Events.user.authenticated, function() { // args: event, model 39 | if(Usersessionservice.authenticated === true) { 40 | $scope.showNav = true; 41 | $scope.model.username = Usersessionservice.user; 42 | } else if(Usersessionservice.authenticated === false) { 43 | $scope.showNav = false; 44 | return; 45 | } 46 | }); 47 | 48 | $scope.$on(Events.user.pagechanged, function() { // args: event, currentPage 49 | $scope.model.activeSection = Usersessionservice.currentSection; 50 | }); 51 | 52 | $scope.doAction = function(action) { 53 | switch (action) { 54 | case 'about': $scope.about(); break; 55 | case 'logout': $scope.logout(); break; 56 | } 57 | }; 58 | 59 | $scope.about = function() { 60 | console.log('about clicked...'); 61 | // ngDialog.open({ template: 'templates/modal-about-template.html' }); 62 | $location.path('/about'); 63 | }; 64 | 65 | $scope.logout = function() { 66 | // TODO logout 67 | console.log('logging out...'); 68 | Usersessionservice.destroy(); 69 | console.info('logged out.'); 70 | }; 71 | 72 | $scope.quit = function() { 73 | // TODO quit 74 | console.log('quitting...'); 75 | if(Appstatusservice.hasPendingOperations() === false) { 76 | $scope.logout(); 77 | console.info('bye! see you next time.'); 78 | // Quit current app 79 | gui.App.quit(); 80 | } 81 | }; 82 | 83 | }]); -------------------------------------------------------------------------------- /App/scripts/controllers/settings.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc function 4 | * @name pinboredWebkitApp.controllers.controller:SettingsCtrl 5 | * @description 6 | * # SettingsCtrl 7 | * Controller of the pinboredWebkitApp.controllers 8 | */ 9 | angular.module('pinboredWebkitApp.controllers') 10 | .controller('SettingsCtrl', 11 | ['$scope', '$controller', '$location', 'Pinboardservice', 12 | 'Usersessionservice', 'Utilservice', 'Appconfigservice', 'Events', 13 | function ($scope, $controller, $location, Pinboardservice, 14 | Usersessionservice, Utilservice, Appconfigservice, Events) { 15 | 16 | // Initialize the super (controller) class and extend it. 17 | angular.extend(this, $controller('BaseViewCtrl', {$scope: $scope})); 18 | 19 | // page model 20 | $scope.model = { 21 | changes : false, 22 | appConfigWatcher : null 23 | }; 24 | 25 | $scope.appconfig = {} // gets populated by Appconfigservice ! 26 | $scope.newappconfig = {} // copy of above 27 | 28 | $scope.onAppconfigChanged = function() { 29 | console.log('onAppconfigChanged'); 30 | $scope.appconfig = Appconfigservice.getConfig(); 31 | // copy appconfig 32 | console.log('received new appconfig: ', Appconfigservice.getConfig()); 33 | angular.copy($scope.appconfig, $scope.newappconfig); 34 | // remove watcher if there is any 35 | if($scope.model.appConfigWatcher !== null) { 36 | $scope.model.appConfigWatcher(); 37 | } 38 | // watch appconfig 39 | $scope.model.appConfigWatcher = $scope.$watchCollection('newappconfig', function(newVal, oldVal) { 40 | // console.log('old, new: ', newVal, $scope.appconfig); 41 | if(angular.equals(newVal, $scope.appconfig)) { 42 | $scope.model.changes = false; 43 | } else { 44 | $scope.model.changes = true; 45 | } 46 | }, true); 47 | }; 48 | 49 | $scope.saveChanges = function() { 50 | Appconfigservice.setConfigObject($scope.newappconfig); // triggers onAppconfigChanged through broadcast 51 | $scope.model.changes = false; // reset changes 52 | }; 53 | 54 | $scope.setRecentAmount = function(amount) { 55 | $scope.newappconfig.maxRecentItems = amount; 56 | }; 57 | 58 | $scope.setStaleCheckTimeout = function(amount) { 59 | $scope.newappconfig.staleCheckTimeout = amount * 1000; 60 | }; 61 | 62 | $scope.$on('$viewContentLoaded', function() { 63 | console.info('settings $viewContentLoaded called'); 64 | // force local $scope copy of app config obj. 65 | $scope.onAppconfigChanged(); 66 | }); 67 | 68 | $scope.$on('$destroy', function() { 69 | console.info('settings $destroy called'); 70 | }); 71 | 72 | // update current page 73 | Usersessionservice.setCurrentSection('settings'); 74 | 75 | // set event hooks / listeners 76 | $scope.$on(Events.app.configchanged, $scope.onAppconfigChanged); 77 | 78 | }]); 79 | -------------------------------------------------------------------------------- /App/scripts/controllers/tools.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc function 4 | * @name pinboredWebkitApp.controllers.controller:ToolsCtrl 5 | * @description 6 | * # ToolsCtrl 7 | * Controller of the pinboredWebkitApp.controllers 8 | */ 9 | angular.module('pinboredWebkitApp.controllers') 10 | .controller('ToolsCtrl', 11 | ['$scope', '$controller', '$location', 'Usersessionservice', 'Appstatusservice', 'Bookmarkservice', 12 | function ($scope, $controller, $location, Usersessionservice, Appstatusservice, Bookmarkservice) { 13 | 14 | // Initialize the super (controller) class and extend it. 15 | angular.extend(this, $controller('BaseViewCtrl', {$scope: $scope})); 16 | 17 | $scope.duplicatecheck = { 18 | isLoading: false, 19 | bookmarks : [], 20 | duplicates : { 21 | name : [], 22 | href : [], 23 | extended : [] 24 | } 25 | }; 26 | 27 | $scope.loadCachedBookmarks = function() { 28 | console.log('checking if stored bookmark set exists...'); 29 | // check if they are cached in service. 30 | var isEmpty = (Object.keys(Bookmarkservice.storedBookmarkData).length) === 0 ? true : false; 31 | console.log('are cached bookmarks empty? ' + isEmpty); 32 | 33 | if(isEmpty === false) { 34 | // console.log('cached bookmarks exist.'); 35 | if(Bookmarkservice.storedBookmarkData.length > 0) { 36 | Appstatusservice.updateStatus('retrieving cached bookmarks...'); 37 | $scope.duplicatecheck.isLoading = false; 38 | $scope.duplicatecheck.bookmarks = Bookmarkservice.storedBookmarkData; 39 | Appstatusservice.updateStatus('cached bookmarks retrieved.'); 40 | } 41 | } 42 | }; 43 | 44 | $scope.checkDuplicates = function() { 45 | 46 | // check if we 'have' bookmarks: 47 | if(Object.keys($scope.duplicatecheck.bookmarks).length === 0) { 48 | $scope.loadCachedBookmarks(); 49 | } 50 | 51 | // walk through all bookmarks, check for several duplicate properties: 52 | Appstatusservice.updateStatus('checking if loaded bookmark set contains duplicates...'); 53 | 54 | var doublyIterate = function(list, visitorFunc) { 55 | // maintain internal list of duplicates 56 | var duplicates = []; 57 | 58 | // doubly iterate over given list, execute visitor function 59 | for(var i=0; i 0) { 18 | filteredList = _.filter(bookmarkCollection, function(bm, bmKey) { 19 | var filtered = false; 20 | _.each(searchFields, function(sf) { 21 | if (bm.data[sf].toLowerCase().indexOf(word.toLowerCase()) > -1) { 22 | filtered = true; 23 | return; 24 | } 25 | }); 26 | return filtered; 27 | }); 28 | } 29 | 30 | return filteredList; 31 | }; 32 | }); 33 | -------------------------------------------------------------------------------- /App/scripts/filters/bookmarktagsfilter.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc filter 4 | * @name pinboredWebkitApp.shared.tags 5 | * @description 6 | * # tags filter for BOOKMARKS 7 | * Filter in the pinboredWebkitApp.shared. 8 | */ 9 | angular.module('pinboredWebkitApp.shared') 10 | 11 | .filter('bookmarkTags', function() { 12 | return function(bookmarkCollection, searchTags, logicType) { 13 | 14 | // console.log('tags filter invoked.'); 15 | var filteredList = []; 16 | 17 | if(searchTags.length > 0) { 18 | 19 | if(logicType === 'OR') { 20 | // console.log('filtering tags using logical OR..'); 21 | for(var i=0; i$1'); 15 | } 16 | return $sce.trustAsHtml(text); 17 | }; 18 | }); -------------------------------------------------------------------------------- /App/scripts/filters/offsetfilter.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc filter 4 | * @name pinboredWebkitApp.shared.offset 5 | * @description 6 | * # offset filter 7 | * Filter in the pinboredWebkitApp.shared. 8 | */ 9 | angular.module('pinboredWebkitApp.shared') 10 | 11 | .filter('offset', function() { 12 | return function(input, start) { 13 | 14 | // console.log("offset filter invoked."); 15 | if(input !== undefined && input !== null && input.length > 0) { 16 | start = parseInt(start, 10); 17 | return input.slice(start); 18 | } 19 | }; 20 | }); -------------------------------------------------------------------------------- /App/scripts/filters/tagfulltextfilter.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc filter 4 | * @name pinboredWebkitApp.shared.fulltext 5 | * @description 6 | * # fulltext filter for BOOKMARKS 7 | * Filter in the pinboredWebkitApp.shared. 8 | */ 9 | angular.module('pinboredWebkitApp.shared') 10 | 11 | .filter('tagFulltext', function() { 12 | return function(tagCollection, word) { 13 | 14 | var filteredList = tagCollection; 15 | 16 | if(word !== undefined && word !== '' && word !== ' ' && word.length > 0) { 17 | filteredList = _.filter(tagCollection, function(tag, tagKey) { 18 | if (tag.tagname.toLowerCase().includes(word.toLowerCase()) || tag.tagname === word) { 19 | return true; 20 | } else { 21 | return false; 22 | } 23 | }); 24 | } 25 | 26 | return filteredList; 27 | }; 28 | }); 29 | -------------------------------------------------------------------------------- /App/scripts/filters/wordcutfilter.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc filter 4 | * @name pinboredWebkitApp.shared.wordcut 5 | * @description 6 | * # wordcut filter 7 | * Filter in the pinboredWebkitApp.shared. 8 | */ 9 | angular.module('pinboredWebkitApp.shared') 10 | 11 | .filter('wordcut', function () { 12 | return function (value, wordwise, max, tail) { 13 | if (!value) { return ''; } 14 | 15 | max = parseInt(max, 10); 16 | if (!max) { return value; } 17 | if (value.length <= max) { return value; } 18 | 19 | value = value.substr(0, max); 20 | if (wordwise) { 21 | var lastspace = value.lastIndexOf(' '); 22 | if (lastspace !== -1) { 23 | value = value.substr(0, lastspace); 24 | } 25 | } 26 | 27 | return value + (tail || ' …'); 28 | }; 29 | }); 30 | 31 | -------------------------------------------------------------------------------- /App/scripts/services/appconfigservice.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc service 4 | * @name pinboredWebkitApp.services.Appconfigservice 5 | * @description 6 | * # Appconfigservice 7 | * Service in the pinboredWebkitApp.services. 8 | */ 9 | angular.module('pinboredWebkitApp.services') 10 | .service('Appconfigservice', 11 | ['$rootScope', 12 | function ($rootScope) { 13 | // AngularJS will instantiate a singleton by calling "new" on this function 14 | 15 | this.config = { 16 | maxTagSearch : 4, 17 | // default values 18 | maxRecentItems : 50, 19 | itemsPerPage : 10, 20 | staleCheckTimeout : 5000, // in ms 21 | defaultTimeout : 15000, // in ms 22 | // choosable amounts of defaults 23 | maxRecentAmounts : [10, 25, 50, 100], 24 | itemsPerPageAmounts : [10, 15, 20, 25, 30, 40, 50], 25 | staleCheckTimeoutAmounts : [2, 3, 4, 5, 10, 15, 20] 26 | }; 27 | 28 | this.setConfig = function(configName, configValue) { 29 | var self = this; 30 | // set config 31 | if(configName !== undefined && configName !== null && configValue !== undefined && configValue !== null) { 32 | console.info('setting config name: ' + configName, configValue); 33 | self.config[configName] = configValue; 34 | // notify listeners and provide the current config 35 | $rootScope.$broadcast('app:configchange', self.config); 36 | } 37 | }; 38 | 39 | this.setConfigObject = function(configObject) { 40 | var self = this; 41 | var valueChanged = false; 42 | // set config object 43 | console.log('appconfigservice: setting new configobject.'); 44 | _.each(configObject, function(value, key) { 45 | if(_.contains(Object.keys(self.config), key)) { 46 | // console.info(key, 'exists in: ', Object.keys(self.config)); 47 | if(self.config[key] !== configObject[key]) { 48 | console.info('setting config name: ' + key, value); 49 | valueChanged = true; 50 | self.config[key] = configObject[key]; 51 | } 52 | } 53 | }); 54 | if(valueChanged) { 55 | console.log('sending broadcast update...'); 56 | // notify listeners and provide the current config 57 | $rootScope.$broadcast('app:configchange', self.config); 58 | } 59 | }; 60 | 61 | this.getConfig = function(configName) { 62 | var self = this; 63 | // get config or null 64 | if(configName !== undefined && configName !== null) { 65 | console.info('getting config name: ' + configName); 66 | return self.config[configName]; 67 | } else { 68 | // called without arguments, returns complete config obj. 69 | return self.config; 70 | } 71 | }; 72 | 73 | }]); 74 | -------------------------------------------------------------------------------- /App/scripts/services/appstatusservice.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc service 4 | * @name pinboredWebkitApp.services.Appstatusservice 5 | * @description 6 | * # Appstatusservice 7 | * Service in the pinboredWebkitApp.services. 8 | */ 9 | angular.module('pinboredWebkitApp.services') 10 | .service('Appstatusservice', 11 | ['$rootScope', 'ngProgress', 'Events', 'Config', 12 | function ($rootScope, ngProgress, Events, Config) { 13 | // AngularJS will instantiate a singleton by calling "new" on this function 14 | 15 | this.state = { 16 | hasPendingOperations: false, 17 | numPendingOperations: 0 18 | }; 19 | 20 | this.process = { 21 | text : '', 22 | progress : 0, 23 | total : 0, 24 | color : '' 25 | }; 26 | 27 | // configure ngProgress 28 | ngProgress.height(Config.theme.progressbar.height); 29 | ngProgress.color(Config.theme.progressbar.color); 30 | 31 | this.updateStatus = function(text, progress, total, color) { 32 | 33 | if(progress === undefined || progress === null || total === undefined || total === null) { 34 | progress = 0; 35 | total = 0; 36 | } 37 | 38 | if(color === undefined || color === null) { 39 | color = 'info'; 40 | } 41 | 42 | this.process.text = text; 43 | this.process.progress = progress; 44 | this.process.total = total; 45 | this.process.color = color; 46 | 47 | // notify listeners and provide the current status 48 | $rootScope.$broadcast(Events.app.statusupdate, this.process); 49 | }; 50 | 51 | this.startProgress = function() { 52 | ngProgress.start(); 53 | this.state.hasPendingOperations = true; 54 | this.state.numPendingOperations++; 55 | }; 56 | 57 | this.updateProgress = function(progress, total) { 58 | // update ngProgress bar 59 | if(progress !== 0 && total !== 0 && progress !== null && total !== null) { 60 | ngProgress.start(); 61 | if(progress !== total) { 62 | ngProgress.set(progress/total); 63 | } else if(progress === total) { 64 | ngProgress.complete(); 65 | } 66 | } else { 67 | ngProgress.complete(); 68 | } 69 | }; 70 | 71 | this.resetProgress = function() { 72 | ngProgress.reset(); 73 | if (this.state.numPendingOperations > 0) { 74 | this.state.numPendingOperations--; 75 | } 76 | }; 77 | 78 | this.hasNoPendingOperationsIfZero = function() { 79 | if (this.state.numPendingOperations === 0) { 80 | this.state.hasPendingOperations = false; 81 | } 82 | }; 83 | 84 | this.completeProgress = function() { 85 | ngProgress.complete(); 86 | if (this.state.numPendingOperations > 0) { 87 | this.state.numPendingOperations--; 88 | } 89 | this.hasNoPendingOperationsIfZero(); 90 | }; 91 | 92 | this.hasPendingOperations = function () { 93 | return (this.state.hasPendingOperations) ? this.state.pendingOperations : false; 94 | }; 95 | 96 | }]); 97 | -------------------------------------------------------------------------------- /App/scripts/services/modalservice.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc service 4 | * @name pinboredWebkitApp.services.Modalservice 5 | * @description 6 | * # Modalservice 7 | * Service in the pinboredWebkitApp.services. 8 | */ 9 | angular.module('pinboredWebkitApp.services') 10 | .service('Modalservice', 11 | ['$q', 'Utilservice', 12 | function ($q, Utilservice) { 13 | // AngularJS will instantiate a singleton by calling 'new' on this function 14 | 15 | this.alert = function (windowTitle, messageString) { 16 | 17 | var deferred = $q.defer(); 18 | 19 | alert(messageString); 20 | console.log('confirmed!'); 21 | 22 | // setTimeout for deferred.resolve because alerts return immediately. 23 | setTimeout(function(){ 24 | deferred.resolve(); 25 | }, 250); 26 | 27 | return deferred.promise; 28 | }; 29 | 30 | this.confirm = function (windowTitle, messageString) { 31 | 32 | var deferred = $q.defer(); 33 | var isConfirmed = confirm(messageString); 34 | 35 | if(isConfirmed) { 36 | deferred.resolve({reason: 'accepted', explanation: 'modal confirmed by user.'}); 37 | } else { 38 | deferred.reject({reason: 'cancelled', explanation: 'modal was cancalled by user.'}); 39 | } 40 | 41 | return deferred.promise; 42 | }; 43 | 44 | }]); 45 | -------------------------------------------------------------------------------- /App/scripts/services/tagservice.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc service 4 | * @name pinboredWebkitApp.services.Tagservice 5 | * @description 6 | * # Utilservice 7 | * Service in the pinboredWebkitApp.services. 8 | */ 9 | angular.module('pinboredWebkitApp.services') 10 | .service('Tagservice', 11 | ['$rootScope', '$filter', 'Pinboardservice', 'Appstatusservice', 'Usersessionservice', 'Utilservice', 12 | function ($rootScope, $filter, Pinboardservice, Appstatusservice, Usersessionservice, Utilservice) { 13 | // AngularJS will instantiate a singleton by calling 'new' on this function 14 | 15 | 16 | 17 | 18 | // in memory cached tags 19 | this.storedTagData = {}; 20 | 21 | this.storeTagData = function(pinboardData) { 22 | this.storedTagData = pinboardData; 23 | }; 24 | 25 | 26 | 27 | 28 | // TAG SUPPORT FUNCTIONS 29 | 30 | 31 | 32 | 33 | this.loadTags = function() { 34 | return Pinboardservice.getAllTags(); 35 | }; 36 | 37 | }]); 38 | -------------------------------------------------------------------------------- /App/scripts/services/usersessionservice.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc service 4 | * @name pinboredWebkitApp.services.Usersessionservice 5 | * @description 6 | * # Usersessionservice 7 | * Service in the pinboredWebkitApp.services. 8 | */ 9 | angular.module('pinboredWebkitApp.services') 10 | .service('Usersessionservice', 11 | ['$rootScope', 'Utilservice', 12 | function ($rootScope, Utilservice) { 13 | 14 | // auth related 15 | this.connection = false; 16 | this.authenticated = false; 17 | this.user = ''; 18 | this.apikey = ''; 19 | 20 | // app session related 21 | this.currentSection = ''; 22 | 23 | // temp ref 24 | var self = this; 25 | 26 | this.setCurrentSection = function(newCurrentSection) { 27 | this.currentSection = newCurrentSection; 28 | // notify listeners and provide the data that changed 29 | $rootScope.$broadcast('user:pagechange', this.currentSection); 30 | }; 31 | 32 | this.setAuthenticated = function(username, apikey) { 33 | // return if no correct input is given 34 | if(_.isEmpty(username) || _.isEmpty(apikey)) { return; } 35 | // console.info('setAuthenticated: ' + username + ', ' + apikey); 36 | 37 | this.authenticated = true; 38 | this.user = username; 39 | this.apikey = apikey; 40 | 41 | // store user and apikey in HTML5 Web Storage (sessionStorage) 42 | sessionStorage.user = this.user; 43 | sessionStorage.apikey = this.apikey; 44 | 45 | // notify listeners and provide the data that changed 46 | $rootScope.$broadcast('user:authenticated', this.authenticated); 47 | }; 48 | 49 | this.isAuthenticated = function() { 50 | 51 | // check if user and apikey are still in session storage. 52 | if(_.isEmpty(sessionStorage.user) || _.isEmpty(sessionStorage.apikey)) { 53 | this.authenticated = false; 54 | } else { 55 | // if they are, store them again in the service 56 | this.user = sessionStorage.user; 57 | this.apikey = sessionStorage.apikey; 58 | this.authenticated = true; 59 | } 60 | 61 | // notify listeners and provide the data that changed 62 | $rootScope.$broadcast('user:authenticated', this.authenticated); 63 | 64 | return this.authenticated; 65 | }; 66 | 67 | this.destroy = function() { 68 | // destroy all session variables 69 | this.user = ''; 70 | this.apikey = ''; 71 | this.currentSection = ''; 72 | 73 | // destroy in memory cached bookmarks 74 | this.storedBookmarks = {}; 75 | 76 | // finally set authenticated to false 77 | this.authenticated = false; 78 | 79 | // notify listeners that user authentication changed 80 | $rootScope.$broadcast('user:authenticated', this.authenticated); 81 | }; 82 | 83 | }]); 84 | -------------------------------------------------------------------------------- /App/scripts/services/utilservice.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @ngdoc service 4 | * @name pinboredWebkitApp.services.Utilservice 5 | * @description 6 | * # Utilservice 7 | * Service in the pinboredWebkitApp.services. 8 | */ 9 | angular.module('pinboredWebkitApp.services') 10 | .service('Utilservice', 11 | ['$filter', 12 | function ($filter) { 13 | // AngularJS will instantiate a singleton by calling 'new' on this function 14 | 15 | this.objectSize = function(object) { 16 | return Object.keys(object).length; 17 | }; 18 | 19 | this.capitalize = function(string) { 20 | return string.charAt(0).toUpperCase() + string.substr(1); 21 | }; 22 | 23 | }]); 24 | -------------------------------------------------------------------------------- /App/scripts/tests/login_TEST.js: -------------------------------------------------------------------------------- 1 | 2 | describe('login controller', function() { 3 | 4 | // service names 5 | var Usersessionservice, Utilservice, Pinboardservice, 6 | q, http, timeout, location, rootScope, controller, 7 | loginCtrl, scope; 8 | 9 | beforeEach(function() { 10 | 11 | // load modules 12 | module('pinboredWebkitApp.thirdparty'); 13 | module('pinboredWebkitApp.shared'); 14 | module('pinboredWebkitApp.controllers'); 15 | module('pinboredWebkitApp.services'); 16 | 17 | // inject required services 18 | inject(function($q, $http, $timeout, $location, $rootScope, $controller, _Usersessionservice_, _Utilservice_) { 19 | q = $q; 20 | http = $http; 21 | timeout = $timeout; 22 | location = $location; 23 | rootScope = $rootScope; 24 | controller = $controller; 25 | Utilservice = _Utilservice_; 26 | Usersessionservice = _Usersessionservice_; 27 | scope = rootScope.$new(); 28 | }); 29 | 30 | // mock pinboard service 31 | Pinboardservice = { 32 | setTimeout : function() {}, 33 | handleRestlerComplete : function() {}, 34 | getUserToken : function() {}, 35 | getRecentBookmarks : function() {}, 36 | getAllBookmarks : function() {}, 37 | getBookmark : function() {}, 38 | deleteBookmark : function() {}, 39 | updateBookmark : function(bookmarkitem) {}, 40 | addBookmark : function() {}, 41 | getAllTags : function() {}, 42 | deleteTag : function() {}, 43 | checkUrl : function() {} 44 | }; 45 | 46 | // Create the controller 47 | loginCtrl = controller('LoginCtrl', { 48 | $scope : scope, 49 | Usersessionservice : Usersessionservice, 50 | Pinboardservice : Pinboardservice, 51 | $location : location, 52 | $timeout : timeout 53 | }); 54 | 55 | // spies 56 | spyOn(scope, 'login'); 57 | spyOn(Pinboardservice, 'getUserToken'); 58 | 59 | }); 60 | 61 | it('should be able to instantiate...', inject(function() { 62 | expect(loginCtrl).toBeDefined(); 63 | })); 64 | 65 | it('should have these defaults', function() { 66 | expect(scope.model.busy).toBe(false); 67 | expect(scope.model.loginAnimation).toBe(null); 68 | }); 69 | 70 | it('should call login() on enter keypress', function() { 71 | var keyEvent = {which : 13}; 72 | scope.loginEnter(keyEvent); 73 | expect(scope.login).toHaveBeenCalled(); 74 | }); 75 | 76 | // it('should not login', function() { 77 | // var user = 'someuser', password = 'somepassword'; 78 | // scope.login(user, password); 79 | // expect(Pinboardservice.getUserToken).toHaveBeenCalledWith(user, password); 80 | // expect(scope.loginAnimation).toBe(false); 81 | // }); 82 | 83 | }); 84 | -------------------------------------------------------------------------------- /App/scripts/tests/pinboardservice_TEST.js: -------------------------------------------------------------------------------- 1 | 2 | describe('pinboard service', function() { 3 | 4 | // service names 5 | var q, http, timeout, rootScope, 6 | Usersessionservice, Utilservice, Pinboardservice; 7 | 8 | beforeEach(function() { 9 | 10 | // load modules 11 | module('pinboredWebkitApp.thirdparty'); 12 | module('pinboredWebkitApp.shared'); 13 | module('pinboredWebkitApp.controllers'); 14 | module('pinboredWebkitApp.services'); 15 | 16 | // inject required services 17 | inject(function($q, $http, $timeout, $rootScope, _Usersessionservice_, _Utilservice_, _Pinboardservice_) { 18 | q = $q; 19 | http = $http; 20 | timeout = $timeout; 21 | rootScope = $rootScope; 22 | Utilservice = _Utilservice_; 23 | Pinboardservice = _Pinboardservice_; 24 | Usersessionservice = _Usersessionservice_; 25 | }); 26 | 27 | }); 28 | 29 | it('should be able to instantiate', function() { 30 | expect(Utilservice).toBeDefined(); 31 | expect(Pinboardservice).toBeDefined(); 32 | expect(Usersessionservice).toBeDefined(); 33 | }); 34 | 35 | it('should have the following functions', function() { 36 | expect(angular.isFunction(Pinboardservice.setTimeout)).toBe(true); 37 | expect(angular.isFunction(Pinboardservice.getUserToken)).toBe(true); 38 | expect(angular.isFunction(Pinboardservice.getRecentBookmarks)).toBe(true); 39 | expect(angular.isFunction(Pinboardservice.getAllBookmarks)).toBe(true); 40 | expect(angular.isFunction(Pinboardservice.getBookmark)).toBe(true); 41 | expect(angular.isFunction(Pinboardservice.deleteBookmark)).toBe(true); 42 | expect(angular.isFunction(Pinboardservice.updateBookmark)).toBe(true); 43 | expect(angular.isFunction(Pinboardservice.addBookmark)).toBe(true); 44 | expect(angular.isFunction(Pinboardservice.getAllTags)).toBe(true); 45 | expect(angular.isFunction(Pinboardservice.deleteTag)).toBe(true); 46 | expect(angular.isFunction(Pinboardservice.checkUrl)).toBe(true); 47 | }); 48 | 49 | }); -------------------------------------------------------------------------------- /App/scripts/tests/usersessionservice_TEST.js: -------------------------------------------------------------------------------- 1 | 2 | describe('user session service', function() { 3 | 4 | // service names 5 | var Usersessionservice, Utilservice, rootScope; //mockUtilService; 6 | 7 | beforeEach(function() { 8 | 9 | // load module 10 | module('pinboredWebkitApp.shared'); 11 | module('pinboredWebkitApp.services'); 12 | 13 | // mockUtilService = { 14 | // isEmpty: jasmine.createSpy() 15 | // }; 16 | 17 | // // provide mock util service 18 | // module(function($provide) { 19 | // $provide.value('Utilservice', mockUtilService); 20 | // }); 21 | 22 | // inject required services 23 | inject(function($rootScope, _Usersessionservice_, _Utilservice_) { 24 | Usersessionservice = _Usersessionservice_; 25 | Utilservice = _Utilservice_; 26 | rootScope = $rootScope; 27 | }); 28 | 29 | // spies 30 | spyOn(rootScope, '$broadcast'); 31 | 32 | // clear storages 33 | localStorage.clear(); 34 | sessionStorage.clear(); 35 | 36 | }); 37 | 38 | it('should be able to instantiate', function() { 39 | expect(Usersessionservice).toBeDefined(); 40 | expect(Utilservice).toBeDefined(); 41 | expect(rootScope).toBeDefined(); 42 | }); 43 | 44 | it('should have the following functions', function() { 45 | expect(angular.isFunction(Usersessionservice.setCurrentSection)).toBe(true); 46 | expect(angular.isFunction(Usersessionservice.setAuthenticated)).toBe(true); 47 | expect(angular.isFunction(Usersessionservice.isAuthenticated)).toBe(true); 48 | expect(angular.isFunction(Usersessionservice.destroy)).toBe(true); 49 | }); 50 | 51 | it('should set current page', function() { 52 | Usersessionservice.setCurrentSection(3); 53 | expect(rootScope.$broadcast).toHaveBeenCalledWith('user:pagechange', 3); 54 | }); 55 | 56 | it('should by default not be authenticated', function() { 57 | expect(Usersessionservice.authenticated).toBe(false); 58 | expect(Usersessionservice.isAuthenticated()).toBe(false); 59 | expect(rootScope.$broadcast).toHaveBeenCalledWith('user:authenticated', false); 60 | }); 61 | 62 | it('should authenticate', function() { 63 | var user = 'someuser', password = 'somepassword'; 64 | Usersessionservice.setAuthenticated(user, password); 65 | expect(Usersessionservice.isAuthenticated()).toBe(true); 66 | expect(rootScope.$broadcast).toHaveBeenCalledWith('user:authenticated', true); 67 | }); 68 | 69 | }); -------------------------------------------------------------------------------- /App/scripts/tests/utilservice_TEST.js: -------------------------------------------------------------------------------- 1 | 2 | describe('util service', function() { 3 | 4 | // service names 5 | var Utilservice, $filter; 6 | 7 | beforeEach(function() { 8 | 9 | // load module 10 | module('pinboredWebkitApp.shared'); 11 | module('pinboredWebkitApp.services'); 12 | 13 | // inject required services 14 | inject(function(_Utilservice_, _$filter_) { 15 | Utilservice = _Utilservice_; 16 | $filter = _$filter_; 17 | }); 18 | }); 19 | 20 | it('should be able to instantiate', function() { 21 | expect(Utilservice).toBeDefined(); 22 | }); 23 | 24 | it('should have the following functions', function() { 25 | expect(angular.isFunction(Utilservice.objectSize)).toBe(true); 26 | expect(angular.isFunction(Utilservice.objectSize)).toBe(true); 27 | }); 28 | 29 | it('should capitalize', function() { 30 | expect(Utilservice.capitalize('someString')).toBe('SomeString'); 31 | }); 32 | 33 | it('should return an object length of 2', function() { 34 | expect(Utilservice.objectSize({ test: 1, test2: 2 })).toBe(2); 35 | }); 36 | 37 | }); -------------------------------------------------------------------------------- /App/styles/app-behaviour.css: -------------------------------------------------------------------------------- 1 | /* app behaviour related */ 2 | 3 | .textselectable { 4 | -webkit-user-select : text; 5 | -moz-user-select : text; 6 | -ms-user-select : text; 7 | user-select : text; 8 | -khtml-user-select : text; 9 | -o-user-select : text; 10 | } 11 | -------------------------------------------------------------------------------- /App/styles/app-styling.css: -------------------------------------------------------------------------------- 1 | 2 | /* app body / html */ 3 | 4 | body, 5 | html { 6 | overflow : hidden; 7 | width : 100%; 8 | height : 100%; 9 | -webkit-user-select : none; 10 | -moz-user-select : none; 11 | -ms-user-select : none; 12 | user-select : none; 13 | /*background-color: #34495E;*/ 14 | 15 | background-color : #2C3E50; 16 | -khtml-user-select : none; 17 | -o-user-select : none; 18 | } 19 | 20 | /* scrollbar */ 21 | 22 | ::-webkit-scrollbar { 23 | width : 8px; 24 | height : 8px; 25 | background-color : transparent; 26 | } 27 | ::-webkit-scrollbar-track { 28 | width : 8px; 29 | background-color : transparent; 30 | } 31 | ::-webkit-scrollbar-track-piece { 32 | background-color : #2980B9; 33 | } 34 | ::-webkit-scrollbar-thumb { 35 | width : 8px; 36 | background-color : rgba(255, 255, 255, 0.4); 37 | } 38 | 39 | /* resize webkit element */ 40 | 41 | ::-webkit-resizer { 42 | border: 2px solid black; 43 | background: red; 44 | box-shadow: 0 0 5px 5px blue; 45 | outline: 2px solid yellow; 46 | } 47 | 48 | /* pinbored logo */ 49 | 50 | .navbar-brand { 51 | box-sizing : border-box; 52 | height : 53px; 53 | margin-top : -7px; 54 | padding : 0; 55 | padding-top : 11px; 56 | } 57 | 58 | /* app-status-indicator */ 59 | 60 | .app-status-indicator { 61 | position : absolute; 62 | z-index : 20; 63 | bottom : 0; 64 | box-sizing : border-box; 65 | width : 100%; 66 | height : 50px; 67 | padding : 10px; 68 | padding-left : 20px; 69 | -webkit-transition : all linear 0.3s; 70 | transition : all linear 0.3s; 71 | text-align : left; 72 | border-top : 2px; 73 | background : #ECF0F1; 74 | } 75 | 76 | .app-status-indicator.ng-hide { 77 | opacity : 0; 78 | } 79 | 80 | .app-status-indicator h7 { 81 | color : #34495E; 82 | } 83 | 84 | .app-status-indicator h7 .danger { 85 | font-weight : bold; 86 | color : #C0392B; 87 | } 88 | 89 | .app-status-indicator h7 .info { 90 | font-weight : bold; 91 | color : #16A085; 92 | } 93 | -------------------------------------------------------------------------------- /App/styles/app-viewcontainer.css: -------------------------------------------------------------------------------- 1 | 2 | .viewcontainer { 3 | height : calc(100% - 53px); 4 | /*background: #34495E;*/ 5 | } 6 | 7 | /* ng-animate DEFAULT transitions */ 8 | /*.viewcontainer.ng-leave { z-index:9999; } 9 | .viewcontainer.ng-enter { z-index:8888; }*/ 10 | 11 | .viewcontainer.ng-enter, 12 | .viewcontainer.ng-leave { 13 | transition : all 0.5s ease; 14 | } 15 | 16 | .viewcontainer.ng-enter { 17 | opacity : 0; 18 | } 19 | .viewcontainer.ng-enter-active { 20 | opacity : 0; 21 | } 22 | .viewcontainer.ng-leave { 23 | opacity : 0; 24 | } 25 | .viewcontainer.leave-active { 26 | opacity : 0; 27 | } 28 | -------------------------------------------------------------------------------- /App/styles/override-autocomplete.css: -------------------------------------------------------------------------------- 1 | tags-input .autocomplete { 2 | border : none; 3 | border-radius : 3px; 4 | background-color : #ECF0F1; 5 | } 6 | 7 | tags-input .autocomplete .suggestion-item { 8 | background-color : #ECF0F1; 9 | } 10 | 11 | tags-input .autocomplete .suggestion-item.selected { 12 | color : #FFF; 13 | background-color : #1ABC9C; 14 | } 15 | 16 | tags-input .autocomplete .suggestion-item em { 17 | color : #2C3E50; 18 | background-color : transparent; 19 | } 20 | 21 | tags-input .autocomplete .suggestion-item.selected em { 22 | font-style : oblique; 23 | color : #FFF; 24 | background-color : #2C3E50; 25 | } 26 | -------------------------------------------------------------------------------- /App/styles/override-bootstrap.css: -------------------------------------------------------------------------------- 1 | /* Bootstrap overrides */ 2 | 3 | .container { 4 | width : auto; 5 | padding-right : 0; 6 | padding-left : 0; 7 | } 8 | 9 | .navbar { 10 | min-height : 0; 11 | margin-bottom : 0; 12 | } 13 | 14 | .navbar > .container { 15 | display : block; 16 | width : auto; 17 | } 18 | 19 | .navbar-nav.navbar-right:last-child { 20 | margin-right : 0; 21 | } 22 | 23 | .navbar-nav li:after { 24 | position : absolute; 25 | left : 50%; 26 | margin-top : -10px; 27 | margin-left : -10px; 28 | content : ' '; 29 | border : solid 10px transparent; 30 | border-width : 10px; 31 | border-color : transparent; 32 | border-top : solid 0 transparent; 33 | transition: 0.3s all ease-out; 34 | } 35 | 36 | .navbar-nav .active:after { 37 | border-color : transparent transparent #2C3E50 transparent; 38 | } 39 | 40 | textarea { 41 | resize : none; 42 | } 43 | 44 | .row { 45 | margin : 0; 46 | } 47 | 48 | .col-xs-1, 49 | .col-xs-2, 50 | .col-xs-3, 51 | .col-xs-4, 52 | .col-xs-5, 53 | .col-xs-6, 54 | .col-xs-7, 55 | .col-xs-8, 56 | .col-xs-9, 57 | .col-xs-10, 58 | .col-xs-11, 59 | .col-xs-12 { 60 | padding : 0; 61 | } 62 | 63 | /* upgrade to tooltip */ 64 | 65 | .tooltip.left .tooltip-arrow { 66 | border-left-color : #ECF0F1; 67 | } 68 | 69 | .tooltip.bottom .tooltip-arrow { 70 | border-bottom-color : #ECF0F1; 71 | } 72 | 73 | .tooltip.top .tooltip-arrow { 74 | border-top-color : #ECF0F1; 75 | } 76 | 77 | .tooltip-inner { 78 | color : #2C3E50; 79 | background : #ECF0F1; 80 | } 81 | 82 | /* modal */ 83 | 84 | .modal-title { 85 | font-size : 22px; 86 | line-height : 1; 87 | } 88 | 89 | .modal { 90 | top : 20%; 91 | display : block; 92 | } 93 | 94 | /* button overrides */ 95 | 96 | .btn-group-sm > .btn { 97 | padding : 8px 15px; 98 | } 99 | 100 | /* checkbox, radio overrides */ 101 | 102 | .checkbox, 103 | .radio { 104 | margin-top : 6px; 105 | } 106 | -------------------------------------------------------------------------------- /App/styles/override-browser.css: -------------------------------------------------------------------------------- 1 | /* button outline removal fix */ 2 | 3 | .btn:focus, 4 | .btn.active:focus, 5 | .btn:active:focus, 6 | .bootstrap-select .btn:focus, 7 | .btn-group.open .dropdown-toggle { 8 | outline : none; 9 | } 10 | -------------------------------------------------------------------------------- /App/styles/override-flatui-pagination.css: -------------------------------------------------------------------------------- 1 | /* 2 | flat-ui pagination overrides. 3 | Copied over pagination-plain classes and renamed to pagination, 4 | because of angular-ui/bootstrap change of classname... 5 | */ 6 | 7 | .pagination { 8 | margin-bottom : 0; 9 | margin-top : 0; 10 | } 11 | 12 | .pagination li>a, 13 | .pagination li>span { 14 | min-height: 0; 15 | min-width: 0; 16 | border: 0; 17 | background: 0; 18 | color: #16a085; 19 | padding: 9px; 20 | } 21 | 22 | .pagination li.active>a, 23 | .pagination li.active>span { 24 | background: 0; 25 | } 26 | 27 | .pagination>.active>a, 28 | .pagination>.active>a:focus, 29 | .pagination>.active>a:hover, 30 | .pagination>.active>span, 31 | .pagination>.active>span:focus, 32 | .pagination>.active>span:hover { 33 | background: 0; 34 | border: 0; 35 | } 36 | 37 | .pagination li > a:hover, 38 | .pagination li > span:hover, 39 | .pagination li > a:focus, 40 | .pagination li > span:focus { 41 | background: 0; 42 | color: #ffffff; 43 | } 44 | 45 | .pagination li.disabled>a, 46 | .pagination li.disabled>span { 47 | color: #c0392b; 48 | background: 0; 49 | } 50 | 51 | .pagination li.disabled>a:hover, 52 | .pagination li.disabled>span:hover, 53 | .pagination li.disabled>a:focus, 54 | .pagination li.disabled>span:focus, 55 | .pagination li.disabled>a:active, 56 | .pagination li.disabled>span:active { 57 | color: #d9534f; 58 | background: 0; 59 | } -------------------------------------------------------------------------------- /App/styles/override-flatui.css: -------------------------------------------------------------------------------- 1 | /* following is specifically for flat-ui */ 2 | 3 | .navbar .container { 4 | padding-left : 0; 5 | padding-right : 0; 6 | } 7 | 8 | .screentitle .btn-xs { 9 | margin-top : 3px; 10 | } 11 | 12 | .screentitle .btn-sm, 13 | .bar .btn-sm, 14 | .settingsrow .btn-sm { 15 | padding : 10px 13px; 16 | line-height : 1; 17 | } 18 | 19 | .navbar > .container .navbar-collapse .navbar-nav.navbar-right:last-child { 20 | margin-right : 0; 21 | } 22 | 23 | .navbar-nav > li > .dropdown-menu { 24 | margin-right : 15px; 25 | } 26 | 27 | .navbar > .container .navbar-brand { 28 | margin-left : 0; 29 | } 30 | 31 | .tagsinput { 32 | margin-bottom : 0; 33 | } 34 | 35 | .login-form:before { 36 | content : none; 37 | } 38 | 39 | .list-group-item { 40 | padding : 0; 41 | margin-bottom : 0; 42 | } 43 | 44 | .navbar-form .btn { 45 | height : auto; 46 | padding : 7.5px 13px; 47 | } 48 | 49 | .navbar-form .form-group + .btn { 50 | font-size : 13px; 51 | } 52 | 53 | /* checkbox text color */ 54 | 55 | .checkbox span { 56 | color : #95A5A6; 57 | } 58 | 59 | /* text size (mostly for bookmarkitem text and tags) */ 60 | 61 | small, 62 | .small { 63 | line-height : 1.3; 64 | } 65 | 66 | // a, 67 | // a:hover, 68 | // a:active, 69 | // a:visited { 70 | // text-decoration: underline; 71 | // } -------------------------------------------------------------------------------- /App/styles/override-gridster.css: -------------------------------------------------------------------------------- 1 | .gridster-loaded { 2 | -webkit-transition : 0.3s ease-out all; 3 | -moz-transition : 0.3s ease-out all; 4 | transition : 0.3s ease-out all; 5 | transition-delay : 0.3s; 6 | } 7 | 8 | .gridster-loaded.gridster-item { 9 | -webkit-transition : 0.3s ease-out all; 10 | -moz-transition : 0.3s ease-out all; 11 | transition : 0.3s ease-out all; 12 | transition-delay : 0; 13 | } 14 | -------------------------------------------------------------------------------- /App/styles/override-ng-tags-input.css: -------------------------------------------------------------------------------- 1 | /* style of ng-tags-input component */ 2 | 3 | tags-input .host { 4 | margin : 0; 5 | } 6 | 7 | tags-input .tags { 8 | background-color : transparent; 9 | -webkit-appearance : none; 10 | -moz-appearance : none; 11 | border : 0; 12 | box-shadow : none; 13 | border-radius : 4px; 14 | padding : 0; 15 | } 16 | 17 | tags-input.ng-invalid .tags { 18 | -webkit-box-shadow : none; 19 | -moz-box-shadow : none; 20 | box-shadow : none; 21 | } 22 | 23 | tags-input.ng-invalid .tags:focus { 24 | border : 2px solid #E74C3C; 25 | color : #E74C3C; 26 | } 27 | 28 | tags-input .tags .input.invalid-tag { 29 | color : #E74C3C; 30 | } 31 | 32 | tags-input .tags .input { 33 | height : auto; 34 | font-family : 'Lato', Helvetica, Arial, sans-serif; 35 | font-size : 15px; 36 | line-height : 1; 37 | background-color : #293A4A; 38 | border : 2px solid #34495E; 39 | border-radius : 4px; 40 | color : #536A81; 41 | padding : 5px; 42 | margin : 0; 43 | margin-top : 2px; 44 | margin-left : 1px; 45 | transition : border 0.25s linear, color 0.25s linear, background-color 0.25s linear; 46 | } 47 | 48 | tags-input .tags .input:focus { 49 | border : 2px solid #1ABC9C; 50 | color : #1ABC9C; 51 | } 52 | 53 | tags-input .tags .input::-webkit-input-placeholder { 54 | color : #536A81; 55 | } 56 | 57 | tags-input .tags.focused { 58 | box-shadow : none; 59 | } 60 | 61 | tags-input .tags .tag-item { 62 | background : #27AE60; 63 | color : #2C3E50; 64 | padding : 0 10px; 65 | padding-left : 5px; 66 | padding-right : 5px; 67 | font-family : 'Lato', Helvetica, Arial, sans-serif; 68 | font-size : 15px; 69 | font-weight : bold; 70 | line-height : 1; 71 | border : 0; 72 | border-radius : 4px; 73 | margin : 2px; 74 | margin-right : 5px; 75 | margin-top : 4px; 76 | } 77 | 78 | tags-input .tags .tag-item.selected { 79 | background : #E74C3C; 80 | color : #2C3E50; 81 | } 82 | 83 | tags-input .tags .tag-item .remove-button { 84 | font-size : 24px; 85 | color : #2C3E50; 86 | padding-right : 2px; 87 | } 88 | -------------------------------------------------------------------------------- /App/styles/override-noresponsive.css: -------------------------------------------------------------------------------- 1 | /* Account for fixed navbar */ 2 | body { 3 | min-width : 1024px; 4 | } 5 | 6 | /* Non-responsive overrides 7 | * 8 | * Utilitze the following CSS to disable the responsive-ness of the container, 9 | * grid system, and navbar. 10 | */ 11 | 12 | /* Reset the container */ 13 | .container { 14 | width : 970px; 15 | max-width : none; 16 | } 17 | 18 | .container .navbar-header, 19 | .container .navbar-collapse { 20 | margin-right : 0; 21 | margin-left : 0; 22 | } 23 | 24 | /* Always float the navbar header */ 25 | .navbar-header { 26 | float : left; 27 | } 28 | 29 | /* Undo the collapsing navbar */ 30 | .navbar-collapse { 31 | display : block; 32 | height : auto; 33 | padding-bottom : 0; 34 | overflow : visible; 35 | } 36 | 37 | .navbar-toggle { 38 | display : none; 39 | } 40 | .navbar-collapse { 41 | border-top : 0; 42 | } 43 | 44 | /* Always apply the floated nav */ 45 | .navbar-nav { 46 | float : left; 47 | margin : 0; 48 | } 49 | .navbar-nav > li { 50 | float : left; 51 | } 52 | .navbar-nav > li > a { 53 | padding : 15px; 54 | } 55 | 56 | /* Redeclare since we override the float above */ 57 | .navbar-nav.navbar-right { 58 | float : right; 59 | } 60 | -------------------------------------------------------------------------------- /App/styles/override-splashmodal.old: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400); 2 | 3 | /* Slideshow style */ 4 | .splash { 5 | position : fixed; 6 | background : rgba(0,0,0,0.85); 7 | width : 100%; 8 | height : 100%; 9 | top : 0; 10 | left : 0; 11 | z-index : 500; 12 | opacity : 0; 13 | visibility : hidden; 14 | overflow : hidden; 15 | -webkit-perspective : 1000px; 16 | perspective : 1000px; 17 | transition : opacity 0.5s, visibility 0s 0.5s; 18 | -webkit-transition : opacity 0.5s, visibility 0s 0.5s; 19 | -moz-transition : opacity 0.5s, visibility 0s 0.5s; 20 | } 21 | 22 | .splash-open.splash { 23 | opacity : 1; 24 | visibility : visible; 25 | -webkit-transition : opacity 0.5s; 26 | transition : opacity 0.5s; 27 | } 28 | 29 | .splash .splash-inner { 30 | width : 100%; 31 | height : 100%; 32 | -webkit-transform-style : preserve-3d; 33 | transform-style : preserve-3d; 34 | -webkit-transform : translate3d(0,0,150px); 35 | -moz-transform : translate3d(0,0,150px); 36 | transform : translate3d(0,0,150px); 37 | -webkit-transition : -webkit-transform 0.5s; 38 | transition : transform 0.5s; 39 | } 40 | 41 | 42 | .splash-open.splash .splash-inner { 43 | -webkit-transform : translate3d(0,0,0); 44 | -moz-transform : translate3d(0,0,0); 45 | transform : translate3d(0,0,0); 46 | } 47 | 48 | .splash .splash-content { 49 | width : 660px; 50 | height : 350px; 51 | position : absolute; 52 | top : 40%; 53 | left : 50%; 54 | margin : -175px 0 0 -330px; 55 | color : #FFF; 56 | font-size : 18px; 57 | } 58 | 59 | .splash-content h1 { 60 | color : #FFF; 61 | margin-bottom : 40px; 62 | } 63 | 64 | 65 | .btn-outline { 66 | margin-top : 40px; 67 | color : #FFF; 68 | box-sizing : border-box; 69 | border : 2px solid #FFF; 70 | border-radius : 2px; 71 | background-color : transparent; 72 | width : 250px; 73 | font-weight : 300; 74 | } 75 | .btn-outline:hover { 76 | color : #FFF; 77 | background-color : rgba(255, 255, 255, 0.05); 78 | } 79 | -------------------------------------------------------------------------------- /App/styles/view-about.css: -------------------------------------------------------------------------------- 1 | #about .screen h7 { 2 | color : #FFF; 3 | } 4 | 5 | #about .screen p { 6 | margin : 0; 7 | padding : 0; 8 | margin-left : 10px; 9 | /*font-weight: bold;*/ 10 | /*color: #BDC3C7;*/ 11 | /*color: #1A4B6C;*/ 12 | color : #E4C52B; 13 | font-size : 14px; 14 | } 15 | 16 | #about .settingsrow { 17 | padding-top : 10px; 18 | padding-left : 10px; 19 | } 20 | 21 | #about .settingsrow label { 22 | color : #E4C52B; 23 | } 24 | -------------------------------------------------------------------------------- /App/styles/view-bookmarkitem.css: -------------------------------------------------------------------------------- 1 | /* bookmark item */ 2 | 3 | .bookmark-item-left { 4 | /*height: 50px; 5 | margin-right: 200px; 6 | margin-left:auto !important;*/ 7 | /*background-color: #34495E;*/ 8 | height : 72px; 9 | cursor : pointer; 10 | } 11 | 12 | .bookmark-item-left small { 13 | margin : 5px; 14 | } 15 | 16 | .bookmark-item-inner { 17 | padding-left : 5px; 18 | padding-top : 5px; 19 | padding-bottom : 3px; 20 | } 21 | 22 | .bookmark-item-inner small { 23 | font-size : 14px; 24 | } 25 | 26 | .bookmark-item-right { 27 | position : relative; 28 | left : auto; 29 | width : 255px; 30 | float : right; 31 | cursor : pointer; 32 | } 33 | 34 | .bookmark-item-right .label { 35 | box-sizing : border-box; 36 | color : #2C3E50; 37 | width : 25px; 38 | height : 25px; 39 | display : block; 40 | margin : 2px; 41 | padding : 6px; 42 | float : right; 43 | } 44 | 45 | .bookmark-item-right .btn-inverse { 46 | background : none; 47 | } 48 | 49 | .bookmark-item-right .btn-inverse:hover { 50 | background : rgba(0, 0, 0, 0.2); 51 | } 52 | 53 | .bookmark-item-right .form-group { 54 | margin-bottom : 0; 55 | } 56 | 57 | .bookmark-item-right .btn-group { 58 | height : 100%; 59 | } 60 | 61 | .bookmark-item-right .btn-group .btn { 62 | box-sizing : border-box; 63 | border-radius : 0; 64 | padding : 26px 15px; 65 | height : 100%; 66 | } 67 | 68 | /* hidden content in bookmark item */ 69 | 70 | .hiddenContent { 71 | box-sizing : border-box; 72 | background : #253443; 73 | /*-webkit-transition : 0.5s ease-out all; 74 | -moz-transition : 0.5s ease-out all; 75 | transition : 0.5s ease-out all;*/ 76 | -webkit-transition : max-height 1.0s cubic-bezier(0.19, 1, 0.22, 1); 77 | -moz-transition : max-height 1.0s cubic-bezier(0.19, 1, 0.22, 1); 78 | transition : max-height 1.0s cubic-bezier(0.19, 1, 0.22, 1); 79 | 80 | /* Initially we don't want any height, and we want the contents to be hidden */ 81 | max-height : 500px; 82 | overflow : hidden; 83 | } 84 | 85 | .hiddenContent.ng-hide { 86 | -webkit-transition : max-height 1.0s cubic-bezier(0, 1.05, 0, 1); 87 | -moz-transition : max-height 1.0s cubic-bezier(0, 1.05, 0, 1); 88 | transition : max-height 1.0s cubic-bezier(0, 1.05, 0, 1); 89 | max-height : 0; 90 | } 91 | 92 | .hiddenContentContainer { 93 | padding-top : 5px; 94 | padding-bottom : 2px; 95 | -webkit-transition : 0.4s ease-out all; 96 | -moz-transition : 0.4s ease-out all; 97 | transition : 0.4s ease-out all; 98 | opacity : 1; 99 | position: relative; 100 | left: 2px; 101 | border-left: 3px solid #5bc0de; 102 | } 103 | 104 | .hiddenContentContainer.ng-hide { 105 | opacity : 0; 106 | } 107 | 108 | .hiddenContentContainer tags-input .tags { 109 | margin-top : 5px; 110 | margin-left : 2px; 111 | margin-bottom : 5px; 112 | } 113 | 114 | .hiddenContent .btn-toolbar { 115 | margin : 2px; 116 | padding-right : 5px; 117 | } 118 | 119 | .hiddenContent .form-control { 120 | width : calc(100% - 8px); 121 | } 122 | 123 | .hiddenContent .editbuttonbar { 124 | margin : 2px; 125 | padding-left : 2px; 126 | padding : 5px; 127 | } 128 | 129 | .hiddenContent .editbuttonbar a.btn { 130 | margin-right : 5px; 131 | float : right; 132 | } 133 | 134 | .hiddenContent .editbuttonbar a.btn.btn-sm, 135 | .hiddenContent .editbuttonbar button.btn.btn-sm, 136 | .hiddenContent .editbuttonbar label.btn.btn-sm { 137 | padding : 10px 13px; 138 | line-height : 1; 139 | } 140 | 141 | .hiddenContent .col-xs-12 { 142 | padding-left : 5px; 143 | padding-right : 5px; 144 | } 145 | 146 | .hiddenContent .input-sm { 147 | height : 30px; 148 | } 149 | 150 | .hiddenContent textarea.hiddeninputs { 151 | box-sizing : border-box; 152 | padding : 10px; 153 | height : 40px; 154 | -webkit-transition : height 0.2s ease-out; 155 | -moz-transition : height 0.2s ease-out; 156 | -o-transition : height 0.2s ease-out; 157 | transition : height 0.2s ease-out; 158 | } 159 | 160 | /* hidden inputs */ 161 | 162 | .hiddeninputs { 163 | border-radius : 0; 164 | background-color : rgba(0, 0, 0, 0.1); 165 | color : #DDD; 166 | border : 0; 167 | margin : 2px; 168 | margin-left : 3px; 169 | padding-left : 8px; 170 | } 171 | 172 | .hiddeninputs:hover { 173 | background-color : rgba(255, 255, 255, 0.1); 174 | } 175 | 176 | /* stale indicator */ 177 | 178 | #stale-indicator { 179 | box-sizing : border-box; 180 | float : right; 181 | width : 110px; 182 | min-height : 72px; 183 | padding : 10px; 184 | color : rgba(255, 255, 255, 0.6); 185 | background : rgba(0, 0, 0, 0.1); 186 | transition : background 0.5s linear; 187 | } 188 | 189 | #stale-indicator .stale-indicator-container { 190 | text-align : center; 191 | margin-top : 10px; 192 | } 193 | 194 | #stale-indicator.unknown, 195 | #stale-indicator.checking { 196 | background : rgba(0, 0, 0, 0.1); 197 | } 198 | -------------------------------------------------------------------------------- /App/styles/view-common.css: -------------------------------------------------------------------------------- 1 | .screentitle { 2 | margin : 0; 3 | padding : 8px; 4 | background-color : #2C3E50; 5 | text-transform : lowercase; 6 | line-height : 0; 7 | -webkit-animation-delay: 1s; 8 | /*-webkit-animation-duration: 2s;*/ 9 | } 10 | 11 | .screentitle h6 { 12 | margin : 0; 13 | margin-top : 5px; 14 | margin-right : 15px; 15 | padding : 0; 16 | font-weight : bold; 17 | color : #BDC3C7; 18 | text-transform : lowercase; 19 | font-size : 20px; 20 | float : left; 21 | } 22 | 23 | /* screens */ 24 | 25 | .screen { 26 | display : table; 27 | height : 100%; 28 | width : 100%; 29 | background : #34495E; 30 | } 31 | 32 | .section { 33 | padding : 10px; 34 | } 35 | 36 | .bar { 37 | padding : 7px; 38 | height : 50px; 39 | background-color : #2C3E50; 40 | box-sizing : border-box; 41 | border-top : 1px solid #34495E; 42 | -webkit-transition : all ease-out 0.2s; 43 | -o-transition : all ease-out 0.2s; 44 | transition : all ease-out 0.2s; 45 | } 46 | 47 | .bar.ng-hide { 48 | height : 0; 49 | padding : 0; 50 | } 51 | 52 | .bar-container { 53 | -webkit-transition : all ease-out 0.2s; 54 | -o-transition : all ease-out 0.2s; 55 | transition : all ease-out 0.2s; 56 | transition-delay : 0.2s; 57 | opacity : 1; 58 | height : 100%; 59 | } 60 | 61 | .bar-container.ng-hide { 62 | -webkit-transition : none; 63 | -o-transition : none; 64 | transition : none; 65 | transition-delay : 0s; 66 | opacity : 0; 67 | height : 0; 68 | } 69 | 70 | /* labels, tags and other stuff */ 71 | 72 | #overview .screentitle .share-label-col, 73 | #tags .screentitle .share-label-col { 74 | text-align : center; 75 | } 76 | 77 | #overview .share-label, 78 | #tags .share-label { 79 | float : none; 80 | color : #95A5A6; 81 | width : auto; 82 | margin-right : 10px; 83 | margin-left : 10px; 84 | } 85 | 86 | #overview label, 87 | #tags label { 88 | margin-bottom : 0; 89 | } 90 | 91 | #overview select, 92 | #tags select { 93 | margin : 4px; 94 | margin-right : 10px; 95 | height : 30px; 96 | } 97 | 98 | #overview select.tall, 99 | #tags select.tall { 100 | margin : 7px; 101 | } 102 | 103 | /* paging */ 104 | 105 | #pages { 106 | /*line-height: 0; 107 | height: auto; 108 | padding: 0;*/ 109 | text-align : center; 110 | } 111 | 112 | /* navbar commonalities */ 113 | 114 | #overview .navbar-inverse, 115 | #tags .navbar-inverse { 116 | background-color : transparent; 117 | } 118 | 119 | #overview .navbar-inverse p, 120 | #tags .navbar-inverse p { 121 | color : #95A5A6; 122 | } 123 | 124 | #overview .navbar-inverse form, 125 | #tags .navbar-inverse form { 126 | width : 100%; 127 | } 128 | 129 | #overview .navbar-inverse .navbar-form .btn-danger, 130 | #tags .navbar-inverse .navbar-form .btn-danger { 131 | background-color : #E74C3C; 132 | } 133 | 134 | #overview .navbar-inverse .navbar-form .btn-danger:hover, 135 | #tags .navbar-inverse .navbar-form .btn-danger:hover { 136 | background-color : #EC7063; 137 | } 138 | 139 | #overview #fulltextsearch .navbar-inverse form .form-group, 140 | #tags .navbar-inverse form .form-group { 141 | width : calc(100% - 100px); 142 | } 143 | 144 | #overview .navbar-inverse form .form-group input, 145 | #tags .navbar-inverse form .form-group input { 146 | width : 100%; 147 | } 148 | 149 | .navbar-inverse .navbar-form .form-control { 150 | border-color : #33495E; 151 | } 152 | 153 | /* navbar commonalities */ 154 | 155 | #overview .navbar, 156 | #tags .navbar { 157 | margin-bottom : 0; 158 | min-height : 35px; 159 | } 160 | 161 | #overview .navbar-collapse, 162 | #tags .navbar-collapse { 163 | padding : 0; 164 | } 165 | 166 | #overview .navbar-collapse .navbar-form, 167 | #tags .navbar-collapse .navbar-form { 168 | padding : 0; 169 | } 170 | 171 | #overview .navbar-embossed > .navbar-collapse, 172 | #tags .navbar-embossed > .navbar-collapse { 173 | -webkit-box-shadow : none; 174 | -moz-box-shadow : none; 175 | box-shadow : none; 176 | } 177 | 178 | #overview #fulltextsearch .share-label, 179 | #tags #fulltextsearch .share-label { 180 | padding-top : 5px; 181 | } 182 | 183 | /* tag item commonalities */ 184 | 185 | .clickabletag { 186 | margin-right : 5px; 187 | background-color : #27AE60; 188 | color : #2C3E50; 189 | cursor : pointer; 190 | -webkit-transition : 0.2s ease-out all; 191 | -moz-transition : 0.2s ease-out all; 192 | transition : 0.2s ease-out all; 193 | } 194 | 195 | .clickabletag:hover { 196 | background-color : #69CC83; 197 | color : #34495E; 198 | } 199 | 200 | .highlightedtag { 201 | background-color : #F39C12; 202 | color : #2C3E50; 203 | } 204 | 205 | .highlightedtag:hover { 206 | background-color : #F1C40F; 207 | color : #34495E; 208 | } 209 | -------------------------------------------------------------------------------- /App/styles/view-login.css: -------------------------------------------------------------------------------- 1 | #login { 2 | background-color : #2C3E50; 3 | width : 100%; 4 | height : 100%; 5 | margin : 0; 6 | padding : 0; 7 | position : absolute; 8 | left : 0; 9 | top : 0; 10 | overflow-y : hidden; 11 | overflow-x : hidden; 12 | } 13 | 14 | #login .tooltip.bottom .tooltip-arrow { 15 | border-bottom-color : #34495E; 16 | } 17 | 18 | #login .tooltip-inner { 19 | background : #34495E; 20 | color : #ECF0F1; 21 | } 22 | 23 | #login .vertical-offset-170 { 24 | padding-top : 170px; 25 | } 26 | -------------------------------------------------------------------------------- /App/styles/view-mainnav.css: -------------------------------------------------------------------------------- 1 | 2 | .user-menu-dropdown { 3 | margin-top : 8px; 4 | margin-right : 8px; 5 | } 6 | 7 | .user-menu-dropdown > button { 8 | padding : 9px 13px; 9 | font-size : 13px; 10 | line-height : 1.385; 11 | border-radius : 4px; 12 | } 13 | 14 | .user-menu-dropdown > ul { 15 | margin-top : 17px; 16 | /*margin-right: 10px;*/ 17 | } 18 | 19 | .navbar-default .navbar-nav > li > a { 20 | text-decoration: underline; 21 | } 22 | -------------------------------------------------------------------------------- /App/styles/view-modal.css: -------------------------------------------------------------------------------- 1 | .modal-tag-highlight { 2 | background : #27AE60; 3 | color : #2C3E50; 4 | padding : 4px 19px; 5 | padding-left : 11px; 6 | padding-right : 11px; 7 | font-family : 'Lato', Helvetica, Arial, sans-serif; 8 | font-size : 20px; 9 | font-weight : bold; 10 | line-height : 1; 11 | border : 0; 12 | border-radius : 6px; 13 | margin : 10px; 14 | } 15 | -------------------------------------------------------------------------------- /App/styles/view-overview.css: -------------------------------------------------------------------------------- 1 | /* view transition styling */ 2 | 3 | 4 | 5 | /* view specific styling */ 6 | 7 | #overview .screentitle .bootstrap-switch-square { 8 | margin-top : 2px; 9 | } 10 | 11 | #overview .clickabletag { 12 | margin-right : 5px; 13 | background-color : #27AE60; 14 | color : #2C3E50; 15 | cursor : pointer; 16 | -webkit-transition : 0.2s ease-out all; 17 | -moz-transition : 0.2s ease-out all; 18 | transition : 0.2s ease-out all; 19 | } 20 | 21 | #overview .clickabletag:hover { 22 | background-color : #69CC83; 23 | color : #34495E; 24 | } 25 | 26 | #overview .highlightedtag { 27 | background-color : #F39C12; 28 | color : #2C3E50; 29 | } 30 | 31 | #overview .highlightedtag:hover { 32 | background-color : #F1C40F; 33 | color : #34495E; 34 | } 35 | 36 | #overview .tagsinput { 37 | background : transparent; 38 | border : none; 39 | padding : 0; 40 | } 41 | 42 | #overview .tagsinput .tag { 43 | margin-bottom : 0; 44 | vertical-align : middle; 45 | } 46 | 47 | #overview .tagsinput input { 48 | vertical-align : middle; 49 | margin : 0; 50 | } 51 | 52 | #overview .tagsinput-add { 53 | background-color : transparent; 54 | margin-bottom : 0; 55 | vertical-align : middle; 56 | } 57 | 58 | #overview .tagContainer { 59 | height : 20px; 60 | max-width: calc(100% - 350px); 61 | overflow: hidden; 62 | } 63 | 64 | /*#selection .bar-container form-group input, 65 | #selection .bar-container form-group button,*/ 66 | #selection .hider { 67 | -webkit-transition : opacity ease-out 0.3s; 68 | -o-transition : opacity ease-out 0.3s; 69 | transition : opacity ease-out 0.3s; 70 | transition-delay : 0.0s; 71 | opacity : 1; 72 | } 73 | 74 | #selection .hider.ng-hide { 75 | opacity : 0; 76 | } 77 | 78 | #selection .hider.ng-hide { 79 | opacity : 0; 80 | } 81 | 82 | #selection .hider.ng-hide-remove-active { 83 | opacity : 1; 84 | } 85 | 86 | /* list specific */ 87 | 88 | .list-group-item { 89 | -webkit-transition : 0.2s ease-out all; 90 | -moz-transition : 0.2s ease-out all; 91 | -o-transition : 0.2s ease-out all; 92 | transition : 0.2s ease-out all; 93 | } 94 | 95 | .list-group-item.ng-move, 96 | .list-group-item.ng-enter { 97 | opacity : 0; 98 | } 99 | 100 | .list-group-item.ng-enter-stagger, 101 | .list-group-item.ng-leave-stagger, 102 | .list-group-item.ng-move-stagger { 103 | /* 50ms between each item being animated after the other */ 104 | -webkit-transition-delay : 50ms; 105 | -moz-transition-delay : 50ms; 106 | transition-delay : 50ms; 107 | 108 | /* this is required here to prevent any CSS inheritance issues */ 109 | -webkit-transition-duration : 0; 110 | -o-transition-duration : 0; 111 | transition-duration : 0; 112 | } 113 | 114 | .list-group-item.ng-move.ng-move-active, 115 | .list-group-item.ng-enter.ng-enter-active { 116 | opacity : 1; 117 | } 118 | 119 | .list-group-item.ng-leave.ng-leave-active { 120 | // -webkit-transition-duration : 0; 121 | // -o-transition-duration : 0; 122 | // transition-duration : 0; 123 | -webkit-transform : scale(0, 0); 124 | -o-transform : scale(0, 0); 125 | transform : scale(0, 0); 126 | height : 1px; 127 | } 128 | 129 | .list-group-item.ng-leave { 130 | -webkit-transition-duration : 0.4s; 131 | -o-transition-duration : 0.4s; 132 | transition-duration : 0.4s; 133 | -webkit-transform : scale(1, 1); 134 | -moz-transform : scale(1, 1); 135 | transform : scale(1, 1); 136 | height : 73px; 137 | } 138 | 139 | #list { 140 | padding : 0; 141 | display : table-row; /* height is dynamic, and will expand... */ 142 | height : 100%; /* ...as content is added (won't scroll) */ 143 | } 144 | 145 | #list .listBackgroundMessage { 146 | position : absolute; 147 | width : 100%; 148 | height : 100px; 149 | line-height : 2; 150 | z-index : 3; 151 | color : #2C3E50; 152 | border : none; 153 | border-radius : 0; 154 | text-align : center; 155 | vertical-align : middle; 156 | margin-top : 20%; 157 | } 158 | 159 | #list > .list-wrapper { 160 | overflow-x : hidden; 161 | overflow-y : scroll; 162 | z-index : 5; 163 | position : relative; 164 | height : 100%; 165 | } 166 | 167 | #list > .fullheight { 168 | height : 100%; 169 | } 170 | 171 | #list > .list-wrapper > ul { 172 | background-color : #34495E; 173 | line-height : 1; 174 | margin : 0; 175 | width : 100%; 176 | height : 100%; 177 | border : none; 178 | border-radius : 0; 179 | z-index : 9; 180 | } 181 | 182 | #list > .list-wrapper > ul > li { 183 | line-height : 1; 184 | z-index : 15; 185 | background-color : #34495E; 186 | border : none; 187 | border-radius : 0; 188 | border-bottom : 1px solid #2C3E50; 189 | } 190 | 191 | #list > .list-wrapper > ul > .selected { 192 | background-color : #212F3C; 193 | } 194 | 195 | #list > .list-wrapper > ul > li .link-item-toolbar .btn-toolbar { 196 | float : right; 197 | } 198 | 199 | #list > .list-wrapper > ul > li .list-group-item-heading { 200 | color : white; 201 | } 202 | 203 | #list > .list-wrapper > ul > li .list-group-item-text { 204 | color : white; 205 | } 206 | 207 | /* highlight for amount of bookmarks */ 208 | 209 | .highlight { 210 | color : #1ABC9C; 211 | font-weight : bold; 212 | } 213 | 214 | /* full text search highlight */ 215 | 216 | .highlight-search { 217 | color : #2C3E50; 218 | font-weight : bold; 219 | background-color : #F1C40F; 220 | border-radius : 3px; 221 | padding : 4px; 222 | padding-top : 2px; 223 | padding-bottom : 2px; 224 | } 225 | -------------------------------------------------------------------------------- /App/styles/view-settings.css: -------------------------------------------------------------------------------- 1 | #settings .screen h7 { 2 | color : #FFF; 3 | } 4 | 5 | #settings .screen p { 6 | margin : 0; 7 | padding : 0; 8 | margin-left : 10px; 9 | /*font-weight: bold;*/ 10 | /*color: #BDC3C7;*/ 11 | /*color: #1A4B6C;*/ 12 | color : #E4C52B; 13 | font-size : 14px; 14 | } 15 | 16 | #settings .settingsHeading { 17 | margin : 0; 18 | margin-top : 5px; 19 | padding : 8px; 20 | padding-left : 14px; 21 | background-color : #2C3E50; 22 | /*background-color: #E4C52B;*/ 23 | text-transform : lowercase; 24 | /*line-height: 0;*/ 25 | } 26 | 27 | #settings .settingsHeading > h7 { 28 | margin : 0; 29 | padding : 0; 30 | /*font-weight: bold;*/ 31 | color : #BDC3C7; 32 | /*color: #1A4B6C;*/ 33 | text-transform : lowercase; 34 | font-size : 16px; 35 | float : left; 36 | } 37 | 38 | #settings .settingsrow { 39 | padding-top : 10px; 40 | padding-left : 10px; 41 | } 42 | 43 | #settings .settingsrow label { 44 | color : #E4C52B; 45 | } 46 | -------------------------------------------------------------------------------- /App/styles/view-tags.css: -------------------------------------------------------------------------------- 1 | /* TAGS VIEW */ 2 | 3 | #tags { 4 | height : calc(100%); 5 | } 6 | 7 | #tags .hiddeninputs { 8 | margin : 0; 9 | } 10 | 11 | #tags .tagbox { 12 | padding : 5px; 13 | background : #2C3E50; 14 | height : 100%; 15 | box-sizing: border-box; 16 | } 17 | 18 | #tags .tag-options { 19 | margin-top : 5px; 20 | -webkit-transition : 0.3s ease-out all; 21 | -moz-transition : 0.3s ease-out all; 22 | transition : 0.3s ease-out all; 23 | transition-delay : 0.3s; 24 | -webkit-transition-delay : 0.3s; 25 | opacity : 1; 26 | } 27 | 28 | #tags .tag-options.ng-hide { 29 | opacity : 0; 30 | transition-delay : 0; 31 | -webkit-transition-delay : 0; 32 | } 33 | 34 | #tags .info { 35 | color : white; 36 | } 37 | -------------------------------------------------------------------------------- /App/styles/view-tools.css: -------------------------------------------------------------------------------- 1 | /* TOOLS VIEW */ 2 | 3 | .tooltitle .btn-sm { 4 | padding : 10px 13px; 5 | line-height : 1; 6 | } 7 | 8 | .tooltitle { 9 | margin : 6px; 10 | width : auto; 11 | padding : 8px; 12 | background-color : #BDC3C7; 13 | text-transform : lowercase; 14 | line-height : 0; 15 | border-radius : 3px; 16 | } 17 | 18 | .tooltitle .toolsheader { 19 | margin : 0; 20 | margin-top : 5px; 21 | margin-right : 15px; 22 | padding : 0; 23 | font-weight : bold; 24 | color : #34495E; 25 | text-transform : lowercase; 26 | font-size : 20px; 27 | float : left; 28 | } 29 | 30 | #list > .list-duplicates > ul { 31 | background-color : #34495E; 32 | } 33 | 34 | #list > .list-duplicates > ul > li { 35 | background-color : #34495E; 36 | border-bottom : 1px solid #2C3E50; 37 | } 38 | 39 | #list > .list-duplicates p, 40 | #list > .list-duplicates small { 41 | color : red; 42 | } 43 | 44 | #list > .list-duplicates .subheader { 45 | color : yellow; 46 | } 47 | -------------------------------------------------------------------------------- /App/templates/modal-about-template.html: -------------------------------------------------------------------------------- 1 |

about

2 |
3 |

4 | Pinbored-webkit is developed by me, Michael Trouw. I do this on a voluntary unpaid basis. 5 | Feel free to flattr me or buy me a beer / coffee! 6 |

7 |
-------------------------------------------------------------------------------- /App/uib/template/accordion/accordion-group.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | {{heading}} 5 |

6 |
7 |
8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /App/uib/template/accordion/accordion.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /App/uib/template/alert/alert.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /App/uib/template/carousel/carousel.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /App/uib/template/carousel/slide.html: -------------------------------------------------------------------------------- 1 |
4 | -------------------------------------------------------------------------------- /App/uib/template/datepicker/datepicker.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
-------------------------------------------------------------------------------- /App/uib/template/datepicker/day.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 | 29 | 30 |
{{::label.abbr}}
{{ weekNumbers[$index] }} 19 | 27 |
31 | -------------------------------------------------------------------------------- /App/uib/template/datepicker/month.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 23 | 24 | 25 |
14 | 22 |
26 | -------------------------------------------------------------------------------- /App/uib/template/datepicker/popup.html: -------------------------------------------------------------------------------- 1 |
2 | 12 |
13 | -------------------------------------------------------------------------------- /App/uib/template/datepicker/year.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 23 | 24 | 25 |
14 | 22 |
26 | -------------------------------------------------------------------------------- /App/uib/template/modal/backdrop.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /App/uib/template/modal/window.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /App/uib/template/pager/pager.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /App/uib/template/pagination/pagination.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /App/uib/template/popover/popover-html.html: -------------------------------------------------------------------------------- 1 |
5 |
6 | 7 |
8 |

9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /App/uib/template/popover/popover-template.html: -------------------------------------------------------------------------------- 1 |
5 |
6 | 7 |
8 |

9 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /App/uib/template/popover/popover.html: -------------------------------------------------------------------------------- 1 |
5 |
6 | 7 |
8 |

9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /App/uib/template/progressbar/bar.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /App/uib/template/progressbar/progress.html: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /App/uib/template/progressbar/progressbar.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | -------------------------------------------------------------------------------- /App/uib/template/rating/rating.html: -------------------------------------------------------------------------------- 1 | 2 | ({{ $index < value ? '*' : ' ' }}) 3 | 4 | 5 | -------------------------------------------------------------------------------- /App/uib/template/tabs/tab.html: -------------------------------------------------------------------------------- 1 |
  • 2 | {{heading}} 3 |
  • 4 | -------------------------------------------------------------------------------- /App/uib/template/tabs/tabset.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 |
    8 |
    9 |
    10 |
    11 | -------------------------------------------------------------------------------- /App/uib/template/timepicker/timepicker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
      
    13 | 14 | : 17 | 18 | : 21 | 22 |
      
    35 | -------------------------------------------------------------------------------- /App/uib/template/tooltip/tooltip-html-popup.html: -------------------------------------------------------------------------------- 1 |
    5 |
    6 |
    7 |
    8 | -------------------------------------------------------------------------------- /App/uib/template/tooltip/tooltip-popup.html: -------------------------------------------------------------------------------- 1 |
    5 |
    6 |
    7 |
    8 | -------------------------------------------------------------------------------- /App/uib/template/tooltip/tooltip-template-popup.html: -------------------------------------------------------------------------------- 1 |
    5 |
    6 |
    9 |
    10 | -------------------------------------------------------------------------------- /App/uib/template/typeahead/typeahead-match.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /App/uib/template/typeahead/typeahead-popup.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /App/views/about.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 |
    About
    6 |
    7 | 8 |
    9 | 10 |
    11 | pinbored 12 |

    asdasdasd asdasd asd asd asdas d

    13 |
    14 | 15 |
    16 |
    ABOUT.
    17 |
    18 | 19 |
    20 | 21 |
    -------------------------------------------------------------------------------- /App/views/login.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 |
    5 | 6 | 27 | 28 |
    29 |
    30 |
    -------------------------------------------------------------------------------- /App/views/overview.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 | 6 |
    7 | 8 |
    Overview
    9 | 10 | 11 |
    12 | 14 | 18 | 23 |
    24 | 25 |
    26 | 27 | 32 | 33 | 34 |
    35 | 36 |
    37 | 38 |
    39 | 40 | 41 |
    42 | 43 | 44 |
    45 | 46 | 47 |
    48 | 49 | 50 |
    51 | 52 | 53 |
    54 |
    55 | 118 |
    119 |
    120 |
    121 | 122 | 123 |
    124 | 125 |
    126 | 127 |
      128 |
    • 131 |
      132 |
    • 133 |
    134 |
    135 | 136 |
    137 |
    {{data.bgMsg}}
    138 |
    139 | 140 |
    141 | 142 |
    -------------------------------------------------------------------------------- /App/views/partials/components/taginput.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    4 | 5 | 6 | 7 | 8 | 9 | 10 |
    11 | 12 |
    Press BACKSPACE again to delete the last tag.
    13 |
    -------------------------------------------------------------------------------- /App/views/partials/items/tagitem.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 4 |
    5 | 6 |
    7 | {{item.tagname}} 9 |
    10 | 11 |
    12 | {{item.occurrences}} 13 |
    14 | 15 |
    16 | 17 |
    18 |
    19 | 20 | 23 | 24 | 27 | 28 | 31 | 32 |
    33 |
    34 | 35 |
    36 |
    37 | 38 |
    39 | 40 |
    41 | 42 |
    43 |
    44 | 45 |
    46 |
    47 | 48 | 52 | 53 | 57 | 58 |
    59 |
    60 | 61 |
    62 |
    63 | 65 | 66 | 67 |
    68 |
    69 | 70 |
    71 |
    72 | 73 | 77 | 78 |
    79 |
    80 | 81 |
    82 | -------------------------------------------------------------------------------- /App/views/partials/mainnav.html: -------------------------------------------------------------------------------- 1 | 38 | -------------------------------------------------------------------------------- /App/views/partials/search/searchbar-buttons.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 4 | 5 | 6 | 7 |
    8 |
    -------------------------------------------------------------------------------- /App/views/partials/search/searchbar-extra-bookmarks.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 22 |
    23 |
    -------------------------------------------------------------------------------- /App/views/partials/search/searchbar-extra-tags.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 22 |
    23 |
    -------------------------------------------------------------------------------- /App/views/partials/search/searchbar-fulltext.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | 22 |
    23 |
    -------------------------------------------------------------------------------- /App/views/partials/search/searchbar-paging.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | 6 |
    7 |
    -------------------------------------------------------------------------------- /App/views/partials/search/searchbar-tags.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 |
    5 | 7 | 8 | 9 | 10 |
    11 |
    12 | {{config.tagFilterTypeText}} 13 |
    14 |
    15 |
    -------------------------------------------------------------------------------- /App/views/settings.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 |
    Settings
    6 |
    7 | 8 |
    9 | 10 |
    11 | - overview screen settings 12 |
    13 | 14 |
    15 | 16 |
    17 | 18 | 19 |
    20 | 21 |
    22 | 25 | 30 |
    31 |
    32 | 33 | 34 |
    35 | 36 |
    37 | 40 | 45 |
    46 |
    47 | 48 |
    49 | 50 |
    51 | 52 |
    53 | 54 |
    55 | 56 |
    57 |
    58 | 60 |
    61 |
    62 | 63 |
    64 | 65 |
    66 | 67 |
    68 | - tag screen settings 69 |
    70 | 71 |
    72 |
    APPLICATION SETTINGS.
    73 |
    74 | 75 |
    76 | 77 |
    -------------------------------------------------------------------------------- /App/views/tags.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 | 6 |
    7 |
    Tags
    8 | 9 |
    10 | 11 | 16 | 17 | 18 |
    19 | 20 |
    21 | 22 |
    23 | 24 | 25 |
    26 | 27 | 28 |
    29 | 30 | 31 |
    32 | 33 |
    34 | 35 | 36 |
    37 | 38 |
    39 |
    40 |
      41 | 42 |
    • 46 |
    47 |
    48 |
    49 | 50 |
    51 |
    NO TAGS FOUND.
    52 |
    53 | 54 |
    55 | 56 |
    -------------------------------------------------------------------------------- /App/views/tools.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 |
    5 | 6 |
    Tools
    7 | 8 |
    9 | 10 |
    11 | 12 |
    13 | 14 |
    15 |

    check for duplicates

    16 |
    17 | 19 |
    20 |
    21 | 22 | 23 |
    24 | 25 |
    26 | 27 |
    28 |

    duplicate bookmark names

    29 |
    30 | 31 | 32 |
      33 |
    • 36 |
      37 |
    • 38 |
    39 | 40 | 41 | 56 | 57 | 58 |
    59 |

    duplicate bookmark hrefs

    60 |
    61 | 62 | 63 |
      64 |
    • 66 |
      67 |

      {{item.description}}

      68 |

      {{item.href}}

      69 |

      {{item.extended}}

      70 |
      71 |
    • 72 |
    73 | 74 | 75 |
    76 |

    duplicate bookmark descriptions

    77 |
    78 | 79 | 80 |
      81 |
    • 83 |
      84 |

      {{item.description}}

      85 |

      {{item.href}}

      86 |

      {{item.extended}}

      87 |
      88 |
    • 89 |
    90 |
    91 | 92 |
    93 |
    NO DUPLICATES FOUND.
    94 |
    95 |
    96 | 97 |
    98 | 99 | -------------------------------------------------------------------------------- /CONTRIBUTE.md: -------------------------------------------------------------------------------- 1 | contribute / version bump 2 | ------------------------- 3 | 4 | **NEW VERSION RELEASE** 5 | 6 | * **1) Run testsuite** 7 | * ```grunt test``` (and apply volkswagen fixes where neccesary) 8 | 9 | * **2) Run and test nw /App** 10 | * ```grunt update``` 11 | * ```nw /App``` (check for obvious runtime bugs, issues) 12 | 13 | * **3) Run and test nw /App_release** 14 | * ```grunt build``` 15 | * ```nw /App_release``` (check for obvious runtime bugs, issues) 16 | 17 | * **4) Fire up Linux + Winblows virtual box machines** 18 | * ```git clone https://github.com/michahell/pinbored-nwjs.git``` (do a fresh git clone) 19 | * follow the project setup steps (to test fresh project setup steps), npm install etc. etc. 20 | * repeat the above steps for each OS target to test for OS specific quirks. 21 | * run ```grunt release-win``` or ```release-lin```. 22 | * test if the binaries work (navigate to folder and start executables). 23 | * zip the folders for each bitness OS target (x32 and x64) if applicable. 24 | * copy the binary zipfiles from the ```Release``` folder to main OS for easier upload later. 25 | 26 | * **5) Release on github** 27 | * first, update the package.json versions in ```/``` and in ```/App``` to the just closed milestone version. 28 | * create a new annotated tag: ```git tag -a -m "Pinbored-nwjs release version : ." 29 | * go to https://github.com/michahell/pinbored-nwjs/releases 30 | * draft a new release, select the newly created tag, add a link to the (not closed) version milestone. 31 | * upload the different OS target binaries 32 | * hit publish release! 33 | 34 | * **6) Close the version milestone and create a new one** 35 | * go to https://github.com/michahell/pinbored-nwjs/milestones/new 36 | * close the milestone, create a new one using this name generator: http://www.codenamegenerator.com/ 37 | * update the README.md roadmap section -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /Resources/pinbored-credits.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/Resources/pinbored-credits.html -------------------------------------------------------------------------------- /Resources/pinbored-icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/Resources/pinbored-icon.icns -------------------------------------------------------------------------------- /Resources/pinbored-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/Resources/pinbored-icon.png -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pinbored-webkit", 3 | "version": "0.3.3", 4 | "dependencies": { 5 | "angular": ">=1.4.9", 6 | "angular-animate": ">=1.2", 7 | "angular-bootstrap": ">=0.12.1", 8 | "angular-elastic": "~2.5.0", 9 | "angular-gridster": ">=0.13.2", 10 | "angular-sanitize": ">=1.2", 11 | "angular-ui-router": "~0.2.15", 12 | "animate.css": ">=3.1.1", 13 | "bootstrap": ">=3.1.1", 14 | "flat-ui": ">=2.2.0", 15 | "fui-angular": "~0.1.5", 16 | "json3": ">=3.3.1", 17 | "mousetrap": "~1.5.3", 18 | "ng-tags-input": ">=2.0.1", 19 | "ngDialog": "~0.4.0", 20 | "ngprogress": "~1.0.7", 21 | "ramda": "~0.17.1", 22 | "ui-router-extras": "~0.0.14", 23 | "underscore": "~1.8.3" 24 | }, 25 | "devDependencies": { 26 | "angular-mocks": ">=1" 27 | }, 28 | "resolutions": { 29 | "angular": "1.5.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | 2 | // temp set environment variable for node-webkit 3 | process.env.NODEWEBKIT_BIN = '/Applications/nwjs.app/Contents/MacOS/nwjs'; 4 | 5 | module.exports = function(config) { 6 | config.set({ 7 | 8 | basePath : './', 9 | 10 | files : [ 11 | 'App/bower_components_dist/jquery/dist/jquery.min.js', 12 | 'App/bower_components_dist/bootstrap/dist/js/bootstrap.min.js', 13 | 'App/bower_components_dist/underscore/underscore-min.js', 14 | 'App/bower_components_dist/json3/lib/json3.min.js', 15 | 'App/bower_components_dist/ramda/dist/ramda.min.js', 16 | 17 | 'App/bower_components_dist/angular/angular.min.js', 18 | 'App/bower_components_dist/angular-bootstrap/ui-bootstrap.min.js', 19 | 'App/bower_components_dist/angular-sanitize/angular-sanitize.min.js', 20 | 'App/bower_components_dist/angular-animate/angular-animate.min.js', 21 | 'App/bower_components_dist/angular-mocks/angular-mocks.js', 22 | 'App/bower_components_dist/angular-ui-router/release/angular-ui-router.min.js', 23 | 'App/bower_components_dist/ui-router-extras/release/modular/ct-ui-router-extras.core.min.js', 24 | 'App/bower_components_dist/ui-router-extras/release/modular/ct-ui-router-extras.sticky.min.js', 25 | 26 | 'App/bower_components_dist/angular-gridster/dist/angular-gridster.min.js', 27 | 'App/bower_components_dist/angular-elastic/elastic.js', 28 | 'App/bower_components_dist/ng-tags-input/ng-tags-input.min.js', 29 | 'App/bower_components_dist/flat-ui/dist/js/flat-ui.min.js', 30 | 'App/bower_components_dist/ngprogress/build/ngProgress.min.js', 31 | 'App/bower_components_dist/ngDialog/js/ngDialog.min.js', 32 | 'App/bower_components_dist/mousetrap/mousetrap.min.js', 33 | 34 | 'App/bower_components_dist/fui-angular/fui-template.js', 35 | 'App/bower_components_dist/fui-angular/fui-checkbox.js', 36 | 'App/bower_components_dist/fui-angular/fui-radio.js', 37 | 'App/bower_components_dist/fui-angular/fui-switch.js', 38 | 'App/bower_components_dist/fui-angular/fui-tpls.js', 39 | 40 | 'App/scripts/app.js', 41 | 'App/scripts/config/**/*.js', 42 | 'App/scripts/constants/**/*.js', 43 | 'App/scripts/controllers/**/*.js', 44 | 'App/scripts/directives/**/*.js', 45 | 'App/scripts/filters/**/*.js', 46 | 'App/scripts/services/**/*.js', 47 | 48 | 'App/scripts/tests/**/*.js' 49 | ], 50 | 51 | // autoWatch : true, 52 | 53 | frameworks: ['jasmine'], 54 | 55 | browsers : ['NodeWebkitWithCustomPath'], // 'NodeWebkit' 56 | 57 | customLaunchers: { 58 | 'NodeWebkitWithCustomPath': { 59 | base: 'NodeWebkit', 60 | // Remember to include 'node_modules' if you have some modules there 61 | paths: ['App/node_modules', 'node_modules'] 62 | } 63 | }, 64 | 65 | singleRun: true, 66 | 67 | reporters: ['mocha', 'coverage'], // 'nyan', 'progress', 'html' 68 | 69 | preprocessors: { 70 | // source files, that you wanna generate coverage for 71 | // do not include tests or libraries 72 | // (these files will be instrumented by Istanbul) 73 | 74 | 'App/scripts/config/**/*.js' : ['coverage'], 75 | 'App/scripts/constants/**/*.js' : ['coverage'], 76 | 'App/scripts/controllers/**/*.js' : ['coverage'], 77 | 'App/scripts/directives/**/*.js' : ['coverage'], 78 | 'App/scripts/filters/**/*.js' : ['coverage'], 79 | 'App/scripts/services/**/*.js' : ['coverage'], 80 | 'App/scripts/tests/**/*.js' : ['coverage'] 81 | }, 82 | 83 | // optionally, configure the reporter 84 | coverageReporter: { 85 | type : 'lcovonly', 86 | dir : 'coverage', 87 | subdir: '.', 88 | file: 'lcov.info' 89 | }, 90 | 91 | // htmlReporter: { 92 | // outputFile: 'karma.report.html' 93 | // } 94 | 95 | // logLevel: 'DEBUG' 96 | 97 | }); 98 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "Michahell", 4 | "email": "maggelo@gmail.com", 5 | "url": "http://www.powergeek.nl/" 6 | }, 7 | "name": "pinbored", 8 | "description": "a bookmark management app built around the Pinboard.in REST service.", 9 | "version": "0.3.4", 10 | "bugs": { 11 | "url": "https://github.com/michahell/pinbored-nwjs/issues", 12 | "email": "maggelo@gmail.com" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/michahell/pinbored-nwjs.git" 17 | }, 18 | "private": true, 19 | "devDependencies": { 20 | "grunt": "^0.4.5", 21 | "grunt-bowercopy": "^1.2.4", 22 | "grunt-contrib-clean": "^1.0.0", 23 | "grunt-contrib-copy": "^0.8.2", 24 | "grunt-contrib-cssmin": "^0.14.0", 25 | "grunt-contrib-uglify": "^0.11.1", 26 | "grunt-htmlclean": "^2.7.6", 27 | "grunt-karma": "^0.12.1", 28 | "grunt-nw-builder": "^2.0.0", 29 | "grunt-open": "^0.2.3", 30 | "grunt-preprocess": "^5.0.1", 31 | "grunt-purifycss": "^0.1.1", 32 | "grunt-shell": "^1.1.2", 33 | "install": "^0.4.4", 34 | "jasmine-core": "^2.4.1", 35 | "jshint": "^2.9.1", 36 | "karma": "^0.13.21", 37 | "karma-coverage": "^0.5.3", 38 | "karma-htmlfile-reporter": "^0.2.2", 39 | "karma-jasmine": "^0.3.7", 40 | "karma-mocha-reporter": "^1.1.5", 41 | "karma-nodewebkit-launcher": "0.0.12", 42 | "karma-nyan-reporter": "^0.2.3", 43 | "load-grunt-tasks": "^3.4.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sources/451574509.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/sources/451574509.jpg -------------------------------------------------------------------------------- /sources/bookmark-icon-1-614x460.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/sources/bookmark-icon-1-614x460.png -------------------------------------------------------------------------------- /sources/bookmark-icon-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/sources/bookmark-icon-3.png -------------------------------------------------------------------------------- /sources/pinbored-icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/sources/pinbored-icon.psd -------------------------------------------------------------------------------- /sources/pinbored-logo-github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/sources/pinbored-logo-github.png -------------------------------------------------------------------------------- /sources/pinbored-logo-github.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/sources/pinbored-logo-github.psd -------------------------------------------------------------------------------- /sources/pinbored-logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michahell/pinbored-nwjs/c55219f5cd97c96cd9c0ef7a1e7326cb7440c8da/sources/pinbored-logo.psd --------------------------------------------------------------------------------