Firefox version
BIN
firefox/assets/Inter-Black.ttf
Normal file
BIN
firefox/assets/Inter-Bold.ttf
Normal file
BIN
firefox/assets/Inter-ExtraBold.ttf
Normal file
BIN
firefox/assets/Inter-ExtraLight.ttf
Normal file
BIN
firefox/assets/Inter-Light.ttf
Normal file
BIN
firefox/assets/Inter-Medium.ttf
Normal file
BIN
firefox/assets/Inter-Regular.ttf
Normal file
BIN
firefox/assets/Inter-SemiBold.ttf
Normal file
BIN
firefox/assets/Inter-Thin.ttf
Normal file
6
firefox/assets/action-delete.svg
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.75 3.5H2.91667H12.25" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.66699 3.50033V2.33366C4.66699 2.02424 4.78991 1.72749 5.0087 1.5087C5.22749 1.28991 5.52424 1.16699 5.83366 1.16699H8.16699C8.47641 1.16699 8.77316 1.28991 8.99195 1.5087C9.21074 1.72749 9.33366 2.02424 9.33366 2.33366V3.50033M11.0837 3.50033V11.667C11.0837 11.9764 10.9607 12.2732 10.742 12.492C10.5232 12.7107 10.2264 12.8337 9.91699 12.8337H4.08366C3.77424 12.8337 3.47749 12.7107 3.2587 12.492C3.03991 12.2732 2.91699 11.9764 2.91699 11.667V3.50033H11.0837Z" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.83301 6.41699V9.91699" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8.16699 6.41699V9.91699" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1,022 B |
BIN
firefox/assets/add-action.png
Normal file
|
After Width: | Height: | Size: 654 B |
7
firefox/assets/add-action.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg width="314" height="20" viewBox="0 0 314 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="175" y="10" width="139" height="1" fill="#35373E"/>
|
||||
<rect y="10" width="139" height="1" fill="#35373E"/>
|
||||
<circle cx="157" cy="10" r="10" fill="#6068D2"/>
|
||||
<path d="M157 5.9165V14.0832" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M152.917 10H161.083" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 494 B |
3
firefox/assets/bookmark.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.75 26.25L15 20L6.25 26.25V6.25C6.25 5.58696 6.51339 4.95107 6.98223 4.48223C7.45107 4.01339 8.08696 3.75 8.75 3.75H21.25C21.913 3.75 22.5489 4.01339 23.0178 4.48223C23.4866 4.95107 23.75 5.58696 23.75 6.25V26.25Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 411 B |
4
firefox/assets/camera.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M27.8332 23.1667C27.8332 23.7855 27.5873 24.379 27.1498 24.8166C26.7122 25.2542 26.1187 25.5 25.4998 25.5H4.49984C3.881 25.5 3.28751 25.2542 2.84992 24.8166C2.41234 24.379 2.1665 23.7855 2.1665 23.1667V10.3333C2.1665 9.71449 2.41234 9.121 2.84992 8.68342C3.28751 8.24583 3.881 8 4.49984 8H9.1665L11.4998 4.5H18.4998L20.8332 8H25.4998C26.1187 8 26.7122 8.24583 27.1498 8.68342C27.5873 9.121 27.8332 9.71449 27.8332 10.3333V23.1667Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M15.0002 20.8333C17.5775 20.8333 19.6668 18.744 19.6668 16.1667C19.6668 13.5893 17.5775 11.5 15.0002 11.5C12.4228 11.5 10.3335 13.5893 10.3335 16.1667C10.3335 18.744 12.4228 20.8333 15.0002 20.8333Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 915 B |
3
firefox/assets/check.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.5 17C13.1944 17 17 13.1944 17 8.5C17 3.80558 13.1944 0 8.5 0C3.80558 0 0 3.80558 0 8.5C0 13.1944 3.80558 17 8.5 17ZM13.2337 6.97078C13.6242 6.58025 13.6242 5.94709 13.2337 5.55657C12.8431 5.16604 12.21 5.16604 11.8194 5.55657L7.60549 9.77051L6.07576 8.24078C5.68524 7.85025 5.05207 7.85025 4.66155 8.24078C4.27102 8.6313 4.27102 9.26446 4.66155 9.65499L6.89839 11.8918C7.08592 12.0794 7.34028 12.1847 7.60549 12.1847C7.87071 12.1847 8.12506 12.0794 8.3126 11.8918L13.2337 6.97078Z" fill="#6068D2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 654 B |
4
firefox/assets/clipboard.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.33301 2.3335H10.4997C10.8091 2.3335 11.1058 2.45641 11.3246 2.6752C11.5434 2.894 11.6663 3.19074 11.6663 3.50016V11.6668C11.6663 11.9762 11.5434 12.273 11.3246 12.4918C11.1058 12.7106 10.8091 12.8335 10.4997 12.8335H3.49967C3.19026 12.8335 2.89351 12.7106 2.67472 12.4918C2.45592 12.273 2.33301 11.9762 2.33301 11.6668V3.50016C2.33301 3.19074 2.45592 2.894 2.67472 2.6752C2.89351 2.45641 3.19026 2.3335 3.49967 2.3335H4.66634" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8.75033 1.1665H5.25033C4.92816 1.1665 4.66699 1.42767 4.66699 1.74984V2.9165C4.66699 3.23867 4.92816 3.49984 5.25033 3.49984H8.75033C9.07249 3.49984 9.33366 3.23867 9.33366 2.9165V1.74984C9.33366 1.42767 9.07249 1.1665 8.75033 1.1665Z" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 958 B |
4
firefox/assets/close-meta.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M22.5 7.5L7.5 22.5" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7.5 7.5L22.5 22.5" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 323 B |
4
firefox/assets/close.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.5 4.5L4.5 13.5" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.5 4.5L13.5 13.5" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 331 B |
4
firefox/assets/down.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 6.25V23.75" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M23.75 15L15 23.75L6.25 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 327 B |
4
firefox/assets/duplicate.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25 11.25H13.75C12.3693 11.25 11.25 12.3693 11.25 13.75V25C11.25 26.3807 12.3693 27.5 13.75 27.5H25C26.3807 27.5 27.5 26.3807 27.5 25V13.75C27.5 12.3693 26.3807 11.25 25 11.25Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.25 18.75H5C4.33696 18.75 3.70107 18.4866 3.23223 18.0178C2.76339 17.5489 2.5 16.913 2.5 16.25V5C2.5 4.33696 2.76339 3.70107 3.23223 3.23223C3.70107 2.76339 4.33696 2.5 5 2.5H16.25C16.913 2.5 17.5489 2.76339 18.0178 3.23223C18.4866 3.70107 18.75 4.33696 18.75 5V6.25" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 731 B |
7
firefox/assets/file.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.16634 1.1665H3.49967C3.19026 1.1665 2.89351 1.28942 2.67472 1.50821C2.45592 1.72701 2.33301 2.02375 2.33301 2.33317V11.6665C2.33301 11.9759 2.45592 12.2727 2.67472 12.4915C2.89351 12.7103 3.19026 12.8332 3.49967 12.8332H10.4997C10.8091 12.8332 11.1058 12.7103 11.3246 12.4915C11.5434 12.2727 11.6663 11.9759 11.6663 11.6665V4.6665L8.16634 1.1665Z" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8.16699 1.1665V4.6665H11.667" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9.33366 7.5835H4.66699" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M9.33366 9.9165H4.66699" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5.83366 5.25H5.25033H4.66699" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
5
firefox/assets/globe.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 25C20.5228 25 25 20.5228 25 15C25 9.47715 20.5228 5 15 5C9.47715 5 5 9.47715 5 15C5 20.5228 9.47715 25 15 25Z" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M5 15H25" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M15 5C17.5013 7.73835 18.9228 11.292 19 15C18.9228 18.708 17.5013 22.2616 15 25C12.4987 22.2616 11.0772 18.708 11 15C11.0772 11.292 12.4987 7.73835 15 5Z" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 665 B |
4
firefox/assets/interact.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.75 1.75L5.87417 11.6492L7.33833 7.33833L11.6492 5.87417L1.75 1.75Z" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7.58301 7.5835L11.083 11.0835" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 394 B |
4
firefox/assets/jquery.nice-select.min.js
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/* jQuery Nice Select - v1.0
|
||||
https://github.com/hernansartorio/jquery-nice-select
|
||||
Made by Hernán Sartorio */
|
||||
!function(e){e.fn.niceSelect=function(t){function s(t){t.after(e("<div></div>").addClass("nice-select").addClass(t.attr("class")||"").addClass(t.attr("disabled")?"disabled":"").attr("tabindex",t.attr("disabled")?null:"0").html('<span class="current"></span><ul class="list"></ul>'));var s=t.next(),n=t.find("option"),i=t.find("option:selected");s.find(".current").html(i.data("display")||i.text()),n.each(function(t){var n=e(this),i=n.data("display");s.find("ul").append(e("<li></li>").attr("data-value",n.val()).attr("data-display",i||null).addClass("option"+(n.is(":selected")?" selected":"")+(n.is(":disabled")?" disabled":"")).html(n.text()))})}if("string"==typeof t)return"update"==t?this.each(function(){var t=e(this),n=e(this).next(".nice-select"),i=n.hasClass("open");n.length&&(n.remove(),s(t),i&&t.next().trigger("click"))}):"destroy"==t?(this.each(function(){var t=e(this),s=e(this).next(".nice-select");s.length&&(s.remove(),t.css("display",""))}),0==e(".nice-select").length&&e(document).off(".nice_select")):console.log('Method "'+t+'" does not exist.'),this;this.hide(),this.each(function(){var t=e(this);t.next().hasClass("nice-select")||s(t)}),e(document).off(".nice_select"),e(document).on("click.nice_select",".nice-select",function(t){var s=e(this);e(".nice-select").not(s).removeClass("open"),s.toggleClass("open"),s.hasClass("open")?(s.find(".option"),s.find(".focus").removeClass("focus"),s.find(".selected").addClass("focus")):s.focus()}),e(document).on("click.nice_select",function(t){0===e(t.target).closest(".nice-select").length&&e(".nice-select").removeClass("open").find(".option")}),e(document).on("click.nice_select",".nice-select .option:not(.disabled)",function(t){var s=e(this),n=s.closest(".nice-select");n.find(".selected").removeClass("selected"),s.addClass("selected");var i=s.data("display")||s.text();n.find(".current").text(i),n.prev("select").val(s.data("value")).trigger("change")}),e(document).on("keydown.nice_select",".nice-select",function(t){var s=e(this),n=e(s.find(".focus")||s.find(".list .option.selected"));if(32==t.keyCode||13==t.keyCode)return s.hasClass("open")?n.trigger("click"):s.trigger("click"),!1;if(40==t.keyCode){if(s.hasClass("open")){var i=n.nextAll(".option:not(.disabled)").first();i.length>0&&(s.find(".focus").removeClass("focus"),i.addClass("focus"))}else s.trigger("click");return!1}if(38==t.keyCode){if(s.hasClass("open")){var l=n.prevAll(".option:not(.disabled)").first();l.length>0&&(s.find(".focus").removeClass("focus"),l.addClass("focus"))}else s.trigger("click");return!1}if(27==t.keyCode)s.hasClass("open")&&s.trigger("click");else if(9==t.keyCode&&s.hasClass("open"))return!1});var n=document.createElement("a").style;return n.cssText="pointer-events:auto","auto"!==n.pointerEvents&&e("html").addClass("no-csspointerevents"),this}}(jQuery);
|
||||
11
firefox/assets/left.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_326_2970)">
|
||||
<path d="M23.75 15L6.25 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M15 23.75L6.25 15L15 6.25" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_326_2970">
|
||||
<rect width="30" height="30" fill="white" transform="matrix(1 0 0 -1 0 30)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 507 B |
BIN
firefox/assets/logo-128.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
BIN
firefox/assets/logo-16.png
Normal file
|
After Width: | Height: | Size: 589 B |
BIN
firefox/assets/logo-48.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
firefox/assets/logo-anchor.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
firefox/assets/logo-asana.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
firefox/assets/logo-calendar.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
firefox/assets/logo-canva.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
firefox/assets/logo-codepen.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
firefox/assets/logo-docs.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
firefox/assets/logo-excel.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
firefox/assets/logo-figma.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
firefox/assets/logo-forms.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
firefox/assets/logo-github.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
firefox/assets/logo-github2.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
firefox/assets/logo-keep.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
firefox/assets/logo-linear.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
firefox/assets/logo-medium.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
firefox/assets/logo-meet.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
firefox/assets/logo-notion.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
firefox/assets/logo-photoshop.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
firefox/assets/logo-powerpoint.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
firefox/assets/logo-producthunt.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
firefox/assets/logo-qr.png
Normal file
|
After Width: | Height: | Size: 9 KiB |
BIN
firefox/assets/logo-sheets.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
firefox/assets/logo-slides.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
firefox/assets/logo-spotify.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
firefox/assets/logo-twitter.png
Normal file
|
After Width: | Height: | Size: 937 B |
BIN
firefox/assets/logo-wip.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
firefox/assets/logo-word.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
firefox/assets/logo-wordpress.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
3
firefox/assets/more-arrow.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="11" height="6" viewBox="0 0 11 6" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 1L5.36713 4.88189C5.4429 4.94925 5.5571 4.94925 5.63287 4.88189L10 1" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 244 B |
BIN
firefox/assets/more-thing.png
Normal file
|
After Width: | Height: | Size: 659 B |
5
firefox/assets/navigate.svg
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11Z" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M1 6H11" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 1C7.25064 2.36918 7.96138 4.14602 8 6C7.96138 7.85398 7.25064 9.63082 6 11C4.74936 9.63082 4.03862 7.85398 4 6C4.03862 4.14602 4.74936 2.36918 6 1V1Z" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 658 B |
138
firefox/assets/nice-select.css
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
.nice-select {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
border: solid 1px #e8e8e8;
|
||||
box-sizing: border-box;
|
||||
clear: both;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
float: left;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
height: 42px;
|
||||
line-height: 40px;
|
||||
outline: none;
|
||||
padding-left: 18px;
|
||||
padding-right: 30px;
|
||||
position: relative;
|
||||
text-align: left !important;
|
||||
-webkit-transition: all 0.2s ease-in-out;
|
||||
transition: all 0.2s ease-in-out;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
width: auto; }
|
||||
.nice-select:hover {
|
||||
border-color: #dbdbdb; }
|
||||
.nice-select:active, .nice-select.open, .nice-select:focus {
|
||||
border-color: #999; }
|
||||
.nice-select:after {
|
||||
border-bottom: 2px solid #999;
|
||||
border-right: 2px solid #999;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 5px;
|
||||
margin-top: -4px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: 12px;
|
||||
top: 50%;
|
||||
-webkit-transform-origin: 66% 66%;
|
||||
-ms-transform-origin: 66% 66%;
|
||||
transform-origin: 66% 66%;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
-webkit-transition: all 0.15s ease-in-out;
|
||||
transition: all 0.15s ease-in-out;
|
||||
width: 5px; }
|
||||
.nice-select.open:after {
|
||||
-webkit-transform: rotate(-135deg);
|
||||
-ms-transform: rotate(-135deg);
|
||||
transform: rotate(-135deg); }
|
||||
.nice-select.open .list {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
-webkit-transform: scale(1) translateY(0);
|
||||
-ms-transform: scale(1) translateY(0);
|
||||
transform: scale(1) translateY(0); }
|
||||
.nice-select.disabled {
|
||||
border-color: #ededed;
|
||||
color: #999;
|
||||
pointer-events: none; }
|
||||
.nice-select.disabled:after {
|
||||
border-color: #cccccc; }
|
||||
.nice-select.wide {
|
||||
width: 100%; }
|
||||
.nice-select.wide .list {
|
||||
left: 0 !important;
|
||||
right: 0 !important; }
|
||||
.nice-select.right {
|
||||
float: right; }
|
||||
.nice-select.right .list {
|
||||
left: auto;
|
||||
right: 0; }
|
||||
.nice-select.small {
|
||||
font-size: 12px;
|
||||
height: 36px;
|
||||
line-height: 34px; }
|
||||
.nice-select.small:after {
|
||||
height: 4px;
|
||||
width: 4px; }
|
||||
.nice-select.small .option {
|
||||
line-height: 34px;
|
||||
min-height: 34px; }
|
||||
.nice-select .list {
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11);
|
||||
box-sizing: border-box;
|
||||
margin-top: 4px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
-webkit-transform-origin: 50% 0;
|
||||
-ms-transform-origin: 50% 0;
|
||||
transform-origin: 50% 0;
|
||||
-webkit-transform: scale(0.75) translateY(-21px);
|
||||
-ms-transform: scale(0.75) translateY(-21px);
|
||||
transform: scale(0.75) translateY(-21px);
|
||||
-webkit-transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out;
|
||||
transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out;
|
||||
z-index: 9; }
|
||||
.nice-select .list:hover .option:not(:hover) {
|
||||
background-color: transparent !important; }
|
||||
.nice-select .option {
|
||||
cursor: pointer;
|
||||
font-weight: 400;
|
||||
line-height: 40px;
|
||||
list-style: none;
|
||||
min-height: 40px;
|
||||
outline: none;
|
||||
padding-left: 18px;
|
||||
padding-right: 29px;
|
||||
text-align: left;
|
||||
-webkit-transition: all 0.2s;
|
||||
transition: all 0.2s; }
|
||||
.nice-select .option:hover, .nice-select .option.focus, .nice-select .option.selected.focus {
|
||||
background-color: #f6f6f6; }
|
||||
.nice-select .option.selected {
|
||||
font-weight: bold; }
|
||||
.nice-select .option.disabled {
|
||||
background-color: transparent;
|
||||
color: #999;
|
||||
cursor: default; }
|
||||
|
||||
.no-csspointerevents .nice-select .list {
|
||||
display: none; }
|
||||
|
||||
.no-csspointerevents .nice-select.open .list {
|
||||
display: block; }
|
||||
BIN
firefox/assets/preview.png
Normal file
|
After Width: | Height: | Size: 341 B |
11
firefox/assets/right.svg
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_326_2970)">
|
||||
<path d="M6.25 15L23.75 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M15 23.75L23.75 15L15 6.25" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_326_2970">
|
||||
<rect width="30" height="30" fill="white" transform="matrix(1 0 0 -1 0 30)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 508 B |
BIN
firefox/assets/save.png
Normal file
|
After Width: | Height: | Size: 302 B |
4
firefox/assets/start-record.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.5 16C12.6421 16 16 12.6421 16 8.5C16 4.35786 12.6421 1 8.5 1C4.35786 1 1 4.35786 1 8.5C1 12.6421 4.35786 16 8.5 16Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.25 8.5C6.25 9.74264 7.25736 10.75 8.5 10.75C9.74264 10.75 10.75 9.74264 10.75 8.5C10.75 7.25736 9.74264 6.25 8.5 6.25C7.25736 6.25 6.25 7.25736 6.25 8.5Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 565 B |
4
firefox/assets/stop.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="17" height="18" viewBox="0 0 17 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.5 16.5C12.6421 16.5 16 13.1421 16 9C16 4.85786 12.6421 1.5 8.5 1.5C4.35786 1.5 1 4.85786 1 9C1 13.1421 4.35786 16.5 8.5 16.5Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.75 6.75H6.25V11.25H10.75V6.75Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 453 B |
7
firefox/assets/target-active.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.00033 12.8337C10.222 12.8337 12.8337 10.222 12.8337 7.00033C12.8337 3.77866 10.222 1.16699 7.00033 1.16699C3.77866 1.16699 1.16699 3.77866 1.16699 7.00033C1.16699 10.222 3.77866 12.8337 7.00033 12.8337Z" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12.8333 7H10.5" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M3.50033 7H1.16699" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7 3.50033V1.16699" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7 12.8333V10.5" stroke="#6068D2" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 854 B |
7
firefox/assets/target.svg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.00033 12.8337C10.222 12.8337 12.8337 10.222 12.8337 7.00033C12.8337 3.77866 10.222 1.16699 7.00033 1.16699C3.77866 1.16699 1.16699 3.77866 1.16699 7.00033C1.16699 10.222 3.77866 12.8337 7.00033 12.8337Z" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12.8333 7H10.5" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M3.50033 7H1.16699" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7 3.50033V1.16699" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M7 12.8333V10.5" stroke="#A5A5AE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 854 B |
4
firefox/assets/up.svg
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15 23.75V6.25" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M23.75 15L15 6.25L6.25 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 326 B |
494
firefox/background.js
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
let actions = [];
|
||||
let newtaburl = "";
|
||||
|
||||
// Clear actions and append default ones
|
||||
const clearActions = () => {
|
||||
getCurrentTab().then((response) => {
|
||||
actions = [];
|
||||
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
let muteaction = {title:"Mute tab", desc:"Mute the current tab", type:"action", action:"mute", emoji:true, emojiChar:"🔇", keycheck:true, keys:['⌥','⇧', 'M']};
|
||||
let pinaction = {title:"Pin tab", desc:"Pin the current tab", type:"action", action:"pin", emoji:true, emojiChar:"📌", keycheck:true, keys:['⌥','⇧', 'P']};
|
||||
if (response.mutedInfo.muted) {
|
||||
muteaction = {title:"Unmute tab", desc:"Unmute the current tab", type:"action", action:"unmute", emoji:true, emojiChar:"🔈", keycheck:true, keys:['⌥','⇧', 'M']};
|
||||
}
|
||||
if (response.pinned) {
|
||||
pinaction = {title:"Unpin tab", desc:"Unpin the current tab", type:"action", action:"unpin", emoji:true, emojiChar:"📌", keycheck:true, keys:['⌥','⇧', 'P']};
|
||||
}
|
||||
actions = [
|
||||
{title:"New tab", desc:"Open a new tab", type:"action", action:"new-tab", emoji:true, emojiChar:"✨", keycheck:true, keys:['⌘','T']},
|
||||
{title:"Bookmark", desc:"Create a bookmark", type:"action", action:"create-bookmark", emoji:true, emojiChar:"📕", keycheck:true, keys:['⌘','D']},
|
||||
pinaction,
|
||||
{title:"Fullscreen", desc:"Make the page fullscreen", type:"action", action:"fullscreen", emoji:true, emojiChar:"🖥", keycheck:true, keys:['⌘', 'Ctrl', 'F']},
|
||||
muteaction,
|
||||
{title:"Reload", desc:"Reload the page", type:"action", action:"reload", emoji:true, emojiChar:"♻️", keycheck:true, keys:['⌘','⇧', 'R']},
|
||||
{title:"Help", desc:"Get help with Omni on GitHub", type:"action", action:"url", url:"https://github.com/alyssaxuu/omni", emoji:true, emojiChar:"🤔", keycheck:false},
|
||||
{title:"Compose email", desc:"Compose a new email", type:"action", action:"email", emoji:true, emojiChar:"✉️", keycheck:true, keys:['⌥','⇧', 'C']},
|
||||
{title:"Print page", desc:"Print the current page", type:"action", action:"print", emoji:true, emojiChar:"🖨️", keycheck:true, keys:['⌘', 'P']},
|
||||
{title:"New Notion page", desc:"Create a new Notion page", type:"action", action:"url", url:"https://notion.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-notion.png"), keycheck:false},
|
||||
{title:"New Sheets spreadsheet", desc:"Create a new Google Sheets spreadsheet", type:"action", action:"url", url:"https://sheets.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-sheets.png"), keycheck:false},
|
||||
{title:"New Docs document", desc:"Create a new Google Docs document", type:"action", action:"url", emoji:false, url:"https://docs.new", favIconUrl:browser.runtime.getURL("assets/logo-docs.png"), keycheck:false},
|
||||
{title:"New Slides presentation", desc:"Create a new Google Slides presentation", type:"action", action:"url", url:"https://slides.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-slides.png"), keycheck:false},
|
||||
{title:"New form", desc:"Create a new Google Forms form", type:"action", action:"url", url:"https://forms.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-forms.png"), keycheck:false},
|
||||
{title:"New Medium story", desc:"Create a new Medium story", type:"action", action:"url", url:"https://story.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-medium.png"), keycheck:false},
|
||||
{title:"New GitHub repository", desc:"Create a new GitHub repository", type:"action", action:"url", url:"https://github.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-github.png"), keycheck:false},
|
||||
{title:"New GitHub gist", desc:"Create a new GitHub gist", type:"action", action:"url", url:"https://gist.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-github.png"), keycheck:false},
|
||||
{title:"New CodePen pen", desc:"Create a new CodePen pen", type:"action", action:"url", url:"https://pen.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-codepen.png"), keycheck:false},
|
||||
{title:"New Excel spreadsheet", desc:"Create a new Excel spreadsheet", type:"action", action:"url", url:"https://excel.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-excel.png"), keycheck:false},
|
||||
{title:"New PowerPoint presentation", desc:"Create a new PowerPoint presentation", type:"action", url:"https://powerpoint.new", action:"url", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-powerpoint.png"), keycheck:false},
|
||||
{title:"New Word document", desc:"Create a new Word document", type:"action", action:"url", url:"https://word.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-word.png"), keycheck:false},
|
||||
{title:"Create a whiteboard", desc:"Create a collaborative whiteboard", type:"action", action:"url", url:"https://whiteboard.new", emoji:true, emojiChar:"🧑🏫", keycheck:false},
|
||||
{title:"Record a video", desc:"Record and edit a video", type:"action", action:"url", url:"https://recording.new", emoji:true, emojiChar:"📹", keycheck:false},
|
||||
{title:"Create a Figma file", desc:"Create a new Figma file", type:"action", action:"url", url:"https://figma.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-figma.png"), keycheck:false},
|
||||
{title:"Create a FigJam file", desc:"Create a new FigJam file", type:"action", action:"url", url:"https://figjam.new", emoji:true, emojiChar:"🖌", keycheck:false},
|
||||
{title:"Hunt a product", desc:"Submit a product to Product Hunt", type:"action", action:"url", url:"https://www.producthunt.com/posts/new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-producthunt.png"), keycheck:false},
|
||||
{title:"Make a tweet", desc:"Make a tweet on Twitter", type:"action", action:"url", url:"https://twitter.com/intent/tweet", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-twitter.png"), keycheck:false},
|
||||
{title:"Create a playlist", desc:"Create a Spotify playlist", type:"action", action:"url", url:"https://playlist.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-spotify.png"), keycheck:false},
|
||||
{title:"Create a Canva design", desc:"Create a new design with Canva", type:"action", action:"url", url:"https://design.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-canva.png"), keycheck:false},
|
||||
{title:"Create a new podcast episode", desc:"Create a new podcast episode with Anchor", type:"action", action:"url", url:"https://episode.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-anchor.png"), keycheck:false},
|
||||
{title:"Edit an image", desc:"Edit an image with Adobe Photoshop", type:"action", action:"url", url:"https://photo.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-photoshop.png"), keycheck:false},
|
||||
{title:"Convert to PDF", desc:"Convert a file to PDF", type:"action", action:"url", url:"https://pdf.new", emoji:true, emojiChar:"📄", keycheck:false},
|
||||
{title:"Scan a QR code", desc:"Scan a QR code with your camera", type:"action", action:"url", url:"https://scan.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-qr.png"), keycheck:false},
|
||||
{title:"Add a task to Asana", desc:"Create a new task in Asana", type:"action", action:"url", url:"https://task.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-asana.png"), keycheck:false},
|
||||
{title:"Add an issue to Linear", desc:"Create a new issue in Linear", type:"action", action:"url", url:"https://linear.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-linear.png"), keycheck:false},
|
||||
{title:"Add a task to WIP", desc:"Create a new task in WIP", type:"action", action:"url", url:"https://todo.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-wip.png"), keycheck:false},
|
||||
{title:"Create an event", desc:"Add an event to Google Calendar", type:"action", action:"url", url:"https://cal.new", emoji:false, favIconUrl:browser.runtime.getURL("assets/logo-calendar.png"), keycheck:false},
|
||||
{title:"Add a note", desc:"Add a note to Google Keep", type:"action", action:"url", emoji:false, url:"https://note.new", favIconUrl:browser.runtime.getURL("assets/logo-keep.png"), keycheck:false},
|
||||
{title:"New meeting", desc:"Start a Google Meet meeting", type:"action", action:"url", emoji:false, url:"https://meet.new", favIconUrl:browser.runtime.getURL("assets/logo-meet.png"), keycheck:false},
|
||||
{title:"Browsing history", desc:"Browse through your browsing history", type:"action", action:"history", emoji:true, emojiChar:"🗂", keycheck:true, keys:['⌘','Y']},
|
||||
{title:"Incognito mode", desc:"Open an incognito window", type:"action", action:"incognito", emoji:true, emojiChar:"🕵️", keycheck:true, keys:['⌘','⇧', 'N']},
|
||||
{title:"Downloads", desc:"Browse through your downloads", type:"action", action:"downloads", emoji:true, emojiChar:"📦", keycheck:true, keys:['⌘','⇧', 'J']},
|
||||
{title:"Extensions", desc:"Manage your browser Extensions", type:"action", action:"extensions", emoji:true, emojiChar:"🧩", keycheck:false, keys:['⌘','D']},
|
||||
{title:"browser settings", desc:"Open the browser settings", type:"action", action:"settings", emoji:true, emojiChar:"⚙️", keycheck:true, keys:['⌘',',']},
|
||||
{title:"Scroll to bottom", desc:"Scroll to the bottom of the page", type:"action", action:"scroll-bottom", emoji:true, emojiChar:"👇", keycheck:true, keys:['⌘','↓']},
|
||||
{title:"Scroll to top", desc:"Scroll to the top of the page", type:"action", action:"scroll-top", emoji:true, emojiChar:"👆", keycheck:true, keys:['⌘','↑']},
|
||||
{title:"Go back", desc:"Go back in history for the current tab", type:"action", action:"go-back", emoji:true, emojiChar:"👈", keycheck:true, keys:['⌘','←']},
|
||||
{title:"Go forward", desc:"Go forward in history for the current tab", type:"action", action:"go-forward", emoji:true, emojiChar:"👉", keycheck:true, keys:['⌘','→']},
|
||||
{title:"Duplicate tab", desc:"Make a copy of the current tab", type:"action", action:"duplicate-tab", emoji:true, emojiChar:"📋", keycheck:true, keys:['⌥','⇧', 'D']},
|
||||
{title:"Close tab", desc:"Close the current tab", type:"action", action:"close-tab", emoji:true, emojiChar:"🗑", keycheck:true, keys:['⌘','W']},
|
||||
{title:"Close window", desc:"Close the current window", type:"action", action:"close-window", emoji:true, emojiChar:"💥", keycheck:true, keys:['⌘','⇧', 'W']},
|
||||
{title:"Manage browsing data", desc:"Manage your browsing data", type:"action", action:"manage-data", emoji:true, emojiChar:"🔬", keycheck:true, keys:['⌘','⇧', 'Delete']},
|
||||
{title:"Clear all browsing data", desc:"Clear all of your browsing data", type:"action", action:"remove-all", emoji:true, emojiChar:"🧹", keycheck:false, keys:['⌘','D']},
|
||||
{title:"Clear browsing history", desc:"Clear all of your browsing history", type:"action", action:"remove-history", emoji:true, emojiChar:"🗂", keycheck:false, keys:['⌘','D']},
|
||||
{title:"Clear cookies", desc:"Clear all cookies", type:"action", action:"remove-cookies", emoji:true, emojiChar:"🍪", keycheck:false, keys:['⌘','D']},
|
||||
{title:"Clear cache", desc:"Clear the cache", type:"action", action:"remove-cache", emoji:true, emojiChar:"🗄", keycheck:false, keys:['⌘','D']},
|
||||
{title:"Clear local storage", desc:"Clear the local storage", type:"action", action:"remove-local-storage", emoji:true, emojiChar:"📦", keycheck:false, keys:['⌘','D']},
|
||||
{title:"Clear passwords", desc:"Clear all saved passwords", type:"action", action:"remove-passwords", emoji:true, emojiChar:"🔑", keycheck:false, keys:['⌘','D']},
|
||||
];
|
||||
|
||||
if (!isMac) {
|
||||
for (action of actions) {
|
||||
switch (action.action) {
|
||||
case "reload":
|
||||
action.keys = ['F5'];
|
||||
break;
|
||||
case "fullscreen":
|
||||
action.keys = ['F11'];
|
||||
break;
|
||||
case "downloads":
|
||||
action.keys = ['Ctrl', 'J'];
|
||||
break;
|
||||
case "settings":
|
||||
action.keycheck = false;
|
||||
break;
|
||||
case "history":
|
||||
action.keys = ['Ctrl', 'H'];
|
||||
break;
|
||||
case "go-back":
|
||||
action.keys = ['Alt','←'];
|
||||
break;
|
||||
case "go-forward":
|
||||
action.keys = ['Alt','→']
|
||||
break;
|
||||
case "scroll-top":
|
||||
action.keys = ['Home'];
|
||||
break;
|
||||
case "scroll-bottom":
|
||||
action.keys = ['End'];
|
||||
break;
|
||||
}
|
||||
for (const key in action.keys) {
|
||||
if (action.keys[key] === "⌘") {
|
||||
action.keys[key] = "Ctrl";
|
||||
} else if (action.keys[key] === "⌥") {
|
||||
action.keys[key] = "Alt";
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Open on install
|
||||
browser.runtime.onInstalled.addListener((object) => {
|
||||
// Inject Omni on install
|
||||
const manifest = browser.runtime.getManifest();
|
||||
|
||||
const injectIntoTab = (tab) => {
|
||||
const scripts = manifest.content_scripts[0].js;
|
||||
const s = scripts.length;
|
||||
|
||||
for (let i = 0; i < s; i++) {
|
||||
browser.scripting.executeScript({
|
||||
target: { tabId: tab.id },
|
||||
files: [scripts[i]],
|
||||
});
|
||||
}
|
||||
|
||||
browser.scripting.insertCSS({
|
||||
target: { tabId: tab.id },
|
||||
files: [manifest.content_scripts[0].css[0]],
|
||||
});
|
||||
};
|
||||
|
||||
// Get all windows
|
||||
browser.windows.getAll(
|
||||
{
|
||||
populate: true,
|
||||
},
|
||||
(windows) => {
|
||||
let currentWindow;
|
||||
const w = windows.length;
|
||||
|
||||
for (let i = 0; i < w; i++) {
|
||||
currentWindow = windows[i];
|
||||
|
||||
let currentTab;
|
||||
const t = currentWindow.tabs.length;
|
||||
|
||||
for (let j = 0; j < t; j++) {
|
||||
currentTab = currentWindow.tabs[j];
|
||||
if (!currentTab.url.includes("browser://") && !currentTab.url.includes("browser-extension://") && !currentTab.url.includes("browser.google.com")) {
|
||||
injectIntoTab(currentTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (object.reason === "install") {
|
||||
browser.tabs.create({ url: "https://github.com/alyssaxuu/omni" });
|
||||
}
|
||||
});
|
||||
|
||||
// Check when the extension button is clicked
|
||||
browser.browserAction.onClicked.addListener((tab) => {
|
||||
browser.tabs.sendMessage(tab.id, {request: "open-omni"});
|
||||
});
|
||||
|
||||
// Listen for the open omni shortcut
|
||||
browser.commands.onCommand.addListener((command) => {
|
||||
if (command === "open-omni") {
|
||||
getCurrentTab().then((response) => {
|
||||
if (!response.url.includes("browser://") && !response.url.includes("browser.google.com")) {
|
||||
browser.tabs.sendMessage(response.id, {request: "open-omni"});
|
||||
} else {
|
||||
browser.tabs.create({
|
||||
url: "./newtab.html"
|
||||
}).then(() => {
|
||||
newtaburl = response.url;
|
||||
browser.tabs.remove(response.id);
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get the current tab
|
||||
const getCurrentTab = async () => {
|
||||
const queryOptions = { active: true, currentWindow: true };
|
||||
const [tab] = await browser.tabs.query(queryOptions);
|
||||
return tab;
|
||||
}
|
||||
|
||||
// Restore the new tab page (workaround to show Omni in new tab page)
|
||||
function restoreNewTab() {
|
||||
getCurrentTab().then((response) => {
|
||||
browser.tabs.create({
|
||||
url: newtaburl
|
||||
}).then(() => {
|
||||
browser.tabs.remove(response.id);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const resetOmni = () => {
|
||||
clearActions();
|
||||
getTabs();
|
||||
getBookmarks();
|
||||
var search = [
|
||||
{title:"Search", desc:"Search for a query", type:"action", action:"search", emoji:true, emojiChar:"🔍", keycheck:false},
|
||||
{title:"Search", desc:"Go to website", type:"action", action:"goto", emoji:true, emojiChar:"🔍", keycheck:false}
|
||||
];
|
||||
actions = search.concat(actions);
|
||||
}
|
||||
|
||||
// Check if tabs have changed and actions need to be fetched again
|
||||
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => resetOmni());
|
||||
browser.tabs.onCreated.addListener((tab) => resetOmni());
|
||||
browser.tabs.onRemoved.addListener((tabId, changeInfo) => resetOmni());
|
||||
|
||||
// Get tabs to populate in the actions
|
||||
const getTabs = () => {
|
||||
browser.tabs.query({}, (tabs) => {
|
||||
tabs.forEach((tab) => {
|
||||
tab.desc = "browser tab";
|
||||
tab.keycheck = false;
|
||||
tab.action = "switch-tab";
|
||||
tab.type = "tab";
|
||||
})
|
||||
actions = tabs.concat(actions);
|
||||
});
|
||||
}
|
||||
|
||||
// Get bookmarks to populate in the actions
|
||||
const getBookmarks = () => {
|
||||
const process_bookmark = (bookmarks) => {
|
||||
for (const bookmark of bookmarks) {
|
||||
if (bookmark.url) {
|
||||
actions.push({title:bookmark.title, desc:"Bookmark", id:bookmark.id, url:bookmark.url, type:"bookmark", action:"bookmark", emoji:true, emojiChar:"⭐️", keycheck:false})
|
||||
}
|
||||
if (bookmark.children) {
|
||||
process_bookmark(bookmark.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
browser.bookmarks.getRecent(100, process_bookmark);
|
||||
}
|
||||
|
||||
// Lots of different actions
|
||||
const switchTab = (tab) => {
|
||||
browser.tabs.highlight({
|
||||
tabs: tab.index,
|
||||
windowId: tab.windowId
|
||||
})
|
||||
browser.windows.update(
|
||||
tab.windowId,
|
||||
{ focused: true }
|
||||
)
|
||||
}
|
||||
const goBack = (tab) => {
|
||||
browser.tabs.goBack({
|
||||
tabs: tab.index
|
||||
})
|
||||
}
|
||||
const goForward = (tab) => {
|
||||
browser.tabs.goForward({
|
||||
tabs: tab.index
|
||||
})
|
||||
}
|
||||
const duplicateTab = (tab) => {
|
||||
getCurrentTab().then((response) => {
|
||||
browser.tabs.duplicate(response.id);
|
||||
})
|
||||
}
|
||||
const createBookmark = (tab) => {
|
||||
getCurrentTab().then((response) => {
|
||||
browser.bookmarks.create({
|
||||
title: response.title,
|
||||
url: response.url
|
||||
});
|
||||
})
|
||||
}
|
||||
const muteTab = (mute) =>{
|
||||
getCurrentTab().then((response) => {
|
||||
browser.tabs.update(response.id, {"muted": mute})
|
||||
});
|
||||
}
|
||||
const reloadTab = () => {
|
||||
browser.tabs.reload();
|
||||
}
|
||||
const pinTab = (pin) => {
|
||||
getCurrentTab().then((response) => {
|
||||
browser.tabs.update(response.id, {"pinned": pin})
|
||||
});
|
||||
}
|
||||
const clearAllData = () => {
|
||||
browser.browsingData.remove({
|
||||
"since": (new Date()).getTime()
|
||||
}, {
|
||||
"appcache": true,
|
||||
"cache": true,
|
||||
"cacheStorage": true,
|
||||
"cookies": true,
|
||||
"downloads": true,
|
||||
"fileSystems": true,
|
||||
"formData": true,
|
||||
"history": true,
|
||||
"indexedDB": true,
|
||||
"localStorage": true,
|
||||
"passwords": true,
|
||||
"serviceWorkers": true,
|
||||
"webSQL": true
|
||||
});
|
||||
}
|
||||
const clearBrowsingData = () => {
|
||||
browser.browsingData.removeHistory({"since": 0});
|
||||
}
|
||||
const clearCookies = () =>{
|
||||
browser.browsingData.removeCookies({"since": 0});
|
||||
}
|
||||
const clearCache = () => {
|
||||
browser.browsingData.removeCache({"since": 0});
|
||||
}
|
||||
const clearLocalStorage = () => {
|
||||
browser.browsingData.removeLocalStorage({"since": 0});
|
||||
}
|
||||
const clearPasswords = () => {
|
||||
browser.browsingData.removePasswords({"since": 0});
|
||||
}
|
||||
const openbrowserUrl = (url) => {
|
||||
browser.tabs.create({url: 'browser://'+url+'/'});
|
||||
}
|
||||
const openIncognito = () => {
|
||||
browser.windows.create({"incognito": true});
|
||||
}
|
||||
const closeWindow = (id) => {
|
||||
browser.windows.remove(id);
|
||||
}
|
||||
const closeTab = (tab) => {
|
||||
browser.tabs.remove(tab.id);
|
||||
}
|
||||
const closeCurrentTab = () => {
|
||||
getCurrentTab().then(closeTab)
|
||||
}
|
||||
const removeBookmark = (bookmark) => {
|
||||
browser.bookmarks.remove(bookmark.id);
|
||||
}
|
||||
|
||||
// Receive messages from any tab
|
||||
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
switch (message.request) {
|
||||
case "get-actions":
|
||||
resetOmni();
|
||||
sendResponse({actions: actions});
|
||||
break;
|
||||
case "switch-tab":
|
||||
switchTab(message.tab);
|
||||
break;
|
||||
case "go-back":
|
||||
goBack(message.tab);
|
||||
break;
|
||||
case "go-forward":
|
||||
goForward(message.tab);
|
||||
break;
|
||||
case "duplicate-tab":
|
||||
duplicateTab(message.tab);
|
||||
break;
|
||||
case "create-bookmark":
|
||||
createBookmark(message.tab);
|
||||
break;
|
||||
case "mute":
|
||||
muteTab(true);
|
||||
break;
|
||||
case "unmute":
|
||||
muteTab(false);
|
||||
break;
|
||||
case "reload":
|
||||
reloadTab();
|
||||
break;
|
||||
case "pin":
|
||||
pinTab(true);
|
||||
break;
|
||||
case "unpin":
|
||||
pinTab(false);
|
||||
break;
|
||||
case "remove-all":
|
||||
clearAllData();
|
||||
break;
|
||||
case "remove-history":
|
||||
clearBrowsingData();
|
||||
break;
|
||||
case "remove-cookies":
|
||||
clearCookies();
|
||||
break;
|
||||
case "remove-cache":
|
||||
clearCache();
|
||||
break;
|
||||
case "remove-local-storage":
|
||||
clearLocalStorage();
|
||||
break;
|
||||
case "remove-passwords":
|
||||
clearPasswords();
|
||||
case "history": // Fallthrough
|
||||
case "downloads":
|
||||
case "extensions":
|
||||
case "settings":
|
||||
case "extensions/shortcuts":
|
||||
openbrowserUrl(message.request);
|
||||
break;
|
||||
case "manage-data":
|
||||
openbrowserUrl("settings/clearBrowserData");
|
||||
break;
|
||||
case "incognito":
|
||||
openIncognito();
|
||||
break;
|
||||
case "close-window":
|
||||
closeWindow(sender.tab.windowId);
|
||||
break;
|
||||
case "close-tab":
|
||||
closeCurrentTab();
|
||||
break;
|
||||
case "search-history":
|
||||
browser.history.search({text:message.query, maxResults:1000, startTime:31536000000*5}).then((data) => {
|
||||
data.forEach((action, index) => {
|
||||
action.type = "history";
|
||||
action.emoji = true;
|
||||
action.emojiChar = "🏛";
|
||||
action.action = "history";
|
||||
action.keyCheck = false;
|
||||
});
|
||||
sendResponse({history:data});
|
||||
})
|
||||
return true;
|
||||
case "search-bookmarks":
|
||||
browser.bookmarks.search({query:message.query}).then((data) => {
|
||||
// The index property of the bookmark appears to be causing issues, iterating separately...
|
||||
data.filter(x => x.index == 0).forEach((action, index) => {
|
||||
if (!action.url) {
|
||||
data.splice(index, 1);
|
||||
}
|
||||
action.type = "bookmark";
|
||||
action.emoji = true;
|
||||
action.emojiChar = "⭐️";
|
||||
action.action = "bookmark";
|
||||
action.keyCheck = false;
|
||||
})
|
||||
data.forEach((action, index) => {
|
||||
if (!action.url) {
|
||||
data.splice(index, 1);
|
||||
}
|
||||
action.type = "bookmark";
|
||||
action.emoji = true;
|
||||
action.emojiChar = "⭐️";
|
||||
action.action = "bookmark";
|
||||
action.keyCheck = false;
|
||||
})
|
||||
sendResponse({bookmarks:data});
|
||||
})
|
||||
return true;
|
||||
case "remove":
|
||||
if (message.type == "bookmark") {
|
||||
removeBookmark(message.action);
|
||||
} else {
|
||||
closeTab(message.action);
|
||||
}
|
||||
break;
|
||||
case "search":
|
||||
browser.search.query(
|
||||
{text:message.query}
|
||||
)
|
||||
break;
|
||||
case "restore-new-tab":
|
||||
restoreNewTab();
|
||||
break;
|
||||
case "close-omni":
|
||||
getCurrentTab().then((response) => {
|
||||
browser.tabs.sendMessage(response.id, {request: "close-omni"});
|
||||
});
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// Get actions
|
||||
resetOmni();
|
||||
387
firefox/content.css
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
.omni-extension {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Scrollbar size */
|
||||
.omni-extension ::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.omni-extension ::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(127, 127, 127, 0.6);
|
||||
background-clip: padding-box;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.omni-extension ::-webkit-scrollbar-thumb:vertical:hover,
|
||||
.omni-extension ::-webkit-scrollbar-thumb:horizontal:hover {
|
||||
background-color: rgb(110, 110, 110);
|
||||
}
|
||||
|
||||
.omni-extension ::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.omni-extension ::-webkit-scrollbar-thumb:vertical:active,
|
||||
.omni-extension ::-webkit-scrollbar-thumb:horizontal:active {
|
||||
background: rgba(95, 91, 91, 1);
|
||||
}
|
||||
|
||||
.omni-extension ::-webkit-scrollbar-corner {
|
||||
background: none;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #1e2128;
|
||||
--border: #35373e;
|
||||
--text: #f1f1f1;
|
||||
--text-2: #c5c6ca;
|
||||
--text-3: #a5a5ae;
|
||||
--select: #17191e;
|
||||
--accent: #6068d2;
|
||||
--accent-hover: #484fac;
|
||||
--shortcut: #383e4a;
|
||||
--placeholder: #63687b;
|
||||
--background-2: #292d36;
|
||||
}
|
||||
}
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
--background: #fafcff;
|
||||
--border: #f2f3fb;
|
||||
--text: #2b2d41;
|
||||
--text-2: #2b2d41;
|
||||
--text-3: #929db2;
|
||||
--select: #eff3f9;
|
||||
--accent: #6068d2;
|
||||
--accent-hover: #484fac;
|
||||
--shortcut: #dadeea;
|
||||
--placeholder: #bac2d1;
|
||||
--background-2: #292d36;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url("moz-extension://__MSG_@@extension_id__/assets/Inter-Regular.ttf");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: url("moz-extension://__MSG_@@extension_id__/assets/Inter-Medium.ttf");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url("moz-extension://__MSG_@@extension_id__/assets/Inter-SemiBold.ttf");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: url("moz-extension://__MSG_@@extension_id__/assets/Inter-Bold.ttf");
|
||||
}
|
||||
.omni-extension * {
|
||||
display: block;
|
||||
width: unset;
|
||||
box-shadow: unset;
|
||||
padding: unset;
|
||||
margin: unset;
|
||||
background-color: unset;
|
||||
border-radius: unset;
|
||||
}
|
||||
.omni-extension .omni-item-details * {
|
||||
line-height: normal;
|
||||
}
|
||||
.omni-extension {
|
||||
font-family: Inter !important;
|
||||
z-index: 99999999999;
|
||||
}
|
||||
.omni-extension #omni-wrap {
|
||||
position: fixed;
|
||||
width: 700px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 5px;
|
||||
margin: auto;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
z-index: 9999999999;
|
||||
height: 540px;
|
||||
transition: all 0.2s cubic-bezier(0.05, 0.03, 0.35, 1);
|
||||
pointer-events: all;
|
||||
}
|
||||
.omni-extension #omni {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
background: var(--background);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 5px;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 9999999998;
|
||||
height: fit-content;
|
||||
transition: all 0.2s cubic-bezier(0.05, 0.03, 0.35, 1);
|
||||
display: block;
|
||||
}
|
||||
.omni-closing #omni {
|
||||
transform: scale(0.9);
|
||||
opacity: 0;
|
||||
}
|
||||
.omni-closing {
|
||||
pointer-events: none;
|
||||
display: none !important;
|
||||
}
|
||||
.omni-extension #omni-overlay {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
background-color: #000;
|
||||
z-index: 9999;
|
||||
opacity: 0.6;
|
||||
transition: all 0.1s cubic-bezier(0.05, 0.03, 0.35, 1);
|
||||
}
|
||||
.omni-closing #omni-overlay {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.omni-extension #omni-head {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
width: 95%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.omni-extension #omni-name {
|
||||
color: var(--text);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
float: left;
|
||||
}
|
||||
.omni-extension #omni-close {
|
||||
color: var(--text-3);
|
||||
float: right;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.omni-extension #omni-close span {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.omni-extension .omni-shortcut {
|
||||
display: inline-block !important;
|
||||
font-size: 13px;
|
||||
border-radius: 5px;
|
||||
background-color: var(--shortcut);
|
||||
color: var(--text);
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
min-width: 20px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
.omni-extension input {
|
||||
background: transparent;
|
||||
border: 0px;
|
||||
outline: none;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
height: 50px;
|
||||
width: 92%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
color: var(--text);
|
||||
caret-color: var(--accent);
|
||||
font-family: Inter !important;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
border: 0px;
|
||||
box-shadow: none;
|
||||
}
|
||||
.omni-extension ::placeholder {
|
||||
color: var(--placeholder);
|
||||
opacity: 1;
|
||||
}
|
||||
.omni-extension :-ms-input-placeholder {
|
||||
color: var(--placeholder);
|
||||
}
|
||||
.omni-extension ::-ms-input-placeholder {
|
||||
color: var(--placeholder);
|
||||
}
|
||||
.omni-extension #omni-list {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
max-height: 400px;
|
||||
border-top: 1px solid var(--border);
|
||||
position: relative;
|
||||
}
|
||||
.omni-extension .omni-item {
|
||||
height: 60px;
|
||||
width: 100%;
|
||||
}
|
||||
.omni-extension .omni-item:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.omni-extension .omni-item-active {
|
||||
background-color: var(--select);
|
||||
position: relative;
|
||||
}
|
||||
.omni-extension .omni-item-active:before {
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
display: block;
|
||||
content: "";
|
||||
width: 2px;
|
||||
background-color: var(--accent);
|
||||
}
|
||||
.omni-extension .omni-select {
|
||||
float: right;
|
||||
vertical-align: middle;
|
||||
color: var(--text-3);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
display: none;
|
||||
margin-top: 20px;
|
||||
margin-right: 5%;
|
||||
}
|
||||
.omni-extension .omni-select span {
|
||||
margin-left: 3px;
|
||||
}
|
||||
.omni-extension .omni-item-active .omni-select {
|
||||
display: block !important;
|
||||
}
|
||||
.omni-extension .omni-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-left: 5%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-top: -12px;
|
||||
}
|
||||
.omni-extension .omni-emoji-action {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-top: -12px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
margin-left: 5%;
|
||||
font-size: 18px;
|
||||
}
|
||||
.omni-extension .omni-item-details {
|
||||
display: inline-block !important;
|
||||
margin-left: 10px;
|
||||
vertical-align: middle;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.omni-extension .omni-item-name {
|
||||
color: var(--text-2);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 460px;
|
||||
}
|
||||
.omni-extension .omni-item-active .omni-item-name {
|
||||
color: var(--text) !important;
|
||||
}
|
||||
.omni-extension .omni-item-desc {
|
||||
color: var(--text-3);
|
||||
margin-top: 5px;
|
||||
font-size: 14px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 460px;
|
||||
}
|
||||
.omni-extension #omni-footer {
|
||||
height: 45px;
|
||||
line-height: 45px;
|
||||
border-top: 1px solid var(--border);
|
||||
width: 92%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.omni-extension #omni-results {
|
||||
color: var(--text-3);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
float: left;
|
||||
}
|
||||
.omni-extension #omni-arrows {
|
||||
color: var(--text-3);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
float: right;
|
||||
}
|
||||
.omni-extension #omni-arrows span {
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.omni-extension .omni-keys {
|
||||
float: right;
|
||||
vertical-align: middle;
|
||||
font-weight: 500;
|
||||
margin-top: 20px;
|
||||
margin-right: 5%;
|
||||
}
|
||||
.omni-extension .omni-item-active .omni-keys {
|
||||
display: none !important;
|
||||
}
|
||||
.omni-extension .omni-keys span {
|
||||
margin-left: 3px;
|
||||
}
|
||||
#omni-extension-toast {
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
position: fixed;
|
||||
width: -moz-max-content;
|
||||
color: var(--text);
|
||||
bottom: 10px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
margin: auto;
|
||||
background: var(--background);
|
||||
border-radius: 5px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
display: block;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: all 0.2s cubic-bezier(0.05, 0.03, 0.35, 1);
|
||||
z-index: 99999999;
|
||||
display: block;
|
||||
}
|
||||
#omni-extension-toast img {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.omni-show-toast {
|
||||
bottom: 20px !important;
|
||||
opacity: 1 !important;
|
||||
visibility: visible !important;
|
||||
}
|
||||
23
firefox/content.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div id="omni-extension" class="omni-closing omni-extension">
|
||||
<div id="omni-wrap">
|
||||
<div id="omni">
|
||||
<div id="omni-search">
|
||||
<input placeholder="Type a command or search">
|
||||
</div>
|
||||
<div id="omni-list">
|
||||
</div>
|
||||
<div id="omni-footer">
|
||||
<div id="omni-results">153 results</div>
|
||||
<div id="omni-arrows">Use arrow keys <span class="omni-shortcut">↑</span><span class="omni-shortcut">↓</span> to navigate</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="omni-overlay"></div>
|
||||
</div>
|
||||
<div id="omni-extension-toast"><img src=''><span>The action has been successful</span></div>
|
||||
</body>
|
||||
</html>
|
||||
449
firefox/content.js
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
// Workaround to capture Esc key on certain sites
|
||||
var isOpen = false;
|
||||
document.onkeyup = (e) => {
|
||||
if (e.key == "Escape" && isOpen) {
|
||||
browser.runtime.sendMessage({request:"close-omni"})
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
var actions = [];
|
||||
var isFiltered = false;
|
||||
|
||||
// Append the omni into the current page
|
||||
$.get(browser.runtime.getURL('/content.html'), (data) => {
|
||||
$(data).appendTo('body');
|
||||
|
||||
// Get checkmark image for toast
|
||||
$("#omni-extension-toast img").attr("src", browser.runtime.getURL("assets/check.svg"));
|
||||
|
||||
// Request actions from the background
|
||||
browser.runtime.sendMessage({request:"get-actions"}, (response) => {
|
||||
actions = response.actions;
|
||||
populateOmni();
|
||||
});
|
||||
|
||||
// New tab page workaround
|
||||
if (window.location.href == "browser-extension://mpanekjjajcabgnlbabmopeenljeoggm/newtab.html") {
|
||||
isOpen = true;
|
||||
$("#omni-extension").removeClass("omni-closing");
|
||||
window.setTimeout(() => {
|
||||
$("#omni-extension input").focus();
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
function renderAction(action, index, keys, img) {
|
||||
var skip = "";
|
||||
if (action.action == "search" || action.action == "goto") {
|
||||
skip = "style='display:none'";
|
||||
}
|
||||
if (index != 0) {
|
||||
$("#omni-extension #omni-list").append("<div class='omni-item' "+skip+" data-index='"+index+"' data-type='"+action.type+"'>"+img+"<div class='omni-item-details'><div class='omni-item-name'>"+action.title+"</div><div class='omni-item-desc'>"+action.desc+"</div></div>"+keys+"<div class='omni-select'>Select <span class='omni-shortcut'>⏎</span></div></div>");
|
||||
} else {
|
||||
$("#omni-extension #omni-list").append("<div class='omni-item omni-item-active' "+skip+" data-index='"+index+"' data-type='"+action.type+"'>"+img+"<div class='omni-item-details'><div class='omni-item-name'>"+action.title+"</div><div class='omni-item-desc'>"+action.desc+"</div></div>"+keys+"<div class='omni-select'>Select <span class='omni-shortcut'>⏎</span></div></div>");
|
||||
}
|
||||
if (!action.emoji) {
|
||||
var loadimg = new Image();
|
||||
loadimg.src = action.favIconUrl;
|
||||
|
||||
// Favicon doesn't load, use a fallback
|
||||
loadimg.onerror = () => {
|
||||
$(".omni-item[data-index='"+index+"'] img").attr("src", browser.runtime.getURL("/assets/globe.svg"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add actions to the omni
|
||||
function populateOmni() {
|
||||
$("#omni-extension #omni-list").html("");
|
||||
actions.forEach((action, index) => {
|
||||
var keys = "";
|
||||
if (action.keycheck) {
|
||||
keys = "<div class='omni-keys'>";
|
||||
action.keys.forEach(function(key){
|
||||
keys += "<span class='omni-shortcut'>"+key+"</span>";
|
||||
});
|
||||
keys += "</div>";
|
||||
}
|
||||
|
||||
// Check if the action has an emoji or a favicon
|
||||
if (!action.emoji) {
|
||||
var onload = 'if ("naturalHeight" in this) {if (this.naturalHeight + this.naturalWidth === 0) {this.onerror();return;}} else if (this.width + this.height == 0) {this.onerror();return;}';
|
||||
var img = "<img src='"+action.favIconUrl+"' alt='favicon' onload='"+onload+"' onerror='this.src=""+browser.runtime.getURL("/assets/globe.svg")+""' class='omni-icon'>";
|
||||
renderAction(action, index, keys, img);
|
||||
} else {
|
||||
var img = "<span class='omni-emoji-action'>"+action.emojiChar+"</span>";
|
||||
renderAction(action, index, keys, img);
|
||||
}
|
||||
})
|
||||
$(".omni-extension #omni-results").html(actions.length+" results");
|
||||
}
|
||||
|
||||
// Add filtered actions to the omni
|
||||
function populateOmniFilter(actions) {
|
||||
isFiltered = true;
|
||||
$("#omni-extension #omni-list").html("");
|
||||
actions.forEach((action, index) => {
|
||||
var keys = "";
|
||||
if (action.keycheck) {
|
||||
keys = "<div class='omni-keys'>";
|
||||
action.keys.forEach(function(key){
|
||||
keys += "<span class='omni-shortcut'>"+key+"</span>";
|
||||
});
|
||||
keys += "</div>";
|
||||
}
|
||||
var img = "<img src='"+action.favIconUrl+"' alt='favicon' onerror='this.src=""+browser.runtime.getURL("/assets/globe.svg")+""' class='omni-icon'>";
|
||||
if (action.emoji) {
|
||||
img = "<span class='omni-emoji-action'>"+action.emojiChar+"</span>"
|
||||
}
|
||||
if (index != 0) {
|
||||
$("#omni-extension #omni-list").append("<div class='omni-item' data-index='"+index+"' data-type='"+action.type+"' data-url='"+action.url+"'>"+img+"<div class='omni-item-details'><div class='omni-item-name'>"+action.title+"</div><div class='omni-item-desc'>"+action.url+"</div></div>"+keys+"<div class='omni-select'>Select <span class='omni-shortcut'>⏎</span></div></div>");
|
||||
} else {
|
||||
$("#omni-extension #omni-list").append("<div class='omni-item omni-item-active' data-index='"+index+"' data-type='"+action.type+"' data-url='"+action.url+"'>"+img+"<div class='omni-item-details'><div class='omni-item-name'>"+action.title+"</div><div class='omni-item-desc'>"+action.url+"</div></div>"+keys+"<div class='omni-select'>Select <span class='omni-shortcut'>⏎</span></div></div>");
|
||||
}
|
||||
})
|
||||
$(".omni-extension #omni-results").html(actions.length+" results");
|
||||
}
|
||||
|
||||
// Open the omni
|
||||
function openOmni() {
|
||||
browser.runtime.sendMessage({request:"get-actions"}, (response) => {
|
||||
isOpen = true;
|
||||
actions = response.actions;
|
||||
$("#omni-extension input").val("");
|
||||
populateOmni();
|
||||
$("html, body").stop();
|
||||
$("#omni-extension").removeClass("omni-closing");
|
||||
window.setTimeout(() => {
|
||||
$("#omni-extension input").focus();
|
||||
focusLock.on($("#omni-extension input").get(0));
|
||||
$("#omni-extension input").focus();
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// Close the omni
|
||||
function closeOmni() {
|
||||
if (window.location.href == "browser-extension://mpanekjjajcabgnlbabmopeenljeoggm/newtab.html") {
|
||||
browser.runtime.sendMessage({request:"restore-new-tab"});
|
||||
} else {
|
||||
isOpen = false;
|
||||
$("#omni-extension").addClass("omni-closing");
|
||||
}
|
||||
}
|
||||
|
||||
// Hover over an action in the omni
|
||||
function hoverItem() {
|
||||
$(".omni-item-active").removeClass("omni-item-active");
|
||||
$(this).addClass("omni-item-active");
|
||||
}
|
||||
|
||||
// Show a toast when an action has been performed
|
||||
function showToast(action) {
|
||||
$("#omni-extension-toast span").html('"'+action.title+'" has been successfully performed');
|
||||
$("#omni-extension-toast").addClass("omni-show-toast");
|
||||
setTimeout(() => {
|
||||
$(".omni-show-toast").removeClass("omni-show-toast");
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
// Autocomplete commands. Since they all start with different letters, it can be the default behavior
|
||||
function checkShortHand(e, value) {
|
||||
var el = $(".omni-extension input");
|
||||
if (e.keyCode != 8) {
|
||||
if (value == "/t") {
|
||||
el.val("/tabs ")
|
||||
} else if (value == "/b") {
|
||||
el.val("/bookmarks ")
|
||||
} else if (value == "/h") {
|
||||
el.val("/history ");
|
||||
} else if (value == "/r") {
|
||||
el.val("/remove ");
|
||||
} else if (value == "/a") {
|
||||
el.val("/actions ");
|
||||
}
|
||||
} else {
|
||||
if (value == "/tabs" || value == "/bookmarks" || value == "/actions" || value == "/remove" || value == "/history") {
|
||||
el.val("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add protocol
|
||||
function addhttp(url) {
|
||||
if (!/^(?:f|ht)tps?\:\/\//.test(url)) {
|
||||
url = "http://" + url;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
// Check if valid url
|
||||
function validURL(str) {
|
||||
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
|
||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
|
||||
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
|
||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
|
||||
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
|
||||
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
|
||||
return !!pattern.test(str);
|
||||
}
|
||||
|
||||
// Search for an action in the omni
|
||||
function search(e) {
|
||||
if (e.keyCode == 37 || e.keyCode == 38 || e.keyCode == 39 || e.keyCode == 40 || e.keyCode == 13 || e.keyCode == 37) {
|
||||
return;
|
||||
}
|
||||
var value = $(this).val().toLowerCase();
|
||||
checkShortHand(e, value);
|
||||
value = $(this).val().toLowerCase();
|
||||
if (value.startsWith("/history")) {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").hide();
|
||||
var tempvalue = value.replace("/history ", "");
|
||||
var query = "";
|
||||
if (tempvalue != "/history") {
|
||||
query = value.replace("/history ", "");
|
||||
}
|
||||
browser.runtime.sendMessage({request:"search-history", query:query}, (response) => {
|
||||
populateOmniFilter(response.history);
|
||||
});
|
||||
} else if (value.startsWith("/bookmarks")) {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").hide();
|
||||
var tempvalue = value.replace("/bookmarks ", "");
|
||||
if (tempvalue != "/bookmarks" && tempvalue != "") {
|
||||
var query = value.replace("/bookmarks ", "");
|
||||
browser.runtime.sendMessage({request:"search-bookmarks", query:query}, (response) => {
|
||||
populateOmniFilter(response.bookmarks);
|
||||
});
|
||||
} else {
|
||||
populateOmniFilter(actions.filter(x => x.type == "bookmark"));
|
||||
}
|
||||
} else {
|
||||
if (isFiltered) {
|
||||
populateOmni();
|
||||
isFiltered = false;
|
||||
}
|
||||
$(".omni-extension #omni-list .omni-item").filter(function(){
|
||||
if (value.startsWith("/tabs")) {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").hide();
|
||||
var tempvalue = value.replace("/tabs ", "");
|
||||
if (tempvalue == "/tabs") {
|
||||
$(this).toggle($(this).attr("data-type") == "tab");
|
||||
} else {
|
||||
tempvalue = value.replace("/tabs ", "");
|
||||
$(this).toggle(($(this).find(".omni-item-name").text().toLowerCase().indexOf(tempvalue) > -1 || $(this).find(".omni-item-desc").text().toLowerCase().indexOf(tempvalue) > -1) && $(this).attr("data-type") == "tab");
|
||||
}
|
||||
} else if (value.startsWith("/remove")) {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").hide();
|
||||
var tempvalue = value.replace("/remove ", "")
|
||||
if (tempvalue == "/remove") {
|
||||
$(this).toggle($(this).attr("data-type") == "bookmark" || $(this).attr("data-type") == "tab");
|
||||
} else {
|
||||
tempvalue = value.replace("/remove ", "");
|
||||
$(this).toggle(($(this).find(".omni-item-name").text().toLowerCase().indexOf(tempvalue) > -1 || $(this).find(".omni-item-desc").text().toLowerCase().indexOf(tempvalue) > -1) && ($(this).attr("data-type") == "bookmark" || $(this).attr("data-type") == "tab"));
|
||||
}
|
||||
} else if (value.startsWith("/actions")) {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").hide();
|
||||
var tempvalue = value.replace("/actions ", "")
|
||||
if (tempvalue == "/actions") {
|
||||
$(this).toggle($(this).attr("data-type") == "action");
|
||||
} else {
|
||||
tempvalue = value.replace("/actions ", "");
|
||||
$(this).toggle(($(this).find(".omni-item-name").text().toLowerCase().indexOf(tempvalue) > -1 || $(this).find(".omni-item-desc").text().toLowerCase().indexOf(tempvalue) > -1) && $(this).attr("data-type") == "action");
|
||||
}
|
||||
} else {
|
||||
$(this).toggle($(this).find(".omni-item-name").text().toLowerCase().indexOf(value) > -1 || $(this).find(".omni-item-desc").text().toLowerCase().indexOf(value) > -1);
|
||||
if (value == "") {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").hide();
|
||||
} else if (!validURL(value)) {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").show();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"'] .omni-item-name").html('\"'+value+'\"');
|
||||
} else {
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "search")+"']").hide();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"']").show();
|
||||
$(".omni-item[data-index='"+actions.findIndex(x => x.action == "goto")+"'] .omni-item-name").html(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(".omni-extension #omni-results").html($("#omni-extension #omni-list .omni-item:visible").length+" results");
|
||||
$(".omni-item-active").removeClass("omni-item-active");
|
||||
$(".omni-extension #omni-list .omni-item:visible").first().addClass("omni-item-active");
|
||||
}
|
||||
|
||||
// Handle actions from the omni
|
||||
function handleAction(e) {
|
||||
var action = actions[$(".omni-item-active").attr("data-index")];
|
||||
closeOmni();
|
||||
if ($(".omni-extension input").val().toLowerCase().startsWith("/remove")) {
|
||||
browser.runtime.sendMessage({request:"remove", type:action.type, action:action});
|
||||
} else if ($(".omni-extension input").val().toLowerCase().startsWith("/history")) {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
window.open($(".omni-item-active").attr("data-url"));
|
||||
} else {
|
||||
window.open($(".omni-item-active").attr("data-url"), "_self");
|
||||
}
|
||||
} else if ($(".omni-extension input").val().toLowerCase().startsWith("/bookmarks")) {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
window.open($(".omni-item-active").attr("data-url"));
|
||||
} else {
|
||||
window.open($(".omni-item-active").attr("data-url"), "_self");
|
||||
}
|
||||
} else {
|
||||
browser.runtime.sendMessage({request:action.action, tab:action, query:$(".omni-extension input").val()});
|
||||
switch (action.action) {
|
||||
case "bookmark":
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
window.open(action.url);
|
||||
} else {
|
||||
window.open(action.url, "_self");
|
||||
}
|
||||
break;
|
||||
case "scroll-bottom":
|
||||
window.scrollTo(0,document.body.scrollHeight);
|
||||
showToast(action);
|
||||
break;
|
||||
case "scroll-top":
|
||||
window.scrollTo(0,0);
|
||||
break;
|
||||
case "navigation":
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
window.open(action.url);
|
||||
} else {
|
||||
window.open(action.url, "_self");
|
||||
}
|
||||
break;
|
||||
case "fullscreen":
|
||||
var elem = document.documentElement;
|
||||
elem.requestFullscreen();
|
||||
break;
|
||||
case "new-tab":
|
||||
window.open("");
|
||||
break;
|
||||
case "email":
|
||||
window.open("mailto:");
|
||||
break;
|
||||
case "url":
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
window.open(action.url);
|
||||
} else {
|
||||
window.open(action.url, "_self");
|
||||
}
|
||||
break;
|
||||
case "goto":
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
window.open(addhttp($(".omni-extension input").val()));
|
||||
} else {
|
||||
window.open(addhttp($(".omni-extension input").val()), "_self");
|
||||
}
|
||||
break;
|
||||
case "print":
|
||||
window.print();
|
||||
break;
|
||||
case "remove-all":
|
||||
case "remove-history":
|
||||
case "remove-cookies":
|
||||
case "remove-cache":
|
||||
case "remove-local-storage":
|
||||
case "remove-passwords":
|
||||
showToast(action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch actions again
|
||||
browser.runtime.sendMessage({request:"get-actions"}, (response) => {
|
||||
actions = response.actions;
|
||||
populateOmni();
|
||||
});
|
||||
}
|
||||
|
||||
// Customize the shortcut to open the Omni box
|
||||
function openShortcuts() {
|
||||
browser.runtime.sendMessage({request:"extensions/shortcuts"});
|
||||
}
|
||||
|
||||
|
||||
// Check which keys are down
|
||||
var down = [];
|
||||
|
||||
$(document).keydown((e) => {
|
||||
down[e.keyCode] = true;
|
||||
if (down[38]) {
|
||||
// Up key
|
||||
if ($(".omni-item-active").prevAll("div").not(":hidden").first().length) {
|
||||
var previous = $(".omni-item-active").prevAll("div").not(":hidden").first();
|
||||
$(".omni-item-active").removeClass("omni-item-active");
|
||||
previous.addClass("omni-item-active");
|
||||
previous[0].scrollIntoView({block:"nearest", inline:"nearest"});
|
||||
}
|
||||
} else if (down[40]) {
|
||||
// Down key
|
||||
if ($(".omni-item-active").nextAll("div").not(":hidden").first().length) {
|
||||
var next = $(".omni-item-active").nextAll("div").not(":hidden").first();
|
||||
$(".omni-item-active").removeClass("omni-item-active");
|
||||
next.addClass("omni-item-active");
|
||||
next[0].scrollIntoView({block:"nearest", inline:"nearest"});
|
||||
}
|
||||
} else if (down[27] && isOpen) {
|
||||
// Esc key
|
||||
closeOmni();
|
||||
} else if (down[13] && isOpen) {
|
||||
// Enter key
|
||||
handleAction(e);
|
||||
}
|
||||
}).keyup((e) => {
|
||||
if (down[18] && down[16] && down[80]) {
|
||||
if (actions.find(x => x.action == "pin") != undefined) {
|
||||
browser.runtime.sendMessage({request:"pin-tab"});
|
||||
} else {
|
||||
browser.runtime.sendMessage({request:"unpin-tab"});
|
||||
}
|
||||
browser.runtime.sendMessage({request:"get-actions"}, (response) => {
|
||||
actions = response.actions;
|
||||
populateOmni();
|
||||
});
|
||||
} else if (down[18] && down[16] && down[77]) {
|
||||
if (actions.find(x => x.action == "mute") != undefined) {
|
||||
browser.runtime.sendMessage({request:"mute-tab"});
|
||||
} else {
|
||||
browser.runtime.sendMessage({request:"unmute-tab"});
|
||||
}
|
||||
browser.runtime.sendMessage({request:"get-actions"}, (response) => {
|
||||
actions = response.actions;
|
||||
populateOmni();
|
||||
});
|
||||
} else if (down[18] && down[16] && down[67]) {
|
||||
window.open("mailto:");
|
||||
}
|
||||
|
||||
down = [];
|
||||
});
|
||||
|
||||
// Recieve messages from background
|
||||
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
if (message.request == "open-omni") {
|
||||
if (isOpen) {
|
||||
closeOmni();
|
||||
} else {
|
||||
openOmni();
|
||||
}
|
||||
} else if (message.request == "close-omni") {
|
||||
closeOmni();
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("click", "#open-page-omni-extension-thing", openShortcuts);
|
||||
$(document).on("mouseover", ".omni-extension .omni-item:not(.omni-item-active)", hoverItem);
|
||||
$(document).on("keyup", ".omni-extension input", search);
|
||||
$(document).on("click", ".omni-item-active", handleAction);
|
||||
$(document).on("click", ".omni-extension #omni-overlay", closeOmni);
|
||||
});
|
||||
476
firefox/focus.js
Normal file
|
|
@ -0,0 +1,476 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global = global || self, global.focusLock = factory());
|
||||
}(this, function () { 'use strict';
|
||||
|
||||
var toArray = function toArray(a) {
|
||||
var ret = Array(a.length);
|
||||
for (var i = 0; i < a.length; ++i) {
|
||||
ret[i] = a[i];
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
var arrayFind = function arrayFind(array, search) {
|
||||
return array.filter(function (a) {
|
||||
return a === search;
|
||||
})[0];
|
||||
};
|
||||
|
||||
var asArray = function asArray(a) {
|
||||
return Array.isArray(a) ? a : [a];
|
||||
};
|
||||
|
||||
var tabSort = function tabSort(a, b) {
|
||||
var tabDiff = a.tabIndex - b.tabIndex;
|
||||
var indexDiff = a.index - b.index;
|
||||
|
||||
if (tabDiff) {
|
||||
if (!a.tabIndex) return 1;
|
||||
if (!b.tabIndex) return -1;
|
||||
}
|
||||
|
||||
return tabDiff || indexDiff;
|
||||
};
|
||||
|
||||
var orderByTabIndex = function orderByTabIndex(nodes, filterNegative, keepGuards) {
|
||||
return toArray(nodes).map(function (node, index) {
|
||||
return {
|
||||
node: node,
|
||||
index: index,
|
||||
tabIndex: keepGuards && node.tabIndex === -1 ? (node.dataset || {}).focusGuard ? 0 : -1 : node.tabIndex
|
||||
};
|
||||
}).filter(function (data) {
|
||||
return !filterNegative || data.tabIndex >= 0;
|
||||
}).sort(tabSort);
|
||||
};
|
||||
|
||||
var tabbables = ['button:enabled:not([readonly])', 'select:enabled:not([readonly])', 'textarea:enabled:not([readonly])', 'input:enabled:not([readonly])', 'a[href]', 'area[href]', 'iframe', 'object', 'embed', '[tabindex]', '[contenteditable]', '[autofocus]'];
|
||||
|
||||
var FOCUS_GROUP = 'data-focus-lock';
|
||||
var FOCUS_DISABLED = 'data-focus-lock-disabled';
|
||||
var FOCUS_ALLOW = 'data-no-focus-lock';
|
||||
var FOCUS_AUTO = 'data-autofocus-inside';
|
||||
|
||||
var queryTabbables = tabbables.join(',');
|
||||
var queryGuardTabbables = queryTabbables + ', [data-focus-guard]';
|
||||
|
||||
var getFocusables = function getFocusables(parents, withGuards) {
|
||||
return parents.reduce(function (acc, parent) {
|
||||
return acc.concat(
|
||||
// add all tabbables inside
|
||||
toArray(parent.querySelectorAll(withGuards ? queryGuardTabbables : queryTabbables)),
|
||||
// add if node is tabble itself
|
||||
parent.parentNode ? toArray(parent.parentNode.querySelectorAll(tabbables.join(','))).filter(function (node) {
|
||||
return node === parent;
|
||||
}) : []);
|
||||
}, []);
|
||||
};
|
||||
|
||||
var getParentAutofocusables = function getParentAutofocusables(parent) {
|
||||
var parentFocus = parent.querySelectorAll('[' + FOCUS_AUTO + ']');
|
||||
return toArray(parentFocus).map(function (node) {
|
||||
return getFocusables([node]);
|
||||
}).reduce(function (acc, nodes) {
|
||||
return acc.concat(nodes);
|
||||
}, []);
|
||||
};
|
||||
|
||||
var isElementHidden = function isElementHidden(computedStyle) {
|
||||
if (!computedStyle || !computedStyle.getPropertyValue) {
|
||||
return false;
|
||||
}
|
||||
return computedStyle.getPropertyValue('display') === 'none' || computedStyle.getPropertyValue('visibility') === 'hidden';
|
||||
};
|
||||
|
||||
var isVisible = function isVisible(node) {
|
||||
return !node || node === document || !isElementHidden(window.getComputedStyle(node, null)) && isVisible(node.parentNode);
|
||||
};
|
||||
|
||||
var notHiddenInput = function notHiddenInput(node) {
|
||||
return !((node.tagName === 'INPUT' || node.tagName === 'BUTTON') && (node.type === 'hidden' || node.disabled));
|
||||
};
|
||||
|
||||
var getParents = function getParents(node) {
|
||||
var parents = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
||||
|
||||
parents.push(node);
|
||||
if (node.parentNode) {
|
||||
getParents(node.parentNode, parents);
|
||||
}
|
||||
return parents;
|
||||
};
|
||||
|
||||
var getCommonParent = function getCommonParent(nodea, nodeb) {
|
||||
var parentsA = getParents(nodea);
|
||||
var parentsB = getParents(nodeb);
|
||||
|
||||
for (var i = 0; i < parentsA.length; i += 1) {
|
||||
var currentParent = parentsA[i];
|
||||
if (parentsB.indexOf(currentParent) >= 0) {
|
||||
return currentParent;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var filterFocusable = function filterFocusable(nodes) {
|
||||
return toArray(nodes).filter(function (node) {
|
||||
return isVisible(node);
|
||||
}).filter(function (node) {
|
||||
return notHiddenInput(node);
|
||||
});
|
||||
};
|
||||
|
||||
var getTabbableNodes = function getTabbableNodes(topNodes, withGuards) {
|
||||
return orderByTabIndex(filterFocusable(getFocusables(topNodes, withGuards)), true, withGuards);
|
||||
};
|
||||
|
||||
var getAllTabbableNodes = function getAllTabbableNodes(topNodes) {
|
||||
return orderByTabIndex(filterFocusable(getFocusables(topNodes)), false);
|
||||
};
|
||||
|
||||
var parentAutofocusables = function parentAutofocusables(topNode) {
|
||||
return filterFocusable(getParentAutofocusables(topNode));
|
||||
};
|
||||
|
||||
var isRadio = function isRadio(node) {
|
||||
return node.tagName === 'INPUT' && node.type === 'radio';
|
||||
};
|
||||
|
||||
var findSelectedRadio = function findSelectedRadio(node, nodes) {
|
||||
return nodes.filter(isRadio).filter(function (el) {
|
||||
return el.name === node.name;
|
||||
}).filter(function (el) {
|
||||
return el.checked;
|
||||
})[0] || node;
|
||||
};
|
||||
|
||||
var pickFirstFocus = function pickFirstFocus(nodes) {
|
||||
if (nodes[0] && nodes.length > 1) {
|
||||
if (isRadio(nodes[0]) && nodes[0].name) {
|
||||
return findSelectedRadio(nodes[0], nodes);
|
||||
}
|
||||
}
|
||||
return nodes[0];
|
||||
};
|
||||
|
||||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||||
|
||||
var filterNested = function filterNested(nodes) {
|
||||
var l = nodes.length;
|
||||
for (var i = 0; i < l; i += 1) {
|
||||
var _loop = function _loop(j) {
|
||||
if (i !== j) {
|
||||
if (nodes[i].contains(nodes[j])) {
|
||||
return {
|
||||
v: filterNested(nodes.filter(function (x) {
|
||||
return x !== nodes[j];
|
||||
}))
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (var j = 0; j < l; j += 1) {
|
||||
var _ret = _loop(j);
|
||||
|
||||
if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
|
||||
}
|
||||
}
|
||||
return nodes;
|
||||
};
|
||||
|
||||
var getTopParent = function getTopParent(node) {
|
||||
return node.parentNode ? getTopParent(node.parentNode) : node;
|
||||
};
|
||||
|
||||
var getAllAffectedNodes = function getAllAffectedNodes(node) {
|
||||
var nodes = asArray(node);
|
||||
return nodes.filter(Boolean).reduce(function (acc, currentNode) {
|
||||
var group = currentNode.getAttribute(FOCUS_GROUP);
|
||||
acc.push.apply(acc, group ? filterNested(toArray(getTopParent(currentNode).querySelectorAll('[' + FOCUS_GROUP + '="' + group + '"]:not([' + FOCUS_DISABLED + '="disabled"])'))) : [currentNode]);
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
var findAutoFocused = function findAutoFocused(autoFocusables) {
|
||||
return function (node) {
|
||||
return !!node.autofocus || node.dataset && !!node.dataset.autofocus || autoFocusables.indexOf(node) >= 0;
|
||||
};
|
||||
};
|
||||
|
||||
var newFocus = function newFocus(innerNodes, outerNodes, activeElement, lastNode, autoFocused) {
|
||||
var cnt = innerNodes.length;
|
||||
var firstFocus = innerNodes[0];
|
||||
var lastFocus = innerNodes[cnt - 1];
|
||||
|
||||
// focus is inside
|
||||
if (innerNodes.indexOf(activeElement) >= 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var activeIndex = outerNodes.indexOf(activeElement);
|
||||
var lastIndex = outerNodes.indexOf(lastNode || activeIndex);
|
||||
var lastNodeInside = innerNodes.indexOf(lastNode);
|
||||
var indexDiff = activeIndex - lastIndex;
|
||||
var firstNodeIndex = outerNodes.indexOf(firstFocus);
|
||||
var lastNodeIndex = outerNodes.indexOf(lastFocus);
|
||||
|
||||
// new focus
|
||||
if (activeIndex === -1 || lastNodeInside === -1) {
|
||||
return innerNodes.indexOf(autoFocused.length ? pickFirstFocus(autoFocused) : pickFirstFocus(innerNodes));
|
||||
}
|
||||
// old focus
|
||||
if (!indexDiff && lastNodeInside >= 0) {
|
||||
return lastNodeInside;
|
||||
}
|
||||
// jump out
|
||||
if (indexDiff && Math.abs(indexDiff) > 1) {
|
||||
return lastNodeInside;
|
||||
}
|
||||
// focus above lock
|
||||
if (activeIndex <= firstNodeIndex) {
|
||||
return cnt - 1;
|
||||
}
|
||||
// focus below lock
|
||||
if (activeIndex > lastNodeIndex) {
|
||||
return 0;
|
||||
}
|
||||
// index is inside tab order, but outside Lock
|
||||
if (indexDiff) {
|
||||
if (Math.abs(indexDiff) > 1) {
|
||||
return lastNodeInside;
|
||||
}
|
||||
return (cnt + lastNodeInside + indexDiff) % cnt;
|
||||
}
|
||||
// do nothing
|
||||
return undefined;
|
||||
};
|
||||
|
||||
var getTopCommonParent = function getTopCommonParent(baseActiveElement, leftEntry, rightEntries) {
|
||||
var activeElements = asArray(baseActiveElement);
|
||||
var leftEntries = asArray(leftEntry);
|
||||
var activeElement = activeElements[0];
|
||||
var topCommon = null;
|
||||
leftEntries.filter(Boolean).forEach(function (entry) {
|
||||
topCommon = getCommonParent(topCommon || entry, entry) || topCommon;
|
||||
rightEntries.filter(Boolean).forEach(function (subEntry) {
|
||||
var common = getCommonParent(activeElement, subEntry);
|
||||
if (common) {
|
||||
if (!topCommon || common.contains(topCommon)) {
|
||||
topCommon = common;
|
||||
} else {
|
||||
topCommon = getCommonParent(common, topCommon);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return topCommon;
|
||||
};
|
||||
|
||||
var allParentAutofocusables = function allParentAutofocusables(entries) {
|
||||
return entries.reduce(function (acc, node) {
|
||||
return acc.concat(parentAutofocusables(node));
|
||||
}, []);
|
||||
};
|
||||
|
||||
var notAGuard = function notAGuard(node) {
|
||||
return !(node.dataset && node.dataset.focusGuard);
|
||||
};
|
||||
|
||||
var reorderNodes = function reorderNodes(srcNodes, dstNodes) {
|
||||
return srcNodes.map(function (dnode) {
|
||||
return dstNodes.find(function (_ref) {
|
||||
var node = _ref.node;
|
||||
return dnode === node;
|
||||
});
|
||||
}).filter(Boolean);
|
||||
};
|
||||
|
||||
var getFocusMerge = function getFocusMerge(topNode, lastNode) {
|
||||
var activeElement = document && document.activeElement;
|
||||
var entries = getAllAffectedNodes(topNode).filter(notAGuard);
|
||||
|
||||
var commonParent = getTopCommonParent(activeElement || topNode, topNode, entries);
|
||||
|
||||
var innerElements = getTabbableNodes(entries).filter(function (_ref5) {
|
||||
var node = _ref5.node;
|
||||
return notAGuard(node);
|
||||
});
|
||||
|
||||
if (!innerElements[0]) {
|
||||
innerElements = getAllTabbableNodes(entries).filter(function (_ref6) {
|
||||
var node = _ref6.node;
|
||||
return notAGuard(node);
|
||||
});
|
||||
if (!innerElements[0]) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
var outerNodes = getTabbableNodes([commonParent]).map(function (_ref7) {
|
||||
var node = _ref7.node;
|
||||
return node;
|
||||
});
|
||||
var orderedInnerElements = reorderNodes(outerNodes, innerElements);
|
||||
var innerNodes = orderedInnerElements.map(function (_ref8) {
|
||||
var node = _ref8.node;
|
||||
return node;
|
||||
});
|
||||
|
||||
var newId = newFocus(innerNodes, outerNodes, activeElement, lastNode, innerNodes.filter(findAutoFocused(allParentAutofocusables(entries))));
|
||||
|
||||
if (newId === undefined) {
|
||||
return newId;
|
||||
}
|
||||
return orderedInnerElements[newId];
|
||||
};
|
||||
|
||||
var focusInFrame = function focusInFrame(frame) {
|
||||
return frame === document.activeElement;
|
||||
};
|
||||
|
||||
var focusInsideIframe = function focusInsideIframe(topNode) {
|
||||
return !!arrayFind(toArray(topNode.querySelectorAll('iframe')), focusInFrame);
|
||||
};
|
||||
|
||||
var focusInside = function focusInside(topNode) {
|
||||
var activeElement = document && document.activeElement;
|
||||
|
||||
if (!activeElement || activeElement.dataset && activeElement.dataset.focusGuard) {
|
||||
return false;
|
||||
}
|
||||
return getAllAffectedNodes(topNode).reduce(function (result, node) {
|
||||
return result || node.contains(activeElement) || focusInsideIframe(node);
|
||||
}, false);
|
||||
};
|
||||
|
||||
var focusIsHidden = function focusIsHidden() {
|
||||
return document && toArray(document.querySelectorAll('[' + FOCUS_ALLOW + ']')).some(function (node) {
|
||||
return node.contains(document.activeElement);
|
||||
});
|
||||
};
|
||||
|
||||
var focusOn = function focusOn(target) {
|
||||
target.focus();
|
||||
if (target.contentWindow) {
|
||||
target.contentWindow.focus();
|
||||
}
|
||||
};
|
||||
|
||||
var guardCount = 0;
|
||||
var lockDisabled = false;
|
||||
|
||||
var setFocus = (function (topNode, lastNode) {
|
||||
var focusable = getFocusMerge(topNode, lastNode);
|
||||
|
||||
if (lockDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (focusable) {
|
||||
if (guardCount > 2) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('FocusLock: focus-fighting detected. Only one focus management system could be active. ' + 'See https://github.com/theKashey/focus-lock/#focus-fighting');
|
||||
lockDisabled = true;
|
||||
setTimeout(function () {
|
||||
lockDisabled = false;
|
||||
}, 1);
|
||||
return;
|
||||
}
|
||||
guardCount++;
|
||||
focusOn(focusable.node);
|
||||
guardCount--;
|
||||
}
|
||||
});
|
||||
|
||||
var lastActiveTrap = 0;
|
||||
var lastActiveFocus = null;
|
||||
|
||||
var focusOnBody = function focusOnBody() {
|
||||
return document && document.activeElement === document.body;
|
||||
};
|
||||
|
||||
var isFreeFocus = function isFreeFocus() {
|
||||
return focusOnBody() || focusIsHidden();
|
||||
};
|
||||
|
||||
var activateTrap = function activateTrap() {
|
||||
var result = false;
|
||||
|
||||
if (lastActiveTrap) {
|
||||
var observed = lastActiveTrap;
|
||||
|
||||
if (!isFreeFocus()) {
|
||||
if (observed && !focusInside(observed)) {
|
||||
result = setFocus(observed, lastActiveFocus);
|
||||
}
|
||||
|
||||
lastActiveFocus = document.activeElement;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var reducePropsToState = function reducePropsToState(propsList) {
|
||||
return propsList.filter(function (node) {
|
||||
return node;
|
||||
}).slice(-1)[0];
|
||||
};
|
||||
|
||||
var handleStateChangeOnClient = function handleStateChangeOnClient(trap) {
|
||||
lastActiveTrap = trap;
|
||||
|
||||
if (trap) {
|
||||
activateTrap();
|
||||
}
|
||||
};
|
||||
|
||||
var instances = [];
|
||||
|
||||
var emitChange = function emitChange(event) {
|
||||
if (handleStateChangeOnClient(reducePropsToState(instances))) {
|
||||
event && event.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var attachHandler = function attachHandler() {
|
||||
document.addEventListener('focusin', emitChange);
|
||||
};
|
||||
|
||||
var detachHandler = function detachHandler() {
|
||||
document.removeEventListener('focusin', emitChange);
|
||||
};
|
||||
|
||||
var focusLock = {
|
||||
on: function on(domNode) {
|
||||
if (instances.length === 0) {
|
||||
attachHandler();
|
||||
}
|
||||
|
||||
if (instances.indexOf(domNode) < 0) {
|
||||
instances.push(domNode);
|
||||
emitChange();
|
||||
}
|
||||
},
|
||||
off: function off(domNode) {
|
||||
instances = instances.filter(function (node) {
|
||||
return node !== domNode;
|
||||
});
|
||||
emitChange();
|
||||
|
||||
if (instances.length === 0) {
|
||||
detachHandler();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return focusLock;
|
||||
|
||||
}));
|
||||
2
firefox/jquery.js
vendored
Normal file
45
firefox/manifest.json
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"name": "Omni",
|
||||
"description": "Supercharge Chrome with commands, shortcuts, and more",
|
||||
"offline_enabled": true,
|
||||
"version": "1.4.2",
|
||||
"manifest_version": 2,
|
||||
"browser_action": {
|
||||
"default_icon": {
|
||||
"16": "assets/logo-16.png",
|
||||
"48": "assets/logo-48.png",
|
||||
"128": "assets/logo-128.png"
|
||||
}
|
||||
},
|
||||
"icons": {
|
||||
"16": "assets/logo-16.png",
|
||||
"48": "assets/logo-48.png",
|
||||
"128": "assets/logo-128.png"
|
||||
},
|
||||
"commands": {
|
||||
"open-omni": {
|
||||
"suggested_key": {
|
||||
"default": "Ctrl+Shift+K",
|
||||
"mac": "Command+Shift+K"
|
||||
},
|
||||
"description": "Open command menu"
|
||||
}
|
||||
},
|
||||
"background": {
|
||||
"scripts": ["background.js"]
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"<all_urls>"
|
||||
],
|
||||
"run_at": "document_end",
|
||||
"js": ["focus.js", "jquery.js", "content.js"],
|
||||
"css": ["content.css"]
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": ["content.html", "newtab.html", "assets/*", "popup.css", "popup.js"],
|
||||
"permissions": [
|
||||
"tabs", "activeTab", "bookmarks", "browsingData", "history", "scripting", "search"
|
||||
]
|
||||
}
|
||||
18
firefox/newtab.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Omni</title>
|
||||
<link rel="stylesheet" href="content.css">
|
||||
<style>
|
||||
body {
|
||||
background: var(--background);
|
||||
margin: 0px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script src="jquery.js"></script>
|
||||
<script src="content.js"></script>
|
||||
</body>
|
||||
</html>
|
||||