├── .babelrc ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .idea ├── misc.xml ├── modules.xml └── vcs.xml ├── .npmignore ├── Designs ├── EG_compact.jpg ├── Logo │ ├── excited gem logo draft.ai │ ├── output │ │ ├── logo.png │ │ └── logo_Xwq_icon.ico │ └── references │ │ ├── 1images.jpg │ │ ├── 1url.jpg │ │ ├── 23976415-geometric-shape-gem-hexagon-shape.jpg │ │ ├── 2images.jpg │ │ ├── facet-crystal-gem-logo.jpg │ │ ├── images.jpg │ │ ├── imgres.jpg │ │ └── stock-vector-abstract-hexagonal-gem-logo-vector-illustration-isolated-icon-313572113.jpg ├── Promotion Design.afdesign ├── Screenshots │ ├── Large Tile.jpg │ ├── Marquee.jpg │ ├── main-filter.JPG │ ├── main-normal-smaller.jpg │ ├── main-normal.JPG │ ├── normal.jpg │ ├── promotion1.jpg │ └── simplified.jpg ├── new.afdesign └── new.jpg ├── LICENSE ├── README.md ├── completion.sh ├── excited-gem.sublime-project ├── index.html ├── manifest_partials ├── chrome.json ├── common.json └── firefox.json ├── package.json ├── params.json ├── post.css.config.js ├── src ├── fonts │ ├── fa-brands-400.eot │ ├── fa-brands-400.svg │ ├── fa-brands-400.ttf │ ├── fa-brands-400.woff │ ├── fa-brands-400.woff2 │ ├── fa-light-300.eot │ ├── fa-light-300.svg │ ├── fa-light-300.ttf │ ├── fa-light-300.woff │ ├── fa-light-300.woff2 │ ├── fa-regular-400.eot │ ├── fa-regular-400.svg │ ├── fa-regular-400.ttf │ ├── fa-regular-400.woff │ ├── fa-regular-400.woff2 │ ├── fa-solid-900.eot │ ├── fa-solid-900.svg │ ├── fa-solid-900.ttf │ ├── fa-solid-900.woff │ └── fa-solid-900.woff2 ├── images │ ├── arrange.svg │ ├── close-icon.svg │ ├── dev-logo.svg │ ├── info-icon.svg │ ├── logo.ico │ ├── logo.svg │ ├── pin-icon.svg │ ├── reload-icon.svg │ ├── search-icon.svg │ └── sound-icon.svg ├── import-export.html ├── logo.svg ├── manifest-loader.js ├── navigation.jade ├── options.ejs ├── options.jade ├── partials │ └── header.html ├── popup.html ├── query.html ├── scripts │ ├── ActiveTabs.js │ ├── ErrorBoundary.js │ ├── TabsApp.js │ ├── active-tabs-container.js │ ├── background.js │ ├── bootstrap │ │ ├── alert.js │ │ ├── button.js │ │ ├── carousel.js │ │ ├── collapse.js │ │ ├── dropdown.js │ │ ├── index.js │ │ ├── modal.js │ │ ├── popover.js │ │ ├── scrollspy.js │ │ ├── tab.js │ │ ├── tooltip.js │ │ └── util.js │ ├── components │ │ ├── Accordion │ │ │ └── TabsGroup │ │ │ │ ├── Tab │ │ │ │ ├── Tab.js │ │ │ │ └── index.js │ │ │ │ ├── TabsGroup.js │ │ │ │ └── index.js │ │ ├── Header │ │ │ └── Search │ │ │ │ ├── Search.js │ │ │ │ └── index.js │ │ ├── WindowSelector.js │ │ ├── browserActions.js │ │ ├── communications.js │ │ ├── general.js │ │ ├── getsetSessions.js │ │ ├── idle.js │ │ ├── readingList.js │ │ ├── search.js │ │ ├── tabSelection.js │ │ └── tabs.js │ ├── content.js │ ├── defaultPreferences.js │ ├── images │ │ ├── ui-icons_444444_256x240.png │ │ ├── ui-icons_555555_256x240.png │ │ ├── ui-icons_777620_256x240.png │ │ ├── ui-icons_777777_256x240.png │ │ ├── ui-icons_cc0000_256x240.png │ │ └── ui-icons_ffffff_256x240.png │ ├── options-container.js │ ├── page-detection.js │ ├── react-components │ │ ├── info-modal.js │ │ ├── navigation.rc.js │ │ ├── options.js │ │ └── session.js │ ├── registerServiceWorker.js │ ├── sessions-container.js │ ├── settings.js │ ├── vendor │ │ ├── bootstrap.js │ │ ├── jquery-ui.css │ │ ├── jquery-ui.js │ │ ├── jquery-ui.structure.css │ │ ├── jquery-ui.theme.css │ │ ├── jquery.min.js │ │ └── npm.js │ └── webfont.js ├── sessions.ejs ├── sessions.jade ├── styles │ ├── bootstrap.scss │ ├── bootstrap │ │ ├── _alert.scss │ │ ├── _badge.scss │ │ ├── _breadcrumb.scss │ │ ├── _button-group.scss │ │ ├── _buttons.scss │ │ ├── _card.scss │ │ ├── _carousel.scss │ │ ├── _close.scss │ │ ├── _code.scss │ │ ├── _custom-forms.scss │ │ ├── _dropdown.scss │ │ ├── _forms.scss │ │ ├── _functions.scss │ │ ├── _grid.scss │ │ ├── _images.scss │ │ ├── _input-group.scss │ │ ├── _jumbotron.scss │ │ ├── _list-group.scss │ │ ├── _media.scss │ │ ├── _mixins.scss │ │ ├── _modal.scss │ │ ├── _nav.scss │ │ ├── _navbar.scss │ │ ├── _pagination.scss │ │ ├── _popover.scss │ │ ├── _print.scss │ │ ├── _progress.scss │ │ ├── _reboot.scss │ │ ├── _root.scss │ │ ├── _tables.scss │ │ ├── _tooltip.scss │ │ ├── _transitions.scss │ │ ├── _type.scss │ │ ├── _utilities.scss │ │ ├── _variables.scss │ │ ├── bootstrap-grid.scss │ │ ├── bootstrap-reboot.scss │ │ ├── bootstrap.scss │ │ ├── mixins │ │ │ ├── _alert.scss │ │ │ ├── _background-variant.scss │ │ │ ├── _badge.scss │ │ │ ├── _border-radius.scss │ │ │ ├── _box-shadow.scss │ │ │ ├── _breakpoints.scss │ │ │ ├── _buttons.scss │ │ │ ├── _caret.scss │ │ │ ├── _clearfix.scss │ │ │ ├── _float.scss │ │ │ ├── _forms.scss │ │ │ ├── _gradients.scss │ │ │ ├── _grid-framework.scss │ │ │ ├── _grid.scss │ │ │ ├── _hover.scss │ │ │ ├── _image.scss │ │ │ ├── _list-group.scss │ │ │ ├── _lists.scss │ │ │ ├── _nav-divider.scss │ │ │ ├── _pagination.scss │ │ │ ├── _reset-text.scss │ │ │ ├── _resize.scss │ │ │ ├── _screen-reader.scss │ │ │ ├── _size.scss │ │ │ ├── _table-row.scss │ │ │ ├── _text-emphasis.scss │ │ │ ├── _text-hide.scss │ │ │ ├── _text-truncate.scss │ │ │ ├── _transition.scss │ │ │ └── _visibility.scss │ │ └── utilities │ │ │ ├── _align.scss │ │ │ ├── _background.scss │ │ │ ├── _borders.scss │ │ │ ├── _clearfix.scss │ │ │ ├── _display.scss │ │ │ ├── _embed.scss │ │ │ ├── _flex.scss │ │ │ ├── _float.scss │ │ │ ├── _position.scss │ │ │ ├── _screenreaders.scss │ │ │ ├── _shadows.scss │ │ │ ├── _sizing.scss │ │ │ ├── _spacing.scss │ │ │ ├── _text.scss │ │ │ └── _visibility.scss │ ├── components │ │ ├── _aside.scss │ │ ├── _buttons.scss │ │ ├── _forms.scss │ │ ├── _generics.scss │ │ ├── _reset.scss │ │ ├── _search.scss │ │ ├── _selectable.scss │ │ ├── _tab.scss │ │ └── _tabsgroup.scss │ ├── eg.scss │ ├── fontawesome5.scss │ ├── fontawesome5 │ │ ├── _animated.scss │ │ ├── _bordered-pulled.scss │ │ ├── _core.scss │ │ ├── _fixed-width.scss │ │ ├── _larger.scss │ │ ├── _list.scss │ │ ├── _mixins.scss │ │ ├── _rotated-flipped.scss │ │ ├── _screen-reader.scss │ │ ├── _stacked.scss │ │ ├── _variables.scss │ │ ├── fa-brands.scss │ │ ├── fa-light.scss │ │ ├── fa-regular.scss │ │ ├── fa-solid.scss │ │ └── fontawesome.scss │ ├── github │ │ ├── github-light.css │ │ ├── normalize.css │ │ └── stylesheet.css │ └── webfonts │ │ ├── fa-brands-400.eot │ │ ├── fa-brands-400.svg │ │ ├── fa-brands-400.ttf │ │ ├── fa-brands-400.woff │ │ ├── fa-brands-400.woff2 │ │ ├── fa-light-300.eot │ │ ├── fa-light-300.svg │ │ ├── fa-light-300.ttf │ │ ├── fa-light-300.woff │ │ ├── fa-light-300.woff2 │ │ ├── fa-regular-400.eot │ │ ├── fa-regular-400.svg │ │ ├── fa-regular-400.ttf │ │ ├── fa-regular-400.woff │ │ ├── fa-regular-400.woff2 │ │ ├── fa-solid-900.eot │ │ ├── fa-solid-900.svg │ │ ├── fa-solid-900.ttf │ │ ├── fa-solid-900.woff │ │ └── fa-solid-900.woff2 ├── tabs.ejs └── tabs.jade ├── utils ├── env.js ├── manifest.generator.js ├── prepare.js ├── production.js └── webserver.js ├── webpack.config.js └── webpack.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "stage-3", ["env", { "loose": true, "browsers": "last 1 Chrome version" }], "react" 4 | ], 5 | "env": { 6 | "development": { 7 | "presets": ["stage-3", "env", "react-hot"] 8 | }, 9 | "production": { 10 | "presets": ["stage-3", "env", "react"] 11 | } 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /.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 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["prettier", "prettier/react"], 3 | "parser": "babel-eslint", 4 | "parserOptions": { 5 | "ecmaVersion": 8, 6 | "ecmaFeatures": { 7 | "experimentalObjectRestSpread": true, 8 | "impliedStrict": true, 9 | "classes": true 10 | } 11 | }, 12 | "env": { 13 | "browser": true, 14 | "node": true, 15 | "jquery": true, 16 | "jest": true 17 | }, 18 | "rules": { 19 | "no-debugger": 0, 20 | "no-unused-vars": [ 21 | 1, 22 | { 23 | "argsIgnorePattern": "res|next|^err" 24 | } 25 | ], 26 | "arrow-body-style": [2, "as-needed"], 27 | "no-unused-expressions": [ 28 | 2, 29 | { 30 | "allowTaggedTemplates": true 31 | } 32 | ], 33 | "no-param-reassign": [ 34 | 2, 35 | { 36 | "props": false 37 | } 38 | ], 39 | "no-console": 0, 40 | "import/prefer-default-export": 0, 41 | "import": 0, 42 | "func-names": 0, 43 | "space-before-function-paren": 0, 44 | "comma-dangle": 0, 45 | "max-len": 0, 46 | "import/extensions": 0, 47 | "no-underscore-dangle": 0, 48 | "consistent-return": 0, 49 | "react/display-name": 1, 50 | "react/react-in-jsx-scope": 0, 51 | "react/prefer-stateless-function": 0, 52 | "react/forbid-prop-types": 0, 53 | "react/no-unescaped-entities": 0, 54 | "jsx-a11y/accessible-emoji": 0, 55 | "react/jsx-filename-extension": [ 56 | 1, 57 | { 58 | "extensions": [".js", ".jsx"] 59 | } 60 | ], 61 | "radix": 0, 62 | "no-shadow": [ 63 | 2, 64 | { 65 | "hoist": "all", 66 | "allow": ["resolve", "reject", "done", "next", "err", "error"] 67 | } 68 | ], 69 | "quotes": [ 70 | 2, 71 | "single", 72 | { 73 | "avoidEscape": true, 74 | "allowTemplateLiterals": true 75 | } 76 | ], 77 | "prettier/prettier": [ 78 | "error", 79 | { 80 | "trailingComma": "es5", 81 | "singleQuote": true, 82 | "printWidth": 120 83 | } 84 | ], 85 | "jsx-a11y/href-no-hash": "off", 86 | "jsx-a11y/anchor-is-valid": [ 87 | "warn", 88 | { 89 | "aspects": ["invalidHref"] 90 | } 91 | ] 92 | }, 93 | "plugins": [ 94 | "prettier" 95 | ] 96 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | $RECYCLE.BIN/ 2 | *.cache 3 | *.csv 4 | *.dat 5 | *.gz 6 | *.log 7 | *.log 8 | *.out 9 | *.pid 10 | *.seed 11 | ./js/*.js 12 | ._* 13 | .AppleDouble 14 | .DS_Store 15 | .DS_STORE 16 | .LSOverride 17 | .remote-sync.json 18 | .sass-cache 19 | .Spotlight-V100 20 | .Trashes 21 | .vscode/launch.json 22 | .vscode/settings.json 23 | /css 24 | /js/*.js 25 | assets/ 26 | bower_components/ 27 | build/ 28 | certs/key.pem 29 | commonjs/ 30 | Desktop.ini 31 | dist/ 32 | thumbs.db 33 | excited-gem.sublime-workspace 34 | Icon 35 | lib-cov 36 | logs 37 | node_modules 38 | npm-debug.log 39 | pids 40 | results 41 | src/components 42 | Thumbs.db 43 | .history/ 44 | New folder/ 45 | .idea/workspace.xml 46 | .idea/excited-gem.iml 47 | .vscode/extensions.json 48 | utils/.npmrc 49 | package-lock.json 50 | firefox/ 51 | chrome/ 52 | .idea/watcherTasks.xml 53 | build.zip 54 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .remote-sync.json 2 | .DS_Store 3 | .DS_STORE 4 | node_modules 5 | -------------------------------------------------------------------------------- /Designs/EG_compact.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/EG_compact.jpg -------------------------------------------------------------------------------- /Designs/Logo/excited gem logo draft.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/excited gem logo draft.ai -------------------------------------------------------------------------------- /Designs/Logo/output/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/output/logo.png -------------------------------------------------------------------------------- /Designs/Logo/output/logo_Xwq_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/output/logo_Xwq_icon.ico -------------------------------------------------------------------------------- /Designs/Logo/references/1images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/1images.jpg -------------------------------------------------------------------------------- /Designs/Logo/references/1url.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/1url.jpg -------------------------------------------------------------------------------- /Designs/Logo/references/23976415-geometric-shape-gem-hexagon-shape.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/23976415-geometric-shape-gem-hexagon-shape.jpg -------------------------------------------------------------------------------- /Designs/Logo/references/2images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/2images.jpg -------------------------------------------------------------------------------- /Designs/Logo/references/facet-crystal-gem-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/facet-crystal-gem-logo.jpg -------------------------------------------------------------------------------- /Designs/Logo/references/images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/images.jpg -------------------------------------------------------------------------------- /Designs/Logo/references/imgres.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/imgres.jpg -------------------------------------------------------------------------------- /Designs/Logo/references/stock-vector-abstract-hexagonal-gem-logo-vector-illustration-isolated-icon-313572113.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Logo/references/stock-vector-abstract-hexagonal-gem-logo-vector-illustration-isolated-icon-313572113.jpg -------------------------------------------------------------------------------- /Designs/Promotion Design.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Promotion Design.afdesign -------------------------------------------------------------------------------- /Designs/Screenshots/Large Tile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/Large Tile.jpg -------------------------------------------------------------------------------- /Designs/Screenshots/Marquee.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/Marquee.jpg -------------------------------------------------------------------------------- /Designs/Screenshots/main-filter.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/main-filter.JPG -------------------------------------------------------------------------------- /Designs/Screenshots/main-normal-smaller.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/main-normal-smaller.jpg -------------------------------------------------------------------------------- /Designs/Screenshots/main-normal.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/main-normal.JPG -------------------------------------------------------------------------------- /Designs/Screenshots/normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/normal.jpg -------------------------------------------------------------------------------- /Designs/Screenshots/promotion1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/promotion1.jpg -------------------------------------------------------------------------------- /Designs/Screenshots/simplified.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/Screenshots/simplified.jpg -------------------------------------------------------------------------------- /Designs/new.afdesign: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/new.afdesign -------------------------------------------------------------------------------- /Designs/new.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/Designs/new.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Big thanks to [BrowserStack](http://browserstack.com/) for the support. Because Excited gem is an extension for browsers, there was need to test the UI and features in multiple browsers across multiple devices and OS. There is where [BrowserStack](http://browserstack.com/) comes in. I am using [BrowserStack](http://browserstack.com/) for to test my extension on different browsers. 2 | # Excited Gem 3 | 4 | This repo is a quest to improve the famous extension for Chrome "OneTab" with respect to UI and UX along with some more useful options for regular Chrome/Firefox users and developers/programmers. 5 | 6 | ## Idea 7 | The thought to make such a thing happened when I faced few problems while using Chrome browser. I love to read and research a lot. And while doing that I end opening more than 50 tabs. Mostly 60 or 70. It is then when I start having problem of managing my tabs. With so many tabs stacked up, it was hard to know which tab was which. Sometimes I accidently closed a tab in try to select it. 8 | 9 | I could have gone with some simple solutions like move all my opened tabs to bookmarks and open them later when need it. Then I found an nice Chrome extension "One Tab". It was doing a great job. In fact part of the reason and inspiration to make this project came from that extension. 10 | 11 | So I decided to make something useful and also learn something new while making it. That is how I started building it and learned quite a bit about Javascript, Chrome Extension API, ReactJS and Typescript. 12 | 13 | 14 | ## Visuals 15 | ### Main 16 | In the Following screen you can see all the tabs that have been opened in the current browser window. The Active Tabs list show you not only the currently opened tabs but also their attributes like whether it is pinned or not, whether it is audible or not. 17 | You can make a tab pinned or mute a tab, or go to a tab by clicking on its link(name). 18 | 19 | ![Normal](./Designs/Screenshots/main-normal.JPG) 20 | 21 | The Active Tabs list keep changing , every time the tabs are either moved , removed or created, pinned or muted. 22 | 23 | The total number of tabs for current window is shown on the extension icon (top right next to address bar). 24 | 25 | ### Filtering 26 | 27 | ![Filtering](./Designs/Screenshots/main-filter.JPG) 28 | 29 | Currently this extension support two types of filtering for Active Tabs. 30 | 1. Normal (String/text search) 31 | 2. Regex/Regular Expressions 32 | 33 | The filtering is case Insensitive for now. But I shall soon add option to quickly toggle that. 34 | 35 | For now that was it. Got of future plans for this project. Shall keep you updated. 36 | 37 | from Pakistan with LOVE. 38 | -------------------------------------------------------------------------------- /completion.sh: -------------------------------------------------------------------------------- 1 | ###-begin-npm-completion-### 2 | # 3 | # npm command completion script 4 | # 5 | # Installation: npm completion >> ~/.bashrc (or ~/.zshrc) 6 | # Or, maybe: npm completion > /usr/local/etc/bash_completion.d/npm 7 | # 8 | 9 | if type complete &>/dev/null; then 10 | _npm_completion () { 11 | local words cword 12 | if type _get_comp_words_by_ref &>/dev/null; then 13 | _get_comp_words_by_ref -n = -n @ -n : -w words -i cword 14 | else 15 | cword="$COMP_CWORD" 16 | words=("${COMP_WORDS[@]}") 17 | fi 18 | 19 | local si="$IFS" 20 | IFS=$'\n' COMPREPLY=($(COMP_CWORD="$cword" \ 21 | COMP_LINE="$COMP_LINE" \ 22 | COMP_POINT="$COMP_POINT" \ 23 | npm completion -- "${words[@]}" \ 24 | 2>/dev/null)) || return $? 25 | IFS="$si" 26 | if type __ltrim_colon_completions &>/dev/null; then 27 | __ltrim_colon_completions "${words[cword]}" 28 | fi 29 | } 30 | complete -o default -F _npm_completion npm 31 | elif type compdef &>/dev/null; then 32 | _npm_completion() { 33 | local si=$IFS 34 | compadd -- $(COMP_CWORD=$((CURRENT-1)) \ 35 | COMP_LINE=$BUFFER \ 36 | COMP_POINT=0 \ 37 | npm completion -- "${words[@]}" \ 38 | 2>/dev/null) 39 | IFS=$si 40 | } 41 | compdef _npm_completion npm 42 | elif type compctl &>/dev/null; then 43 | _npm_completion () { 44 | local cword line point words si 45 | read -Ac words 46 | read -cn cword 47 | let cword-=1 48 | read -l line 49 | read -ln point 50 | si="$IFS" 51 | IFS=$'\n' reply=($(COMP_CWORD="$cword" \ 52 | COMP_LINE="$line" \ 53 | COMP_POINT="$point" \ 54 | npm completion -- "${words[@]}" \ 55 | 2>/dev/null)) || return $? 56 | IFS="$si" 57 | } 58 | compctl -K _npm_completion npm 59 | fi 60 | ###-end-npm-completion-### 61 | -------------------------------------------------------------------------------- /excited-gem.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "folder_exclude_patterns": 6 | [ 7 | ".vscode", 8 | "stylesheets", 9 | "Designs", 10 | "certs", 11 | "node_modules" 12 | ], 13 | "path": "." 14 | }, 15 | { 16 | "path": "D:/xampp/htdocs/my/excited-gem" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /manifest_partials/chrome.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage_url": "http://path/to/homepage", 3 | "minimum_chrome_version": "versionString", 4 | "omnibox": { 5 | "keyword": "aString" 6 | }, 7 | "options_ui": { 8 | "page": "options.html", 9 | "open_in_tab": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /manifest_partials/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "background": { 3 | "scripts": [ 4 | "js/background.js" 5 | ] 6 | }, 7 | "commands": { 8 | "execute_browser_action": { 9 | "description": "Display Excited Gem Tabs Page", 10 | "suggested_key": { 11 | "windows": "Ctrl+Shift+X" 12 | } 13 | } 14 | }, 15 | "permissions": [ 16 | "tabs", 17 | "idle", 18 | "", 19 | "contextMenus", 20 | "storage", 21 | "notifications" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /manifest_partials/firefox.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "excited-gem", 3 | "title": "Excited Gem", 4 | "version": "0.9.200", 5 | "description": "A tool to manage your tabs and other browser related features.", 6 | "homepage": "https://picwellwisher12pk.github.io/onetab-advanced/", 7 | "bugs": "{}", 8 | 9 | "logoimage": "images/logo.svg", 10 | "license": "GNU 3.0", 11 | "author": "Amir Hameed", 12 | "client": { 13 | "chrome": "chrome", 14 | "firefox": "browser" 15 | }, 16 | 17 | "browser": { 18 | "./dist/index.js": "./firefox/tabs.js" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/picwellwisher12pk/onetab-advanced.git" 23 | }, 24 | "scripts": { 25 | "build": "node utils/production.js NODE_ENV=development browserClient=firefox", 26 | "start": "SET DEBUG=activetabs&& node utils/webserver.js NODE_ENV=development browserClient=firefox", 27 | "firefoxd": "SET Client=browser & npm run start", 28 | "chromed": "npm run start --env.CLIENT=chrome", 29 | "firefoxp": "SET NODE_ENV=production& SET BROWSER_CLIENT=firefox& node utils/production.js", 30 | "chromep": "SET NODE_ENV=production& SET BROWSER_CLIENT=chrome& node utils/production.js", 31 | "mount": "cd firefox & web-ext run --firefox=firefoxdeveloperedition", 32 | "packf": "cd firefox & web-ext build" 33 | }, 34 | "quokka": { 35 | "babel": true, 36 | "react": true, 37 | "es6": true 38 | }, 39 | "dependencies": { 40 | "@babel/polyfill": "^7.0.0", 41 | "babel-eslint": "^8.2.6", 42 | "bootstrap": "^4.1.3", 43 | "console.log": "^0.1.3", 44 | "debug": "^4.1.0", 45 | "eslint": "^4.19.1", 46 | "eslint-plugin-prettier": "^2.7.0", 47 | "jquery": "^3.3.1", 48 | "prop-types": "^15.6.2", 49 | "react": "^16.6.3", 50 | "react-custom-scrollbars": "^4.2.1", 51 | "react-dom": "^16.6.0" 52 | }, 53 | "devDependencies": { 54 | "@babel/preset-env": "^7.1.0", 55 | "autoprefixer": "^8.6.5", 56 | "babel-core": "^6.26.3", 57 | "babel-loader": "^7.1.5", 58 | "babel-preset-env": "^1.7.0", 59 | "babel-preset-react": "^6.16.0", 60 | "babel-preset-react-hmre": "^1.1.1", 61 | "babel-preset-react-hot": "^1.0.5", 62 | "babel-preset-stage-3": "^6.24.1", 63 | "css-loader": "^0.25.0", 64 | "ejs-loader": "^0.3.3", 65 | "eslint-config-prettier": "^2.10.0", 66 | "extract-text-webpack-plugin": "^3.0.2", 67 | "file-loader": "^0.11.2", 68 | "fs-extra": "^0.30.0", 69 | "html-loader": "^0.4.5", 70 | "html-webpack-plugin": "3.1.0", 71 | "jest": "^22.4.4", 72 | "node-sass": "^4.10.0", 73 | "popper.js": "^1.14.4", 74 | "postcss-cli": "^5.0.1", 75 | "postcss-loader": "^3.0.0", 76 | "precss": "^3.1.2", 77 | "prettier": "1.11.1", 78 | "pug-load": "^2.0.11", 79 | "pug-loader": "^2.4.0", 80 | "react-devtools": "^3.4.2", 81 | "react-hot-loader": "^4.3.12", 82 | "react-transition-group": "^2.5.0", 83 | "sass-loader": "^7.1.0", 84 | "style-loader": "^0.13.0", 85 | "webextension-polyfill": "^0.3.1", 86 | "webpack": "3.6.0", 87 | "webpack-dev-server": "^2.11.3", 88 | "webpackbar": "^1.5.1", 89 | "write-file-webpack-plugin": "3.4.2" 90 | }, 91 | "sideEffects": false, 92 | "lint-staged": { 93 | "*.test.tsx": [ 94 | "jest" 95 | ], 96 | "*.{js,tsx,ts}": [ 97 | "prettier --single-quote --trailing-comma es5 --write", 98 | "eslint", 99 | "git add" 100 | ] 101 | }, 102 | "applications": { 103 | "gecko": { 104 | "id": "{daf44bf7-a45e-4450-979c-91cf07434c3d}" 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /params.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Excited Gem", 3 | "tagline": "A tool to manage your tabs and other browser related features.", 4 | "body": "# Excited Gem\r\n\r\nThis repo is a quest to improve the famous extension for Chrome \"OneTab\" with respect to UI and UX along with some more useful options for regular Chrome users and developers/programmers.\r\n\r\n## Idea\r\nThe thought to make such a thing happened when I faced few problems while using Chrome browser. I love to read and research a lot. And while doing that I end opening more than 50 tabs. Mostly 60 or 70. It is then when I start having problem of managing my tabs. With so many tabs stacked up, it was hard to know which tab was which. Sometimes I accidently closed a tab in try to select it.\r\n\r\nI could have gone with some simple solutions like move all my opened tabs to bookmarks and open them later when need it. Then I found an nice Chrome extension \"One Tab\". It was doing a great job. In fact part of the reason and inspiration to make this project came from that extension.\r\n\r\nSo I decided to make something useful and also learn something new while making it. That is how I started building it and learned quite a bit about Javascript, Chrome Extension API, ReactJS and Typescript.\r\n\r\n\r\n## Visuals\r\n### Main\r\nIn the Following screen you can see all the tabs that have been opened in the current browser window. The Active Tabs list show you not only the currently opened tabs but also their attributes like whether it is pinned or not, whether it is audible or not.\r\nYou can make a tab pinned or mute a tab, or go to a tab by clicking on its link(name).\r\n![Normal](./Designs/Screenshots/main-normal.JPG) \r\n\r\nThe Active Tabs list keep changing , every time the tabs are either moved , removed or created, pinned or muted.\r\n\r\nThe total number of tabs for current window is shown on the extension icon (top right next to address bar).\r\n\r\n### Filtering\r\n![Filtering](./Designs/Screenshots/main-filter.JPG)\r\nCurrently this extension support two types of filtering for Active Tabs. \r\n1. Normal (String/text search)\r\n2. Regex/Regular Expressions\r\n\r\nThe filtering is case Insensitive for now. But I shall soon add option to quickly toggle that.\r\n\r\nFor now that was it. Got of future plans for this project. Shall keep you updated.\r\n\r\nfrom Pakistan with LOVE.\r\n", 5 | "note": "Don't delete this file! It's used internally to help with page regeneration." 6 | } 7 | -------------------------------------------------------------------------------- /post.css.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // module.exports = (ctx) => ({ 4 | // map: ctx.file.dirname.includes('examples') ? false : { 5 | // inline: false, 6 | // annotation: true, 7 | // sourcesContent: true 8 | // }, 9 | // plugins: { 10 | // autoprefixer: { 11 | // cascade: false 12 | // } 13 | // } 14 | // }) 15 | module.exports = { 16 | parser: 'sugarss', 17 | plugins: { 18 | 'postcss-import': {}, 19 | 'postcss-preset-env': {}, 20 | 'cssnano': {} 21 | } 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /src/fonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-brands-400.eot -------------------------------------------------------------------------------- /src/fonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /src/fonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-brands-400.woff -------------------------------------------------------------------------------- /src/fonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /src/fonts/fa-light-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-light-300.eot -------------------------------------------------------------------------------- /src/fonts/fa-light-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-light-300.ttf -------------------------------------------------------------------------------- /src/fonts/fa-light-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-light-300.woff -------------------------------------------------------------------------------- /src/fonts/fa-light-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-light-300.woff2 -------------------------------------------------------------------------------- /src/fonts/fa-regular-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-regular-400.eot -------------------------------------------------------------------------------- /src/fonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /src/fonts/fa-regular-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-regular-400.woff -------------------------------------------------------------------------------- /src/fonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /src/fonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-solid-900.eot -------------------------------------------------------------------------------- /src/fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /src/fonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-solid-900.woff -------------------------------------------------------------------------------- /src/fonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/fonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /src/images/arrange.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/close-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/dev-logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/info-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/images/logo.ico -------------------------------------------------------------------------------- /src/images/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/pin-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/reload-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/search-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/sound-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/import-export.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | OneTab 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/manifest-loader.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | // A loader to transform a partial manifest.json file into a complete 4 | // manifest.json file by adding entries from an NPM package.json. 5 | module.exports = function(source) { 6 | const pkg = JSON.parse(fs.readFileSync('./manifest.json')); 7 | const merged = Object.assign({}, JSON.parse(source), { 8 | name: pkg.name, 9 | description: pkg.description, 10 | version: pkg.version, 11 | author: pkg.author, 12 | homepage_url: pkg.homepage, 13 | }); 14 | const mergedJson = JSON.stringify(merged); 15 | // In Webpack, loaders ultimately produce JavaScript. In order to produce 16 | // another file type (like JSON), it needs to be emitted separately. 17 | this.emitFile('manifest.json', mergedJson); 18 | // Return the processed JSON to be used by the next item in the loader chain. 19 | return mergedJson; 20 | }; 21 | -------------------------------------------------------------------------------- /src/navigation.jade: -------------------------------------------------------------------------------- 1 | nav.navbar.navbar-default.navbar-fixed-top 2 | .container-fluid 3 | // Brand and toggle get grouped for better mobile display 4 | .navbar-header 5 | button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#bs-example-navbar-collapse-1', aria-expanded='false') 6 | span.sr-only Toggle navigation 7 | span.icon-bar 8 | span.icon-bar 9 | span.icon-bar 10 | a.navbar-brand(href='#') Excited Gem 11 | // Collect the nav links, forms, and other content for toggling 12 | #bs-example-navbar-collapse-1.collapse.navbar-collapse 13 | ul.nav.navbar-nav 14 | li.tabs 15 | a#go-to-tabs(href='excited_gem_tabs.html') 16 | | Tabs 17 | span.sr-only (current) 18 | li.sessions 19 | a(href="sessions.html") 20 | | Sessions 21 | ul.nav.navbar-nav.navbar-right 22 | li.options 23 | a#go-to-options(href="options.html").btn Options 24 | -------------------------------------------------------------------------------- /src/options.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title My Test Extension Options 5 | style. 6 | body: { 7 | padding: 10px; 8 | } 9 | link(rel='stylesheet', href='css/bootstrap.css') 10 | link(rel='stylesheet', href='css/font-awesome.css') 11 | link(href='css/onetab.css', rel='stylesheet', type='text/css') 12 | script(src='js/jquery.min.js') 13 | script(src='js/bootstrap.js') 14 | script(src='js/content.js') 15 | body.eg 16 | include _navigation 17 | .container 18 | h1 Options 19 | #status.alert.alert-success(role='alert', style='display: none;') 20 | button.close(type='button', data-dismiss='alert', aria-label='Close') 21 | span(aria-hidden='true') × 22 | span 23 | .cf.clearfix(style='margin-bottom: 15px;') 24 | button#save.btn.btn-success.btn-lg.pull-right(type='button') 25 | span.glyphicon.glyphicon-floppy-disk(aria-hidden='true') 26 | | Save 27 | .row 28 | .col-md-6 29 | .panel.panel-default 30 | .panel-heading 31 | h3.panel-title Search/Filter 32 | .panel-body 33 | form 34 | .form-group 35 | label(for='filter-type-option-id') Filter Type: 36 | select#filter-type-option-id.form-control 37 | option(value='normal') Normal 38 | option(value='regex') Regular Expression 39 | .checkbox 40 | label 41 | input#filterCase-option-id(type='checkbox') 42 | | Case Insensitive? 43 | // 44 | .col-md-6 45 | .panel.panel-default 46 | .panel-heading 47 | h3.panel-title Tabs 48 | .panel-body 49 | form 50 | .form-group 51 | label(for='sort-animation-option-id') Sort Tabs Animation 52 | .input-group 53 | input#sort-animation-option-id.form-control(type='number', value='250', min='0') 54 | span.input-group-addon milliseconds 55 | span 56 | | ( Time in milliseconds. 0 means no very quick. higher numbers means slower animation) 57 | // 58 | #status 59 | script(src='js/options.js') 60 | -------------------------------------------------------------------------------- /src/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OneTab 6 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |

Popup

43 | 46 |
47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/scripts/ErrorBoundary.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | export default class ErrorBoundary extends React.Component { 3 | constructor(props) { 4 | super(props); 5 | this.state = { hasError: false }; 6 | } 7 | 8 | static getDerivedStateFromError(error) { 9 | // Update state so the next render will show the fallback UI. 10 | return { hasError: true }; 11 | } 12 | 13 | componentDidCatch(error, info) { 14 | // You can also log the error to an error reporting service 15 | console.log(error, info); 16 | } 17 | 18 | render() { 19 | if (this.state.hasError) { 20 | // You can render any custom fallback UI 21 | return

Something went wrong.

; 22 | } 23 | 24 | return this.props.children; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/scripts/TabsApp.js: -------------------------------------------------------------------------------- 1 | import 'react-devtools'; 2 | // var browser = require('./browser-polyfill.js'); 3 | var browser = require('webextension-polyfill'); 4 | import React from 'react'; 5 | import { render } from 'react-dom'; 6 | import ActiveTabs from './ActiveTabs'; 7 | import { getTabs } from './components/browserActions'; 8 | 9 | function onRemoved(tabId, removeInfo) { 10 | getTabs().then(tabs => { 11 | window.tabs = tabs.filter(tab => tab.id != tabId); 12 | window.activeTabs.setState({ tabs: window.tabs }); 13 | }); 14 | } 15 | getTabs().then(tabs => { 16 | window.tabs = tabs; 17 | }); 18 | 19 | browser.tabs.onRemoved.addListener(onRemoved); 20 | browser.tabs.onDetached.addListener(onRemoved); 21 | 22 | browser.tabs.onCreated.addListener(() => { 23 | getTabs().then(tabs => { 24 | // console.log('onCreated:', tabs); 25 | window.tabs = tabs; 26 | window.activeTabs.setState({ tabs }); 27 | }); 28 | }); 29 | browser.tabs.onAttached.addListener(() => { 30 | getTabs().then(tabs => { 31 | window.tabs = tabs; 32 | window.activeTabs.setState({ tabs }); 33 | }); 34 | }); 35 | browser.tabs.onUpdated.addListener((tabId, changeInfo, tabInfo) => { 36 | getTabs().then(tabs => { 37 | window.tabs = tabs; 38 | window.activeTabs.setState({ tabs }); 39 | }); 40 | }); 41 | 42 | browser.storage.local.get('preferences').then(result => { 43 | // console.log("Root",window.tabs,result.preferences,NODE_ENV); 44 | window.activeTabs = render( 45 | , 46 | document.querySelector('#root') 47 | ); 48 | // console.log('tabapp', result.preferences); 49 | }); 50 | -------------------------------------------------------------------------------- /src/scripts/active-tabs-container.js: -------------------------------------------------------------------------------- 1 | let env = require('../../utils/env'); 2 | let client = env.browserClient == 'firefox' ? browser : chrome; 3 | window.homepageOpened = null; 4 | 5 | 6 | 7 | //Scripts and Modules 8 | //Vendors 9 | // const $ = (jQuery = require('jquery')); 10 | const bootstrap = require('bootstrap'); 11 | 12 | // import offCanvasNav from "./vendor/codedrops/sidebarEffects"; 13 | import React from 'react'; 14 | import 'react-devtools'; 15 | import ReactDOM from 'react-dom'; 16 | 17 | //JS libraries 18 | // import packagedAndBroadcast from './components/communications.js'; 19 | import {updateTabs,getTabs,setTabCountInBadge} from './components/browserActions'; 20 | import * as general from './components/general.js'; 21 | // import selectTab from './components/tabSelection.js'; 22 | // require("./components/general.js"); 23 | 24 | // React Components 25 | // import Navigation from './react-components/navigation.rc.js'; 26 | import TabsGroup from './components/Accordion/TabsGroup'; 27 | // import InfoModal from './react-components/info-modal.js'; 28 | // import { getReadingLists, setReadingLists } from "./components/readingList.jsx"; 29 | 30 | //Styles 31 | // import "../styles/bootstrap/functions"; 32 | // import "../styles/bootstrap/variables"; 33 | // import '../styles/bootstrap.scss'; 34 | import '../styles/fontawesome5/fa-solid.scss'; 35 | import '../styles/fontawesome5.scss'; 36 | import '../styles/eg.scss'; 37 | // import "../styles/codedrops/component.scss"; 38 | 39 | //Images 40 | import '../images/logo.svg'; 41 | import '../images/dev-logo.svg'; 42 | import '../images/arrange.svg'; 43 | import '../images/close-icon.svg'; 44 | import '../images/info-icon.svg'; 45 | import '../images/pin-icon.svg'; 46 | import '../images/reload-icon.svg'; 47 | import '../images/search-icon.svg'; 48 | import '../images/sound-icon.svg'; 49 | 50 | window.tabsList = []; 51 | window.tabsgroup = null; 52 | const menu = document.querySelector(".context-menu"); 53 | let menuVisible = false; 54 | const toggleMenu = command => { 55 | menu.style.display = command === "show" ? "block" : "none"; 56 | menuVisible = !menuVisible; 57 | }; 58 | window.addEventListener("click", e => { 59 | if(menuVisible)toggleMenu("hide"); 60 | }); 61 | const setPosition = ({ top, left }) => { 62 | menu.style.left = `${left}px`; 63 | menu.style.top = `${top}px`; 64 | toggleMenu("show"); 65 | }; 66 | if (document.addEventListener) { 67 | document.addEventListener('contextmenu', function(e) { 68 | e.preventDefault(); 69 | const origin = { 70 | left: e.pageX, 71 | top: e.pageY 72 | }; 73 | setPosition(origin); 74 | return false; 75 | }, false); 76 | } else { 77 | document.attachEvent('oncontextmenu', function() { 78 | alert("You've tried to open context menu"); 79 | window.event.returnValue = false; 80 | }); 81 | } 82 | 83 | // NavigationReference = ReactDOM.render(, document.getElementById('navigation')); 84 | // infoModal = ReactDOM.render(, document.getElementById('infoModal')); 85 | window.tabsgroup = ReactDOM.render(, document.getElementById('active-tabs-list-container')); 86 | 87 | $('#refreshActiveTabs').on('click', updateTabs( window.tabsgroup)); 88 | $('#closeSelectedBtn').on('click', (e)=>{ 89 | window.tabsgroup.processSelectedTabs('close'); 90 | }); 91 | -------------------------------------------------------------------------------- /src/scripts/background.js: -------------------------------------------------------------------------------- 1 | // import { saveSessions, getSessions } from './components/getsetSessions.js'; 2 | // import packagedAndBroadcast from './components/communications.js'; 3 | // import { registerMenus, setTabCountInBadge } from "./components/browserActions.jsx"; 4 | // const { setTabCountInBadge,updateTabs } = require('./components/browserActions.js'); 5 | // import './defaultPreferences'; 6 | var browser = require("webextension-polyfill"); 7 | import {log} from './components/general'; 8 | import {preferences} from './defaultPreferences'; 9 | import {getTabs, openExcitedGemPage, setBadge,setTabCountInBadge} from "./components/browserActions"; 10 | 11 | 12 | // let muteAll = (data) => { 13 | // for (let i = 0; i < data.length; i++) { 14 | // browser.tabs.update(tabId, { muted: true }); 15 | // } 16 | // }; 17 | 18 | // let moveTab = (data) => { 19 | // tabId = parseInt(data.tabId); 20 | // position = parseInt(data.position); 21 | // browser.tabs.move(tabId, { index: position }); 22 | // }; 23 | function onRemoved(tabId, removeInfo) { 24 | getTabs().then((tabs)=> {window.tabs = tabs;}); 25 | } 26 | /** 27 | * [saveData description] 28 | * @param {String/Object/Array} data [description] 29 | * @param {String} message [description] 30 | */ 31 | let saveData = (data, message = 'Data saved') =>{ 32 | browser.storage.local.set(data, () => { 33 | browser.notifications.create( 34 | 'reminder', 35 | { 36 | type: 'basic', 37 | iconUrl: '../images/extension-icon48.png', 38 | title: 'Data saved', 39 | message: message, 40 | }, 41 | notificationId => {} 42 | ); 43 | }); 44 | }; 45 | 46 | /* Events */ 47 | /////////// 48 | browser.runtime.onInstalled.addListener(() => { 49 | // console.info("Excited Gem Installed!"); 50 | // if (NODE_ENV == 'development') browser.storage.local.clear(console.log("cleared")); //Previous data being removed for development version 51 | let jsonObj = {}; 52 | jsonObj['preferences'] = preferences; 53 | browser.storage.local.set(jsonObj).then(result => { 54 | browser.storage.local.get('preferences').then(result => { 55 | }); 56 | }); 57 | getTabs().then((tabs)=> setBadge(tabs.length)); 58 | }); 59 | browser.tabs.onRemoved.addListener((tabId) => { 60 | // browser.tabs.get(homepageOpened.id, () => { 61 | // if (browser.runtime.lastError) { 62 | // setHomePageOpened(null); 63 | // console.log(browser.runtime.lastError.message); 64 | // } else { 65 | // // Tab exists 66 | // } 67 | // log('tab-closed:', tab); 68 | // }); 69 | log('Excited Gem: Tab Removed/Closed.'); 70 | onRemoved(); 71 | setTabCountInBadge(tabId,true); 72 | 73 | }); 74 | 75 | 76 | 77 | browser.tabs.onDetached.addListener(onRemoved); 78 | 79 | browser.tabs.onCreated.addListener( 80 | () => { 81 | getTabs().then((tabs)=> setBadge(tabs.length)); 82 | }); 83 | browser.tabs.onAttached.addListener( 84 | () => { 85 | getTabs().then((tabs)=> setBadge(tabs.length)); 86 | }); 87 | 88 | 89 | /* Browser Actions */ 90 | ///////////////////// 91 | browser.browserAction.onClicked.addListener(tab => { 92 | console.info("Extension Page opening"); 93 | browser.tabs.create({ url: browser.extension.getURL('tabs.html'), pinned: true }) 94 | .then(tab => window.homepageOpened = tab); 95 | // openExcitedGemPage(); 96 | }); 97 | 98 | 99 | 100 | 101 | // On clicking extension button opens EG homepage. 102 | 103 | //Registering Menus 104 | // registerMenus(); 105 | -------------------------------------------------------------------------------- /src/scripts/bootstrap/index.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery' 2 | import Alert from './alert' 3 | import Button from './button' 4 | import Carousel from './carousel' 5 | import Collapse from './collapse' 6 | import Dropdown from './dropdown' 7 | import Modal from './modal' 8 | import Popover from './popover' 9 | import Scrollspy from './scrollspy' 10 | import Tab from './tab' 11 | import Tooltip from './tooltip' 12 | import Util from './util' 13 | 14 | /** 15 | * -------------------------------------------------------------------------- 16 | * Bootstrap (v4.1.3): index.js 17 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 18 | * -------------------------------------------------------------------------- 19 | */ 20 | 21 | (($) => { 22 | if (typeof $ === 'undefined') { 23 | throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.') 24 | } 25 | 26 | const version = $.fn.jquery.split(' ')[0].split('.') 27 | const minMajor = 1 28 | const ltMajor = 2 29 | const minMinor = 9 30 | const minPatch = 1 31 | const maxMajor = 4 32 | 33 | if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { 34 | throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0') 35 | } 36 | })($) 37 | 38 | export { 39 | Util, 40 | Alert, 41 | Button, 42 | Carousel, 43 | Collapse, 44 | Dropdown, 45 | Modal, 46 | Popover, 47 | Scrollspy, 48 | Tab, 49 | Tooltip 50 | } 51 | -------------------------------------------------------------------------------- /src/scripts/components/Accordion/TabsGroup/Tab/index.js: -------------------------------------------------------------------------------- 1 | import Tab from './Tab.js'; 2 | // import 'tab.css'; 3 | // export default Tab; 4 | module.exports = require('./Tab.js'); 5 | -------------------------------------------------------------------------------- /src/scripts/components/Accordion/TabsGroup/TabsGroup.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { TransitionGroup, CSSTransition } from 'react-transition-group'; 4 | // import Tab from './Tab/index'; 5 | // import {log} from '../../general'; 6 | // var browser = require('webextension-polyfill'); 7 | 8 | export default class TabsGroup extends React.Component { 9 | constructor(props) { 10 | super(props); 11 | this.state = { 12 | // tabs:this.props.tabs, 13 | // preferences: this.props.preferences, 14 | selectedTabs: [], 15 | }; 16 | this.render = this.render.bind(this); 17 | // this.updateSelectedTabs = this.updateSelectedTabs.bind(this); 18 | } 19 | static getDerivedStateFromProps(nextProps, prevState) { 20 | // console.log("Tabsgroup.js getDerivedStateFromProps:",nextProps, prevState); 21 | return nextProps; 22 | } 23 | componentDidMount() { 24 | // console.log("tabsgroup mounted:",this.state.tabs); 25 | } 26 | // componentWillReceiveProps(props) { 27 | // console.log("TabsGroup.js getting new props:",props.tabs); 28 | // this.setState({tabs: props.tabs}); 29 | // } 30 | render() { 31 | // console.log("tabgroup this props children",this.state.tabs,this.props.children); 32 | return ( 33 | 34 | {this.props.children} 35 | 36 | ); 37 | } 38 | } 39 | TabsGroup.propTypes = { 40 | preferences: PropTypes.object, 41 | tabs: PropTypes.array, 42 | }; 43 | -------------------------------------------------------------------------------- /src/scripts/components/Accordion/TabsGroup/index.js: -------------------------------------------------------------------------------- 1 | // import TabsGroup from './TabsGroup.js'; 2 | module.exports = require('./TabsGroup.js'); 3 | -------------------------------------------------------------------------------- /src/scripts/components/Header/Search/index.js: -------------------------------------------------------------------------------- 1 | import Tab from './Search.js'; 2 | // import 'tab.css'; 3 | // export default Tab; 4 | module.exports = require('./Search.js'); 5 | -------------------------------------------------------------------------------- /src/scripts/components/communications.js: -------------------------------------------------------------------------------- 1 | function packagedData(sender, receiver, targetMethod, data) { 2 | let pack = { 3 | sender: sender, 4 | receiver: receiver, 5 | targetMethod: targetMethod, 6 | data: data 7 | }; 8 | return pack; 9 | } 10 | 11 | export default function packagedAndBroadcast(sender = sender, receiver, targetMethod, data) { 12 | browser.runtime.sendMessage(packagedData(sender, receiver, targetMethod, data)); 13 | } -------------------------------------------------------------------------------- /src/scripts/components/idle.js: -------------------------------------------------------------------------------- 1 | chrome.idle.setDetectionInterval(30); 2 | chrome.idle.onStateChanged.addListener((newState) => { 3 | if (newState == 'idle') { 4 | console.log("idle"); 5 | } 6 | }); -------------------------------------------------------------------------------- /src/scripts/components/readingList.js: -------------------------------------------------------------------------------- 1 | ////READING LISTS 2 | let itemGroup; //variable to stores data for React Component 3 | let ReadingLists; //React Component 4 | let readinglistsCounter; 5 | 6 | let renderReadingLists = (items)=>{ 7 | console.log("Getting Reading list",items); 8 | itemGroup = items.readinglists; 9 | if(items.readinglists == undefined){ 10 | itemGroup = []; 11 | readinglistsCounter = 0; 12 | }else{ 13 | itemGroup = items.readinglists; 14 | readinglistsCounter = items.readinglists.length; 15 | } 16 | return items.readinglists; 17 | ReadingLists.setState({data:itemGroup}); 18 | } 19 | let getReadingLists = () => { 20 | chrome.storage.local.get("readinglists", renderReadingLists(items)); 21 | } 22 | let setReadingLists = (data) => { 23 | chrome.storage.local.set({ readinglists: data }, function() { 24 | console.log('Saving readinglists'); 25 | readinglistsCounter++; 26 | ReadingLists.setState({ data: itemGroup }); 27 | }); 28 | } 29 | export {getReadingLists,setReadingLists}; 30 | -------------------------------------------------------------------------------- /src/scripts/components/search.js: -------------------------------------------------------------------------------- 1 | ////QUERY 2 | let sidebar; 3 | let resultTable; 4 | let results; 5 | 6 | function query(queryString = 'table#searchResult tbody td') { 7 | console.log($(queryString)); 8 | $('.eg_results_table').empty(); 9 | return $(queryString); 10 | } 11 | 12 | function createQueryResultaTable() { 13 | let sidebar = $("
"); 14 | sidebar.addClass('eg_sidebar'); 15 | $('body').append(sidebar); 16 | sidebar.css({ 17 | 'position': 'fixed', 18 | 'width': '400px', 19 | 'height': windowHeight, 20 | 'min-height': '700px', 21 | 'background': 'white', 22 | 'overflow-y': 'scroll', 23 | 'right': "-400px", 24 | 'top': '0', 25 | 'box-shadow': '0 0 10px 0 #000', 26 | 'z-index': '9999' 27 | }); 28 | let queryinput = $(''); 29 | sidebar.append(queryinput); 30 | queryinput.on('keyup', function(e) { 31 | if (e.keyCode == 13) { 32 | let queryString = queryinput.val(); 33 | results = query(queryString); 34 | manageQueryResultTable(results); 35 | } 36 | }); 37 | resultTable = $(`
`); 38 | sidebar.append(resultTable); 39 | return resultTable; 40 | } 41 | 42 | function manageQueryResultTable(results) { 43 | $.each(results, function(index, value) { 44 | // let name = $(value).find('.detName a').text(); 45 | // let url = $(value).find('> a').first().attr('href'); 46 | let tr = $(''); 47 | resultTable.append(tr); 48 | let tableRow = `${index+1}${value.outerHTML}`; 49 | tr.append(tableRow); 50 | 51 | }); 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/scripts/components/tabSelection.js: -------------------------------------------------------------------------------- 1 | // export let selectedTabIndex; 2 | // export default function selectTab(number) { 3 | // if (number < 0) number = 0; 4 | // $('.eg .tabs-list.list-group li.list-group-item').removeClass('selected'); 5 | // $('.eg .tabs-list.list-group').find('li.list-group-item:nth(' + number + ')').addClass('selected'); 6 | // selectedTabIndex = number; 7 | // } 8 | // $(document).keydown(function(e) { 9 | // console.log(e.key, e.which, e.code); 10 | // if (e.which == 40) { 11 | // console.log(selectedTabIndex, $('.eg .tabs-list li').length); 12 | // if (selectedTabIndex >= $('.eg .tabs-list li').length) { 13 | // selectTab($('.eg .tabs-list li').length - 1); 14 | // } else if (selectedTabIndex < $('.eg .tabs-list li').length - 1) { 15 | // selectTab(selectedTabIndex + 1); 16 | // } 17 | // } 18 | // if (e.which == 36) { //Home 19 | // selectTab(0); 20 | // } 21 | // if (e.which == 35) { //End 22 | // selectTab($('.eg .tabs-list li').length - 1); 23 | // } 24 | // if (e.which == 38) { 25 | // selectTab(selectedTabIndex - 1); 26 | // } 27 | // if (e.which == 13) { //focus tab on Enter 28 | // let id = $('.eg .tabs-list li.list-group-item:nth(' + selectedTabIndex + ')').attr('data-id'); 29 | // packageAndBroadcast(sender, "background", "focusTab", id); 30 | // } 31 | // if (e.which == 46) { 32 | // let id = $('.eg .tabs-list li.list-group-item:nth(' + selectedTabIndex + ')').attr('data-id'); 33 | // if (confirm('Are you sure you want to close the following this Tab')) { packageAndBroadcast(sender, "background", "closeTab", id); } 34 | // } 35 | // }); 36 | //Prevents scrolling with Down arrow key 37 | // document.addEventListener("keydown", function(e) { 38 | // if ([37, 38, 39, 40].indexOf(e.keyCode) > -1) { 39 | // e.preventDefault(); 40 | // // Do whatever else you want with the keydown event (i.e. your navigation). 41 | // } 42 | // }, false); 43 | -------------------------------------------------------------------------------- /src/scripts/components/tabs.js: -------------------------------------------------------------------------------- 1 | let selectTab = (number) => { 2 | if (number < 0) number = 0; 3 | $('.eg .tabs-list.list-group li.list-group-item').removeClass('selected'); 4 | $('.eg .tabs-list.list-group').find('li.list-group-item:nth(' + number + ')').addClass('selected'); 5 | selectedTabIndex = number; 6 | } 7 | 8 | let renderTabs = () => { 9 | if (window.location.pathname.indexOf('tabs') > -1) { 10 | chrome.runtime.onConnect.addListener(function(port) { 11 | // console.assert(port.name == "ActiveTabsConnection"); 12 | if (port.name == "ActiveTabsConnection") { 13 | port.onMessage.addListener(function(msg) { 14 | // console.log("msg", msg); 15 | activeTabsCount = msg.tabs.length; 16 | $('.active-tab-counter').text("(" + activeTabsCount + ")"); 17 | if (!jQuery.isEmptyObject(msg)) { 18 | tabsList = msg.tabs; 19 | $('.active-tab-count').html(msg.tabs.length); 20 | ActiveTabs.setState({ data: msg.tabs }); 21 | selectTab(1); 22 | } 23 | }); 24 | } 25 | }) 26 | } 27 | } 28 | function sortTabs(head, type) { 29 | // var type = type; 30 | // let head = head; 31 | let prevTabs = tabsList; 32 | let prevTabsArray; 33 | let tabsListArray; 34 | let loopFinished; 35 | setTimeout(function() { 36 | if (type == 'url') tabsList.sort(compareURL); 37 | if (type == 'title') tabsList.sort(compareTitle); 38 | // console.log(tabsList[i].title); 39 | data = { 'position': head, "tabId": tabsList[head].id } 40 | packageAndBroadcast(sender, 'background', 'moveTab', data); 41 | if (type == 'url') { 42 | tabsListArray = propertyToArray(tabsList, 'url'); 43 | prevTabsArray = propertyToArray(prevTabs, 'url'); 44 | } 45 | if (type == 'title') { 46 | tabsListArray = propertyToArray(tabsList, 'title'); 47 | prevTabsArray = propertyToArray(prevTabs, 'title'); 48 | } 49 | head++; 50 | if (head < tabsList.length) { 51 | sortTabs(head, type); 52 | } 53 | loopFinished = true; 54 | let sameArray = arraysAreIdentical(prevTabsArray, tabsListArray); 55 | 56 | if (sameArray) { 57 | console.log(sameArray, prevTabsArray, tabsListArray); 58 | return; 59 | } 60 | 61 | if (!sameArray && loopFinished) { 62 | console.log(sameArray, "=", tabsListArray, '=', prevTabsArray); 63 | head = 0; 64 | sortTabs(head, type); 65 | } 66 | }, pref.sortAnimation) 67 | } 68 | -------------------------------------------------------------------------------- /src/scripts/defaultPreferences.js: -------------------------------------------------------------------------------- 1 | exports.preferences = { 2 | search:{ 3 | regex : true, 4 | ignoreCase : true, 5 | searchIn: [true,true] // title,url 6 | }, 7 | defaultTabsFrom : "current", 8 | tempTabsFrom: 'current', 9 | tabsGroup: { 10 | promptForClosure :true,/**/ 11 | tabsListAnimation: true, 12 | tabSortAnimation: true, 13 | //selection by ckeckbox/hover mode/click mode 14 | selectionBy: 'checkbox', 15 | display:{ 16 | favicon: true, 17 | title: true, 18 | url:true, 19 | pin:true, 20 | sound: true, 21 | // close:true 22 | } 23 | } 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /src/scripts/images/ui-icons_444444_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/scripts/images/ui-icons_444444_256x240.png -------------------------------------------------------------------------------- /src/scripts/images/ui-icons_555555_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/scripts/images/ui-icons_555555_256x240.png -------------------------------------------------------------------------------- /src/scripts/images/ui-icons_777620_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/scripts/images/ui-icons_777620_256x240.png -------------------------------------------------------------------------------- /src/scripts/images/ui-icons_777777_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/scripts/images/ui-icons_777777_256x240.png -------------------------------------------------------------------------------- /src/scripts/images/ui-icons_cc0000_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/scripts/images/ui-icons_cc0000_256x240.png -------------------------------------------------------------------------------- /src/scripts/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/scripts/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /src/scripts/options-container.js: -------------------------------------------------------------------------------- 1 | require('jquery'); 2 | require('bootstrap'); 3 | 4 | import packagedAndBroadcast from './components/communications.js'; 5 | import * as general from './components/general.js'; 6 | 7 | import '../styles/bootstrap.scss'; 8 | import '../styles/eg.scss'; 9 | ////GENERAL OPTIONS/CONFIGURATIONS 10 | let pref = { 11 | filterType: 'regex', 12 | filterCase: false, 13 | sortAnimation: 250, 14 | }; 15 | general.highlightCurrentNavLink(); 16 | 17 | function getOptions() { 18 | chrome.storage.sync.get('pref', function(items) { 19 | pref.filterType = items.pref.filterType; 20 | pref.filterCase = items.pref.filterCase; 21 | pref.sortAnimation = items.pref.sortAnimation; 22 | 23 | $('.option-case-sensitive input').prop(('checked': pref.filterCase)); 24 | 25 | if (pref.filterType == 'regex') { 26 | $('.option-regex input').prop(('checked': true)); 27 | } else { 28 | $('.option-regex input').prop(('checked': false)); 29 | } 30 | }); 31 | } 32 | // Saves options to chrome.storage.sync. 33 | function save_options(e) { 34 | e.preventDefault(); 35 | let pref = {}; 36 | pref.filterType = $('#filter-type-option-id').val(); 37 | pref.filterCase = $('#filterCase-option-id').prop('checked'); 38 | pref.sortAnimation = $('#sort-animation-option-id').val(); 39 | console.log(pref); 40 | chrome.storage.sync.set( 41 | { 42 | pref: pref, 43 | }, 44 | function() { 45 | // Update status to let user know options were saved. 46 | console.log(pref); 47 | let status = document.getElementById('status'); 48 | $('#status>span').text('Options Saved'); 49 | $('#status').fadeIn('slow'); 50 | // status.textContent = 'Options saved.'; 51 | setTimeout(function() { 52 | $('#status').fadeOut('slow'); 53 | $('#status>span').text(''); 54 | }, 2500); 55 | } 56 | ); 57 | } 58 | // Restores select box and checkbox state using the preferences 59 | // stored in chrome.storage. 60 | function restore_options() { 61 | chrome.storage.sync.get('pref', function(items) { 62 | console.log(items); 63 | $('#filter-type-option-id').val(items.pref.filterType); 64 | $('#sort-animation-option-id').val(items.pref.sortAnimation); 65 | $('#filterCase-option-id').prop(('checked': items.pref.filterCase)); 66 | }); 67 | } 68 | document.addEventListener('DOMContentLoaded', restore_options); 69 | // document.getElementById('save').addEventListener('click', save_options); 70 | $('#save').on('click', save_options); 71 | $('#go-to-tabs').on('click', function() { 72 | packagedAndBroadcast('options', 'background', 'openExcitedGemPage', null); 73 | }); 74 | -------------------------------------------------------------------------------- /src/scripts/page-detection.js: -------------------------------------------------------------------------------- 1 | let windowHeight: number; 2 | let sender: string = 'content'; 3 | let tabsList; 4 | let ActiveTabs :[] ; //React Component 5 | -------------------------------------------------------------------------------- /src/scripts/react-components/navigation.rc.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | const Navigation = () => ( 3 |
4 |
5 | 6 |
7 | 14 |
15 |

16 | Made with Love by Amir :) 17 |

18 |
19 |
20 | ); 21 | export default Navigation; -------------------------------------------------------------------------------- /src/scripts/react-components/options.js: -------------------------------------------------------------------------------- 1 | ////MESSAGING AND COMMUNICATION 2 | function packageData(sender:string,receiver:string,targetMethod:String,data: any): Object{ 3 | let package :Object = { 4 | sender: sender, 5 | receiver: receiver, 6 | targetMethod:targetMethod, 7 | data: data 8 | }; 9 | return package; 10 | } 11 | 12 | function packageAndBroadcast(sender:string = sender,receiver:string,targetMethod:String,data: any){ 13 | chrome.runtime.sendMessage(packageData(sender,receiver,targetMethod,data)); 14 | } 15 | chrome.runtime.onConnect.addListener(function(port){ 16 | 17 | console.assert(port.name == "ActiveTabsConnection"); 18 | if (port.name == "ActiveTabsConnection") { 19 | port.onMessage.addListener(function(msg) { 20 | console.log("msg",msg); 21 | if(!jQuery.isEmptyObject(msg)) 22 | { 23 | tabsList = msg.tabs; 24 | $('.active-tab-count').html(msg.tabs.length); 25 | ActiveTabs.setState({data: msg.tabs}); 26 | } 27 | }); 28 | } 29 | }); 30 | 31 | 32 | // Saves options to chrome.storage.sync. 33 | function save_options(e) { 34 | e.preventDefault(); 35 | let pref = {}; 36 | pref.filterType = $('#filter-type-option-id').val(); 37 | pref.filterCase = $('#filterCase-option-id').prop('checked'); 38 | pref.sortAnimation = $('#sort-animation-option-id').val(); 39 | console.log(pref) 40 | chrome.storage.local.set({ 41 | pref: pref 42 | }, function () { 43 | // Update status to let user know options were saved. 44 | console.log(pref); 45 | let status = document.getElementById('status'); 46 | $('#status>span').text('Options Saved'); 47 | $('#status').fadeIn('slow') 48 | // status.textContent = 'Options saved.'; 49 | setTimeout(function () { 50 | $('#status').fadeOut('slow') 51 | $('#status>span').text(''); 52 | }, 2500); 53 | }); 54 | 55 | } 56 | // Restores select box and checkbox state using the preferences 57 | // stored in chrome.storage. 58 | function restore_options() { 59 | chrome.storage.local.get("pref", function (items) { 60 | console.log(items); 61 | $('#filter-type-option-id').val(items.pref.filterType) 62 | $('#sort-animation-option-id').val(items.pref.sortAnimation) 63 | $('#filterCase-option-id').prop('checked': items.pref.filterCase) 64 | }); 65 | } 66 | document.addEventListener('DOMContentLoaded', restore_options); 67 | // document.getElementById('save').addEventListener('click', save_options); 68 | $('#save').on('click',save_options); 69 | $('#go-to-tabs').on('click',function(){ 70 | packageAndBroadcast('options','background','openExcitedGemPage',null); 71 | }); 72 | 73 | -------------------------------------------------------------------------------- /src/scripts/sessions-container.js: -------------------------------------------------------------------------------- 1 | //Vendors 2 | const $ = (jQuery = require('jquery')); 3 | const bootstrap = require('bootstrap'); 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom'; 6 | // import * as general from './components/general.js'; 7 | import Sessions from './react-components/session'; 8 | import { saveSessions, getSessions } from './components/getsetSessions'; 9 | 10 | //Styles 11 | import '../styles/fontawesome5/fa-solid.scss'; 12 | import '../styles/fontawesome5/fa-light.scss'; 13 | import '../styles/fontawesome5/fa-regular.scss'; 14 | import '../styles/fontawesome5.scss'; 15 | import '../styles/eg.scss'; 16 | 17 | $(document).ready(function() { 18 | $('.collapse').collapse(); 19 | window.sessions = ReactDOM.render(, document.getElementById('all-sessions')); 20 | getSessions().then(items => window.sessions.setState({ data: items })); 21 | 22 | $('#saveSessions-btn').on('click', function(e) { 23 | e.preventDefault(); 24 | saveSessions(sessions); 25 | }); 26 | 27 | $('#saveSessionsAndClose-btn').on('click', function() { 28 | packagedAndBroadcast(sender, 'background', 'saveSessionsAndClose', null); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /src/scripts/settings.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/picwellwisher12pk/Excited-Gem/93da5e1f05848a332afb5262390c72848c2bb7f7/src/scripts/settings.js -------------------------------------------------------------------------------- /src/scripts/vendor/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /src/sessions.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 | 10 | 11 | 12 | 63 | 64 |
65 |
66 | 67 |
68 |
69 |
70 |
71 | 72 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/sessions.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html(lang="en") 3 | head 4 | title="Excited Gem" 5 | link(rel="stylesheet", href="css/bootstrap.css") 6 | link(rel="stylesheet", href="css/eg.css") 7 | //- link(rel="stylesheet", href="css/font-awesome.css") 8 | script(src="js/jquery.min.js") 9 | script(src="js/react/dist/react.js") 10 | script(src="js/react-dom/dist/react-dom.js") 11 | script(src="js/bootstrap.js") 12 | //- script(src="js/activetabs.js") 13 | script(src="js/sessions.js") 14 | //- script(src="js/readinglist.js") 15 | script(src="js/content.js") 16 | //- script(src="js/contentext.js") 17 | //- script(src="js/jquery-ui.js") 18 | 19 | style. 20 | .tabGroupTitleText { 21 | font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif; 22 | color: #444; 23 | } 24 | 25 | 26 | body.eg 27 | include navigation 28 | .container-fluid.sessions 29 | h1 Sessions 30 | #sessions-tab.tab-pane(role='tabpanel') 31 | .tabs-list-container.header 32 | .horizontal-block.context-actions 33 | ul.nav.nav-pills 34 | li(role='presentation') 35 | a#saveSessions-btn(href='#', title='Save Active Tabs opened in all Chrome windows') 36 | span.glyphicon.glyphicon-save(aria-hidden='true') 37 | | Save Session 38 | li(role='presentation') 39 | a#saveSessionsAndClose-btn(href='#', title='Save Active Tabs opened in all Chrome windows and close Chrome') 40 | span.glyphicon.glyphicon-save(aria-hidden='true') 41 | | Save Session and Close Chrome 42 | #all-sessions 43 | #react-container 44 | // Small modal 45 | #infoModal.modal.bs-example-modal-sm(tabindex='-1', role='dialog', aria-labelledby='mySmallModalLabel') 46 | -------------------------------------------------------------------------------- /src/styles/bootstrap.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v4.1.3 (https://getbootstrap.com/) 3 | * Copyright 2011-2018 The Bootstrap Authors 4 | * Copyright 2011-2018 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | */ 7 | 8 | @import "bootstrap/functions"; 9 | @import "bootstrap/variables"; 10 | @import "bootstrap/mixins"; 11 | @import "bootstrap/root"; 12 | @import "bootstrap/reboot"; 13 | @import "bootstrap/type"; 14 | @import "bootstrap/images"; 15 | //@import "bootstrap/code"; 16 | @import "bootstrap/grid"; 17 | //@import "bootstrap/tables"; 18 | @import "bootstrap/forms"; 19 | @import "bootstrap/buttons"; 20 | @import "bootstrap/transitions"; 21 | @import "bootstrap/dropdown"; 22 | //@import "bootstrap/button-group"; 23 | @import "bootstrap/input-group"; 24 | @import "bootstrap/custom-forms"; 25 | @import "bootstrap/nav"; 26 | @import "bootstrap/navbar"; 27 | @import "bootstrap/card"; 28 | //@import "bootstrap/breadcrumb"; 29 | //@import "bootstrap/pagination"; 30 | @import "bootstrap/badge"; 31 | //@import "bootstrap/jumbotron"; 32 | @import "bootstrap/alert"; 33 | //@import "bootstrap/progress"; 34 | //@import "bootstrap/media"; 35 | @import "bootstrap/list-group"; 36 | @import "bootstrap/close"; 37 | @import "bootstrap/modal"; 38 | @import "bootstrap/tooltip"; 39 | //@import "bootstrap/popover"; 40 | @import "bootstrap/carousel"; 41 | @import "bootstrap/utilities"; 42 | //@import "bootstrap/print"; 43 | -------------------------------------------------------------------------------- /src/styles/bootstrap/_alert.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Base styles 3 | // 4 | 5 | .alert { 6 | position: relative; 7 | padding: $alert-padding-y $alert-padding-x; 8 | margin-bottom: $alert-margin-bottom; 9 | border: $alert-border-width solid transparent; 10 | @include border-radius($alert-border-radius); 11 | } 12 | 13 | // Headings for larger alerts 14 | .alert-heading { 15 | // Specified to prevent conflicts of changing $headings-color 16 | color: inherit; 17 | } 18 | 19 | // Provide class for links that match alerts 20 | .alert-link { 21 | font-weight: $alert-link-font-weight; 22 | } 23 | 24 | 25 | // Dismissible alerts 26 | // 27 | // Expand the right padding and account for the close button's positioning. 28 | 29 | .alert-dismissible { 30 | padding-right: ($close-font-size + $alert-padding-x * 2); 31 | 32 | // Adjust close link position 33 | .close { 34 | position: absolute; 35 | top: 0; 36 | right: 0; 37 | padding: $alert-padding-y $alert-padding-x; 38 | color: inherit; 39 | } 40 | } 41 | 42 | 43 | // Alternate styles 44 | // 45 | // Generate contextual modifier classes for colorizing the alert. 46 | 47 | @each $color, $value in $theme-colors { 48 | .alert-#{$color} { 49 | @include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/styles/bootstrap/_badge.scss: -------------------------------------------------------------------------------- 1 | // Base class 2 | // 3 | // Requires one of the contextual, color modifier classes for `color` and 4 | // `background-color`. 5 | 6 | .badge { 7 | display: inline-block; 8 | padding: $badge-padding-y $badge-padding-x; 9 | font-size: $badge-font-size; 10 | font-weight: $badge-font-weight; 11 | line-height: 1; 12 | text-align: center; 13 | white-space: nowrap; 14 | vertical-align: baseline; 15 | @include border-radius($badge-border-radius); 16 | 17 | // Empty badges collapse automatically 18 | &:empty { 19 | display: none; 20 | } 21 | } 22 | 23 | // Quick fix for badges in buttons 24 | .btn .badge { 25 | position: relative; 26 | top: -1px; 27 | } 28 | 29 | // Pill badges 30 | // 31 | // Make them extra rounded with a modifier to replace v3's badges. 32 | 33 | .badge-pill { 34 | padding-right: $badge-pill-padding-x; 35 | padding-left: $badge-pill-padding-x; 36 | @include border-radius($badge-pill-border-radius); 37 | } 38 | 39 | // Colors 40 | // 41 | // Contextual variations (linked badges get darker on :hover). 42 | 43 | @each $color, $value in $theme-colors { 44 | .badge-#{$color} { 45 | @include badge-variant($value); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/styles/bootstrap/_breadcrumb.scss: -------------------------------------------------------------------------------- 1 | .breadcrumb { 2 | display: flex; 3 | flex-wrap: wrap; 4 | padding: $breadcrumb-padding-y $breadcrumb-padding-x; 5 | margin-bottom: $breadcrumb-margin-bottom; 6 | list-style: none; 7 | background-color: $breadcrumb-bg; 8 | @include border-radius($breadcrumb-border-radius); 9 | } 10 | 11 | .breadcrumb-item { 12 | // The separator between breadcrumbs (by default, a forward-slash: "/") 13 | + .breadcrumb-item { 14 | padding-left: $breadcrumb-item-padding; 15 | 16 | &::before { 17 | display: inline-block; // Suppress underlining of the separator in modern browsers 18 | padding-right: $breadcrumb-item-padding; 19 | color: $breadcrumb-divider-color; 20 | content: $breadcrumb-divider; 21 | } 22 | } 23 | 24 | // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built 25 | // without `