diff --git a/.eslintrc.js b/.eslintrc.js index 467a3a6..eab0580 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,7 +19,9 @@ module.exports = { "OS": true, "ADDON_UNINSTALL": true, "ADDON_DISABLE": true, - "proxifiedContainers": true + "proxifiedContainers": true, + "MozillaVPN": true, + "MozillaVPN_Background": true }, "plugins": [ "promise", diff --git a/.stylelintrc b/.stylelintrc index 5debd45..afed108 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -14,7 +14,7 @@ ignoreProperties: ["inset-block-end", "inset-block-start"] }], - "property-blacklist": [ + "property-disallowed-list": [ "/(min[-]|max[-])height/", "/width/", "/top/", diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 80ea76e..c416bbe 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -42,64 +42,52 @@ "message": "A better way to manage all the things you do online" }, "onboarding-1-description": { - "message": "Use containers to organize tasks, manage accounts, and keep your focus where you want it." - }, - "onboarding-1-sec-header": { - "message": "A simple and secure way to manage your online life" - }, - "onboarding-1-sec-description": { - "message" : "Use containers to organize tasks, manage accounts, and store sensitive data." + "message": "Use Containers to organize tasks, manage accounts, and keep your focus where you want it." }, "onboarding-2-header": { - "message": "Put containers to work for you." + "message": "Put Containers to work for you." }, "onboarding-2-description": { - "message": "Features like color-coding and separate container tabs help you find things easily, focus your attention, and minimize distractions." - }, - "onboarding-2-sec-description": { - "message": "Color-coding helps you categorize your online life, find things easily, and minimize distractions." + "message": "Features like color-coding and separate Container tabs help you find things easily, focus your attention, and minimize distractions." }, "onboarding-3-header": { "message": "A place for everything, and everything in its place." }, "onboarding-3-description": { - "message": "Start with the containers we've created, or create your own." - }, - "onboarding-3-sec-header": { - "message": "Set boundaries for your browsing." - }, - "onboarding-3-sec-description": { - "message": "Cookies are stored within a container, so you can segment sensitive data and browsing history to stay organized and to limit the impact of online trackers." + "message": "Start with the Containers we’ve created, or create your own." }, "onboarding-4-header": { - "message": "Always open sites in the containers you want." + "message": "Always open sites in the Containers you want." }, "onboarding-4-description": { - "message": "Right-click inside a container tab to assign the site to always open in the container." + "message": "Right-click inside a Container tab to assign the site to always open in the Container." }, "onboarding-5-header": { "message": "Container tabs when you need them." }, "onboarding-5-description": { - "message": "Long-press the New Tab button to create a new container tab." + "message": "Long-press the New Tab button to create a new Container tab." }, "onboarding-6-header": { "message": "Syncing Containers is now Available!" }, "onboarding-6-description": { - "message": "Turn on Sync to share container and site assignments with any computer connected to your Firefox Account." + "message": "Turn on Sync to share Container and site assignments with any computer connected to your Firefox account." }, "onboarding-7-header": { - "message": "Firefox Account is required to sync." + "message": "Firefox account is required to sync." }, "onboarding-7-description": { - "message": "Click Sign In to confirm that your Firefox Account is active." + "message": "Click Sign In to confirm that your Firefox account is active." + }, + "onboarding-8-description": { + "message": "This is a really exciting message about how Container proxies are now supported and about how it’s now really easy to do with Mozilla VPN..." }, "oneHundredTabsHeader": { "message": "100 tabs!" }, "youHaveOpened": { - "message": "You've opened 100 Container tabs." + "message": "You’ve opened 100 Container tabs." }, "spreadTheWord": { "message": "If you enjoy Containers, help us spread the word!" @@ -138,7 +126,7 @@ "message": "OK" }, "sitesAssignedToThisContainer": { - "message": "Sites assigned to this container" + "message": "Sites assigned to this Container" }, "options": { "message": "Options" @@ -189,10 +177,10 @@ "message": "Next" }, "openThisSiteConfirmation": { - "message": "Open this site in your assigned container?" + "message": "Open this site in your assigned Container?" }, "wouldYouStillLikeToOpenConfirmation": { - "message": "Would you still like to open in this current container?" + "message": "Would you still like to open in this current Container?" }, "rememberMyDecision": { "message": "Remember my decision for this site" @@ -215,29 +203,29 @@ "tabBehavior": { "message": "Tab behavior:" }, - "firefoxAccountsSync": { - "message": "Firefox Accounts Sync:" - }, "enableBookMarkMenus": { "message": "Enable Bookmark Menus" }, + "firefoxAccountsSync": { + "message": "Firefox accounts sync:" + }, "enableSync": { - "message": "Enable Sync" + "message": "Enable sync" }, "enableBookMarkMenusDescription": { - "message": "This setting allows you to open a bookmark or folder of bookmarks in a container." + "message": "This setting allows you to open a bookmark or folder of bookmarks in a Container." }, "enableSyncDescription": { - "message": "This setting allows you to sync your containers and site assignments across devices." + "message": "This setting allows you to sync your Containers and site assignments across devices." }, "replaceTab": { - "message": "This setting allows you to sync your containers and site assignments across devices." + "message": "This setting allows you to sync your Containers and site assignments across devices." }, "replaceTabDescription": { - "message": "Replace the current tab if a page which is assigned to another container is opened (instead of keeping the current tab open). Opening tabs with middle mouse button is not affected." + "message": "Replace the current tab if a page which is assigned to another Container is opened (instead of keeping the current tab open). Opening tabs with middle mouse button is not affected." }, "editWhichContainer": { - "message": "Edit which container is opened when using the numbered shortcuts." + "message": "Edit which Container is opened when using the numbered shortcuts." }, "keyboardShortCut": { "message": "Container to open with Keyboard Shortcut $keyId$", @@ -266,5 +254,59 @@ "content": "$1" } } + }, + "chooseLocation": { + "message": "Choose location" + }, + "hide": { + "message": "Hide" + }, + "show": { + "message": "Show" + }, + "protectEachContainer": { + "message": "Protect each Container with Mozilla VPN" + }, + "protectThisContainer": { + "message": "Protect this Container with Mozilla VPN" + }, + "advancedProxySettings": { + "message": "Advanced proxy settings" + }, + "proxyInputLabel": { + "message": "Enter custom proxy" + }, + "useCustomLocation": { + "message": "Use custom location for this Container" + }, + "clearproxylabel": { + "message": "Clear proxy" + }, + "moz-vpn-connected": { + "message": "Mozilla VPN is on" + }, + "moz-vpn-disconnected": { + "message": "Mozilla VPN is off" + }, + "invalidProxyAlert": { + "message": "Please enter a valid proxy URL" + }, + "mozillaVpnMustBeOn": { + "message": "Mozilla VPN app must be on to use this feature." + }, + "learnMore": { + "message": "Learn more" + }, + "proxyNowAvailable": { + "message": "Mozilla VPN and proxy integration is now available!" + }, + "getMozillaVpn": { + "message": "Get Mozilla VPN" + }, + "integratewithmozillavpn": { + "message": "Integrate your Containers with Mozilla VPN" + }, + "applyToThisContainer": { + "message": "Apply to this Container" } } diff --git a/src/css/confirm-page.css b/src/css/confirm-page.css index 49990f3..3ff1e14 100644 --- a/src/css/confirm-page.css +++ b/src/css/confirm-page.css @@ -5,8 +5,8 @@ main { background: url(/img/onboarding-4.png) no-repeat; - background-position: -10px -15px; - background-size: 300px; + background-position: 200px 0; + background-size: 120px; margin-inline-start: -350px; padding-inline-start: 350px; } @@ -20,7 +20,7 @@ button .container-name, font-weight: bold; } -@media only screen and (max-width: 1300px) { +@media only screen and (max-width: 900px) { main { background: none; } diff --git a/src/css/popup.css b/src/css/popup.css index a69774c..7c75e33 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -1,4 +1,33 @@ +@font-face { + font-family: "Metropolis"; + font-style: normal; + font-weight: 800; + src: url("/fonts/Metropolis-Medium.woff2") format("woff2"); +} + +@font-face { + font-family: "Metropolis-Light"; + font-style: normal; + font-weight: 300; + src: url("/fonts/Metropolis-Light.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter"; + font-style: normal; + font-weight: 400; + src: url("/fonts/Inter-Regular.woff2") format("woff2"); +} + +@font-face { + font-family: "Inter-Medium"; + font-style: normal; + font-weight: 500; + src: url("/fonts/Inter-Medium.woff2") format("woff2"); +} + /* General Rules and Resets */ + * { font-size: inherit; margin-block-end: 0; @@ -15,33 +44,85 @@ html { background-color: #fefefe; box-sizing: border-box; font-size: 12px; + overscroll-behavior: none; } body { - color: #000; - font-family: Roboto, Noto, "San Francisco", Ubuntu, "Segoe UI", "Fira Sans", message-box, Arial, sans-serif; + font-family: var(--fontInter); font-size: 13px; - inline-size: calc(var(--overflow-size) + 299px); - - /* inline-size: 320px; */ - letter-spacing: -0.1px; - max-inline-size: calc(var(--overflow-size) + 299px); + inline-size: 352px; + letter-spacing: -0.125px; + min-inline-size: 352px; + background-color: var(--bgColor); --highlight-blue: #1296f8; - --hr-grey: #e3e3e3; - --text-grey: #737373; + --hr-grey: #cececf91; + --text-grey: #262726eb; + + color: var(--text-grey); } html, body { block-size: 100%; /* Bugfix: issue 948 */ + max-block-size: 650px; + min-block-size: 300px; + + /* stylelint-disable */ + scrollbar-width: none; + /* stylelint-enable */ + transition: height 0.1s ease-in-out; } :root { + --fontInter: "Inter", sans-serif; + --fontInterMedium: "Inter-Medium", sans-serif; + --fontMetropolis: "Metropolis", sans-serif; + --fontMetropolisLight: "Metropolis-Light", sans-serif; --primary-action-color: #248aeb; --title-text-color: #000; - --text-normal-color: #4a4a4a; - --text-heading-color: #000; + --text-normal-color: #262726; + --text-heading-color: #3d3d3d; + --iconArrowLeft: url("/img/arrow-icon-left.svg"); + --iconArrowRight: url("/img/arrow-icon-right.svg"); + --iconCloseX: url("/img/close.svg"); + --iconGear: url("/img/gear-icon.svg"); + --iconProxyWarning: url("/img/proxy-warning.svg"); + --logoMozillaVpn: url("/img/moz-vpn-logo.svg"); + --menuItemHeight: 28px; + --marginInline: 16px; + --footerHeight: 48px; + --bgColor: #fefffe; + --blue20: #0df; + --blue30: #00b3f4; + --blue40: #0090ed; + --blue50: #0060df; + --blue60: #0250bb; + --blue70: #054096; + --red30: #ff848b; + --red40: #ff6a75; + --red50: #ff4f5e; + --red60: #e22850; + --red70: #c50042; + --alertColor: var(--red50); + --primaryCtaDefault: var(--blue50); + --primaryCtaHover: var(--blue60); + --primaryCtaActive: var(--blue70); + --primaryCtafocus: rgba(0, 97, 223, 0.4); + --controllerDefault: var(--bgColor); + --controllerHover: var(--grey10); + --controllerActive: var(--grey20); + --green50: #3fe1b0; + --green60: #3ad4b3; + --green70: #1cc4a0; + --green80: #00a49a; + --grey10: #e7e7e7; + --grey20: #cececf; + --grey30: #9e9e9e; + --grey40: #6d6e6e; + --grey50: #3d3d3d; + --panelSize: 560px; + --rowHeight: 48px; /* calculated from 12px */ --font-size-heading: 1.33rem; /* 16px */ @@ -58,16 +139,13 @@ body { --small-text-size: 0.833rem; /* 10px */ --small-radius: 3px; --icon-button-size: calc(calc(var(--block-line-separation-size) * 2) + 1.66rem); /* 20px */ - --column-panel-inline-size: calc(var(--overflow-size) + 267px); --inactive-opacity: 0.3; --overflow-size: 1px; --icon-fit: 8; -} -@media (min-resolution: 1dppx) { - html { - font-size: 14px; - } + background: var(--bgColor); + margin-block: 0; + margin-inline: 0; } *, @@ -76,21 +154,10 @@ body { box-sizing: inherit; } -form { - margin-block-end: 0; - margin-block-start: 0; - margin-inline-end: 0; - margin-inline-start: 0; -} - table { border: 0; border-spacing: 0; inline-size: 100%; - margin-block-end: 0; - margin-block-start: 0; - margin-inline-end: 0; - margin-inline-start: 0; } /* Helper Classes */ @@ -101,9 +168,11 @@ table { .scrollable { flex: 1; inline-size: 100%; - max-block-size: 400px; - overflow-x: hidden; + block-size: 100%; + overscroll-behavior: none; overflow-y: auto; + overflow-x: hidden; + padding-block-end: 8px; } .offpage { @@ -114,27 +183,28 @@ table { display: none !important; } -/* Effect borrowed from tabs in Firefox, ensure that the element flexes to the full width */ +/* effect borrowed from tabs in firefox, ensure that the element flexes to the full width */ .truncate-text { - inline-size: 100%; + inline-size: calc(100vw - 80px); overflow: hidden; position: relative; white-space: nowrap; + text-overflow: ellipsis; } .truncate-text::after { - background: white; + background: var(--bgColor); content: " "; - height: 100%; - inline-size: 50px; + block-size: 100%; + inline-size: 100px; inset-inline-end: 0; - mask-image: linear-gradient(to right, transparent, white 70%); + mask-image: linear-gradient(to right, transparent, var(--bgColor) 70%); position: absolute; } .hover-highlight:hover .truncate-text::after, .hover-highlight:focus .truncate-text::after { - background: var(--highlight-blue); + background-color: var(--highlight-blue); mask-image: linear-gradient(to right, transparent, var(--highlight-blue) 50%); } @@ -242,8 +312,9 @@ table { } /* Buttons */ + .button { - color: black; + color: var(--text-heading-color); } .button.primary { @@ -261,22 +332,1007 @@ table { background-color: rgba(0, 0, 0, 0.05); } +/* Mozilla VPN status icon */ + +.moz-vpn-status-icon { + color: var(--text-heading-color); + background-size: 17px; + background-position: left center; + font-size: 13px; + padding-inline-start: 22px; + padding-inline-end: 32px; +} + +.moz-vpn-status-icon.connected { + background-image: url("/img/moz-vpn-status-icons/moz-vpn-connected.svg"); +} + +.moz-vpn-status-icon.disconnected { + background-image: url("/img/moz-vpn-status-icons/moz-vpn-disconnected.svg"); +} + +.moz-vpn-logotype.vpn-status-container-list { + color: var(--text-heading-color); + background-size: 16px; + background-position: left center; + font-size: 12px; + padding-inline-start: 19px; + padding-inline-end: 22px; + margin-inline-end: 20px; + align-items: center; +} + +.moz-vpn-connection-status-indicator.container-list-status-icon { + block-size: 16px; + inline-size: 16px; +} + +/* Toggle Switch */ + +.switch { + display: inline-block; + block-size: 24px; + position: relative; + inline-size: 45px; +} + +.switch .switch-input { + block-size: 0; + opacity: 0; + inline-size: 0; +} + +.slider { + background-color: var(--grey20); + border-radius: 24px; + inset-block-end: 0; + box-shadow: 0 0 0 2px var(--bgColor), 0 0 0 4px var(--bgColor); + inset-inline-start: 0; + position: absolute; + inset-inline-end: 0; + inset-block-start: 0; + transition: 0.1s ease-in-out; +} + +.slider::before { + background-color: #fff; + border-radius: 50%; + inset-block-end: 3px; + content: ""; + block-size: 18px; + inset-inline-start: 3px; + position: absolute; + transition: 0.1s ease-in-out; + inline-size: 18px; +} + +input:hover + .slider { + background-color: var(--grey30); +} + +input:focus + .slider { + box-shadow: 0 0 0 2px var(--bgColor), 0 0 0 4px var(--grey30); +} + +input:active + .slider { + background-color: var(--grey40); +} + +input:checked + .slider { + background-color: var(--green50); +} + +input:checked:hover + .slider { + background-color: var(--green60); +} + +input:checked:focus + .slider { + box-shadow: 0 0 0 2px var(--bgColor), 0 0 0 4px var(--green70); +} + +input:checked:active + .slider { + background-color: var(--green70); +} + +input:checked + .slider::before { + transform: translateX(21px); +} + +.hidden { + visibility: hidden; +} + +/* Primary CTA Buttons */ + +.primary-cta { + background-color: var(--primaryCtaDefault); + border: transparent; + border-radius: 4px; + color: #fff; + transition: background-color 0.2s ease-in-out; +} + +.primary-cta:hover { + background-color: var(--primaryCtaHover); +} + +.primary-cta:focus { + outline: none; + box-shadow: 0 0 0 1px var(--blue60), 0 0 0 4px var(--primaryCtafocus); +} + +.primary-cta:active { + background-color: var(--primaryCtaActive); +} + +/* Mozilla VPN tout */ + +#moz-vpn-tout { + opacity: 0; + background-color: var(--bgColor); + visibility: visible; + max-block-size: 500px; + position: absolute; + inset-block-end: var(--footerHeight); + inset-inline-start: 0; + inset-inline-end: 0; + box-shadow: 0 0 7px 0 #9498a25e; + animation: appear 0.2s ease-out 0.5s forwards; + transition: opacity 0.1s ease-in-out, max-height 0.3s ease-in-out; +} + +#moz-vpn-tout.disappear { + animation: hideTout 0.2s ease-in forwards; +} + +@keyframes appear { + 0% { + opacity: 0; + transform: translateY(10%); + } + + 100% { + opacity: 1; + transform: translateY(0%); + } +} + +@keyframes hideTout { + 0% { + transform: translateY(0%); + opacity: 1; + } + + 50% { + opacity: 1; + } + + 100% { + transform: translateY(20%); + opacity: 0; + } +} + +/* Mozilla VPN Controller UI in Container Management Panel */ + +.moz-vpn-content, +.moz-vpn-controller-content { + display: flex; + position: relative; + flex-direction: column; + padding-block: 16px; + transition: max-height 0.3s ease-in-out, padding-block-end 0.2s ease-in-out; + + /* max-block-size: 56px; */ + min-block-size: 56px; + box-shadow: 0 0 0 1px var(--hr-grey); +} + +.moz-vpn-connection-status-indicator { + position: absolute; + inset-inline-end: 0; + background-position: center center; + background-repeat: no-repeat; + background-size: contain; + size: 0; + color: rgba(0, 0, 0, 0); + block-size: 24px; + inline-size: 24px; +} + +.current-country-flag { + display: inline-block; + background-repeat: no-repeat; + background-position: left center; + background-size: contain; + block-size: 16px; + inline-size: 16px; +} + +.moz-vpn-controller-content.show-server-button { + padding-block-end: 56px; + transition: 0.2s ease-in-out; +} + +.dismiss-moz-vpn-tout { + margin-inline-start: auto; + block-size: 24px; + inline-size: 24px; + background: var(--bgColor); + background-image: var(--iconCloseX); + border: none; + border-radius: 4px; +} + +.flag-img { + block-size: 13px; + margin-inline-end: 4px; + opacity: 0.9; +} + +.page-action-flag { + margin-inline-end: var(--marginInline); +} + +.display-none { + display: none; +} + +.proxy-disabled { + opacity: 0.4; +} + +fieldset.proxies { + position: absolute; + inset-block-start: 120px; + inset-inline-start: 0; + inset-inline-end: 0; + block-size: 60px; + display: flex; + background: #5cabff; + justify-content: center; + align-content: center; + align-items: center; + flex-direction: row; + pointer-events: none; +} + +input.proxies { + font-size: 6px; + block-size: 20px; + max-block-size: 20px; + padding-block: 0 !important; + padding-inline: 0 !important; + display: inline-flex; + inline-size: 40% !important; + pointer-events: none; +} + +.moz-vpn-cta { + block-size: 32px; + margin-block: 16px; + margin-inline: var(--marginInline); + text-align: center; +} + +.apply-to-container { + block-size: 32px; + inline-size: 100%; + text-align: center; + margin-block: 16px; +} + +#moz-vpn-current-server { + align-items: center; + border: none; + display: flex; + block-size: 48px; + margin-block-start: 8px; + background-image: var(--iconArrowRight); + background-position: calc(100% - 24px) center; + background-repeat: no-repeat; + background-size: 9px; + outline: none; + padding-inline-start: 20px; + visibility: visible; + position: absolute; + inset-block-end: 0; + inline-size: 100%; + opacity: 0; + transition: opacity 0.2s ease-in-out; +} + +.moz-vpn-controller-content.show-server-button #moz-vpn-current-server { + opacity: 1; +} + +.moz-vpn-controller-content.show-server-button #moz-vpn-current-server[disabled] { + opacity: 0.5; + cursor: not-allowed; +} + +@keyframes serverButtonAppear { + 0% { + opacity: 0; + visibility: hidden; + z-index: -1; + } + + 90% { + z-index: -1; + visibility: hidden; + } + + 100% { + visibility: visible; + z-index: 1; + opacity: 1; + } +} + +#moz-vpn-current-server.hidden { + block-size: 0; + opacity: 0; + visibility: hidden; + z-index: -1; +} + +.current-city-name { + padding-inline-start: 12px; +} + +.collapsible-content { + max-block-size: 0; + opacity: 0; + visibility: hidden; + background-color: var(--bgColor); + transition: max-height 0.2s ease-in-out, opacity 0.2s ease-in-out, visibility 0.2s ease-in-out; +} + +.moz-vpn-subtitle { + font-size: 12px; + flex: 0 1 80%; + color: var(--text-normal-color); +} + +.collapsible-content > .flx-row.flx-space-between { + inline-size: calc(100% - 40px); + margin-inline: auto; + padding-block-start: 12px; +} + +[disabled] { + pointer-events: none; + opacity: 0.5; +} + +#current-proxy { + font-size: 12px; + color: var(--grey30); + line-height: 13px; +} + +.expanded .collapsible-content { + max-block-size: 500px; + opacity: 1; + visibility: visible; +} + +.hide-label, +.show-label { + line-height: 100%; + position: absolute; + inset-inline-end: 0; + transition: visibility 0.2s ease-in-out, color 0.2s ease-in-out, opacity 0.2s ease-in-out; +} + +.expanded .hide-label, +.show-label { + visibility: visible; + opacity: 1; +} + +/* stylelint-disable */ +.hide-label, +.expanded .show-label { + visibility: hidden; + opacity: 0; +} + +/* stylelint-enable */ + +.expand-collapse { + inline-size: 50%; + margin-inline-start: auto; + pointer-events: all; +} + +.button-wrapper { + margin-inline: 20px; +} + +/* Advanced Proxy Settings Button */ + +#edit-advanced-proxy-input { + padding-inline-end: 40px; +} + +#edit-advanced-proxy-input.valid:focus { + box-shadow: 0 0 0 3px #3fe1b030; + border-color: var(--green80); +} + +.advanced-proxy-settings-btn { + background-color: var(--bgColor); + box-shadow: 0 0 0 1px var(--hr-grey); + background-image: var(--iconGear), var(--iconArrowRight); + background-position: 16px center, calc(100% - 24px) center; + background-repeat: no-repeat; + background-size: 24px 24px, 9px; + border: none; + color: var(--text-grey); + block-size: 56px; + min-block-size: 56px; + line-height: 19px; + display: flex; + flex-direction: column; + justify-content: center; + outline: none; + padding-inline-start: 44px; + z-index: 2; + transition: opacity 0.1s ease-in-out, background-color 0.1s ease-in-out; +} + +.disabled { + opacity: 0.5; + cursor: not-allowed; + pointer-events: none; +} + +.advanced-proxy-settings-btn:hover, +.advanced-proxy-settings-btn:focus { + background-color: var(--grey10); + outline: none; +} + +#clear-advanced-proxy-input { + position: absolute; + inset-inline-end: 8px; + inset-block-start: 7px; + border: none; + block-size: 22px; + inline-size: 22px; + border-radius: 50%; + background-image: var(--iconCloseX); + background-repeat: no-repeat; + background-position: center center; + background-size: 16px; + font-size: 1; + color: var(--bgColor); +} + +.proxy-title-container-color { + block-size: 12px; + inline-size: 12px; + z-index: 10; + border-radius: 50%; +} + +.advanced-proxy-panel-content { + padding-block: 16px; + padding-inline: 20px; + margin-block-start: 56px; + display: flex; + flex-direction: column; +} + +.advanced-proxy-input-wrapper { + margin-block-start: 12px; + position: relative; + display: flex; + flex-direction: column; +} + +.proxy-validity { + position: absolute; + inset-block-start: 42px; + inset-inline-start: 16px; + visibility: hidden; + opacity: 0; + background-color: var(--alertColor); + color: white; + border-radius: 4px; + padding-block: 2px; + padding-inline: 4px; + transition: opacity 0.2s ease-in-out, visibility 0.2s ease-in-out; +} + +.proxy-validity::after { + content: ""; + block-size: 8px; + inline-size: 8px; + background-color: var(--alertColor); + inset-block-start: -4px; + position: absolute; + transform: rotate(45deg); + inset-inline-start: 12px; +} + +.invalid .proxy-validity { + opacity: 1; + z-index: 10; + visibility: visible; +} + +.invalid .proxy-host.primary-input { + border-color: var(--red50); + box-shadow: 0 0 0 3px #ff848b70; +} + +.invalid button { + pointer-events: none; + opacity: 0.5; +} + +/* Mozilla VPN Server list */ + +.moz-vpn-logo, +.moz-vpn-logotype { + color: var(--text-heading-color); + background-image: var(--logoMozillaVpn); + background-repeat: no-repeat; + background-size: 24px; + background-position: left center; + font-family: var(--fontMetropolis); + font-size: 15px; + line-height: 24px; + padding-inline-start: 28px; + position: relative; + padding-inline-end: 32px; +} + +#moz-vpn-server-list-panel { + block-size: var(--panelSize); + max-block-size: var(--panelSize); + min-block-size: var(--panelSize); +} + +.proxy-panel-title { + line-height: var(--rowHeight); + block-size: var(--rowHeight); + border-block-end: 1px solid var(--hr-grey); + position: fixed; + z-index: 1; + background-color: var(--bgColor); + box-shadow: 0 0 13px -2px #b5b5b500; + transition: box-shadow 0.5s ease; +} + +.drop-shadow { + box-shadow: 0 0 13px -2px #b5b5b54d; +} + +.moz-vpn-server-list { + padding-block-start: 4px; + font-size: 15px; + color: var(--grey50); + position: absolute; + inset-block-start: var(--rowHeight); + inset-inline-start: 0; + inset-inline-end: 0; + overflow: scroll; + overscroll-behavior: none; + block-size: calc(var(--panelSize) - var(--rowHeight)); + min-block-size: calc(var(--panelSize) - var(--rowHeight)); +} + +#moz-vpn-return { + z-index: 2; +} + +.server-list-item { + display: flex; + flex-direction: column; + position: relative; + background-color: var(--bgColor); +} + +.server-country-flag { + inline-size: 16px; + margin-inline-start: 16px; + margin-block: auto; + pointer-events: none; +} + +.server-country-name { + padding-block: 0; + padding-inline-end: 0; + padding-inline-start: 20px; + font-family: var(--fontMetropolis); + pointer-events: none; + color: var(--text-heading-color); +} + +.server-city-list-item, +.server-city-list-visibility-btn { + block-size: 40px; + margin-block-start: 4px; + margin-block-end: 4px; + margin-inline-start: 8px; + margin-inline-end: 8px; + inline-size: calc(100% - 16px); +} + +.server-city-list-visibility-btn { + display: flex; + background-color: var(--bgColor); + border-radius: 4px; + border: none; + transition: background-color 0.3s ease; +} + +.server-city-list-visibility-btn:hover { + background-color: var(--grey10); +} + +.server-city-list-visibility-btn:active { + background-color: var(--grey20); +} + +.toggle { + background-image: url("/img/arrow-toggle.svg"); + background-position: center center; + background-repeat: no-repeat; + block-size: 24px; + margin-inline-start: 8px; + pointer-events: none; + transform: rotate(-90deg); + transition: transform 0.275s ease-in-out; + inline-size: 24px; +} + +.expanded .toggle { + transform: rotate(0deg); +} + +.server-city-list { + block-size: 0; + opacity: 0; + transition: height 0.3s ease-in-out, opacity 0.3s ease, visibility 0.4s ease; + list-style-type: none; + visibility: hidden; +} + +.expanded .server-city-list { + opacity: 1; + visibility: visible; +} + +.server-city-list-item { + align-items: center; + display: flex; + position: relative; +} + +.server-city-name { + font-family: var(--fontMetropolisLight); + font-weight: 300; + color: var(--text-grey); + padding-inline-start: 18px; +} + +/* ----- controller buttons ------- */ + +.controller { + background-color: var(--bgColor); + color: var(--text-grey); + transition: background-color 0.1s ease-in-out; +} + +.controller:hover, +.controller:focus { + background-color: var(--controllerHover); +} + +.controller:active { + background-color: var(--controllerActive); +} + +/* WARNING MODAL ---- */ + +.modal-warning { + position: absolute; + inset-block-start: 0; + inset-block-end: 0; + inset-inline-start: 0; + background-color: #42404c89; + z-index: 4; + display: flex; + justify-content: center; +} + +.modal-content { + background-color: var(--bgColor); + inline-size: 80%; + block-size: 80%; + margin-inline: auto; + margin-block: auto; + border-radius: 16px; + box-shadow: 1px 2px 10px 10px var(--bgDark); + padding-block: 20px; + padding-inline: 20px; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} + +/* ----- MozillaVPN Proxy Unavailable-Specific -------- */ + +[data-moz-proxy-warning="proxy-unavailable"] { + position: relative; +} + +.flag-img.proxy-unavailable { + opacity: 0.5; +} + +/* ----- MozillaVPN Status Tooltips -------- */ + +.tooltip { + opacity: 0; + position: absolute; + z-index: 10; + inset-block-start: 24px; + inset-inline-end: -3px; + font-size: 11px; + font-family: var(--fontInter) !important; + font-weight: 300; + color: var(--text-normal-color); + background-color: var(--bgColor); + padding-inline: 8px; + padding-block: 4px; + border-radius: 4px; + box-shadow: 0 0 12px 3px #0000001c; + transform: translateY(-2px); + transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out; + min-inline-size: 170px; + line-height: 1.3; + text-align: center; + pointer-events: none; +} + +.tooltip::before { + content: ""; + block-size: 7px; + inline-size: 7px; + border-radius: 1px; + transform: rotate(45deg); + background: inherit; + position: absolute; + inset-block-start: -3px; + inset-inline-end: 9px; +} + +[data-moz-proxy-warning="proxy-unavailable"]:hover .tooltip, +[data-moz-proxy-warning="proxy-unavailable"]:active .tooltip { + opacity: 1; + transform: translateY(0); + transition: opacity 0.2s ease-in-out 0.5s, transform 0.2s ease-in-out 0.5s; +} + +.moz-vpn-logotype.vpn-status-container-list:hover .tooltip { + opacity: 1; + transform: translateY(0); + transition: opacity 0.2s ease-in-out 1s, transform 0.2s ease-in-out 1s; +} + +.tooltip.proxy-unavailable::after { + inset-inline-start: 4px; + inset-inline-end: auto; +} + +.tooltip.proxy-unavailable::before { + inset-inline-start: 12px; +} + +.tooltip.proxy-unavailable { + inset-inline-start: 32px; + inset-block-start: 32px; + padding-inline-start: 32px; + text-align: left; + background-image: var(--iconProxyWarning); + background-size: 24px 24px; + background-repeat: no-repeat; + background-position: 4px 4px; +} + +/* ------------ SERVER LIST RADIO BUTTONS ------------ */ + +.server-radio-btn { + block-size: 20px; + opacity: 0; + position: fixed; + inline-size: 20px; +} + +.server-radio-control { + border-radius: 50%; + border: 2px solid var(--grey40); + block-size: 20px; + margin-inline-start: 46px; + pointer-events: none; + position: relative; + inline-size: 20px; + transition: border 0.1s ease-in-out; +} + +.server-radio-btn:checked + .server-radio-control { + border-color: var(--primaryCtaDefault); + transition: border-color 0.2s ease; +} + +.server-radio-control::after { + background-color: var(--grey40); + border-radius: 50%; + inset-block-end: 0; + content: ""; + block-size: 12px; + inset-inline-start: 0; + margin-inline: auto; + margin-block: auto; + opacity: 0; + position: absolute; + inset-inline-end: 0; + inset-block-start: 0; + transition: opacity 0.1s ease-in-out; + inline-size: 12px; +} + +/* Unchecked radio button styles */ + +.server-city-list-item:hover .server-radio-control { + border: 2px solid var(--grey50); +} + +.server-city-list-item:hover .server-radio-control::after { + opacity: 0.3; +} + +.server-city-list-item:active .server-radio-control::after { + opacity: 0.5; +} + +/* Checked radio button rules */ + +.server-city-list-item:hover .server-radio-btn:checked + .server-radio-control { + border: 2px solid var(--primaryCtaDefault); +} + +.server-radio-btn:checked + .server-radio-control::after { + background-color: var(--primaryCtaDefault); + opacity: 1; +} + +/* Helpers */ + +.add-bg-color { + background-color: var(--bgColor); + z-index: 2; +} + +.flx-space-between { + justify-content: space-between; +} + +.flx-row { + align-items: center; + display: flex; + flex-direction: row; +} + +/* stylelint-disable */ + +v-padding-hack16 { + block-size: 16px; +} + +v-padding-hack-4 { + block-size: 4px; + inline-size: 100%; +} + +v-padding-hack-footer { + block-size: var(--footerHeight); + inline-size: 100%; +} + +/* stylelint-enable */ + +.flx-col { + display: flex; + flex-direction: column; +} + +fieldset, +.options-header { + padding-block-end: 16px; +} + +.options-header { + display: none; +} + +/* ------ Input ----- */ + +input[type=text] { + block-size: 36px; + border-radius: 4px; + background-color: var(--bgColor); + color: var(--text-grey); + padding-block: 8px; + padding-inline: 8px; +} + +/* Blue links */ + +.blue-link { + box-sizing: content-box; + text-decoration: none; + align-items: center; + background-color: transparent; + border: none; + color: var(--primaryCtaDefault); + display: flex; + block-size: 24px; + line-height: 24px; + position: relative; + margin-inline: auto; + transition: color 0.1s ease-in-out; +} + +.blue-link, +.hide-show-label { + block-size: 24px; + line-height: 24px; +} + +.blue-link:hover { + color: var(--primaryCtaHover); +} + +.blue-link:focus, +.blue-link:focus .hide-show-label { + text-decoration: underline; + outline: none; +} + +/* ------------ ------------ ------------ ------------ */ + /* Panels keep everything together */ .panel { display: flex; flex-direction: column; justify-content: space-between; - min-block-size: 400px; + position: relative; + max-block-size: 601px; + background-color: var(--bgColor); + transition: height 0.1s ease-in-out; +} + +.container-panel { + min-block-size: 500px; +} + +.delete-container-panel { + min-block-size: 300px; } .panel.onboarding, .achievement-panel { align-items: center; - block-size: 360px; - margin-block-end: 16px; - margin-block-start: 16px; - margin-inline-end: 16px; - margin-inline-start: 16px; + margin-block: var(--marginInline); + margin-inline: var(--marginInline); min-block-size: 360px; } @@ -311,6 +1367,7 @@ table { margin-inline-end: 0; margin-inline-start: 0; max-inline-size: 80%; + font-family: var(--fontMetropolis); } .onboarding p { @@ -338,8 +1395,9 @@ table { align-items: center; display: flex; flex-direction: row; - height: 44px; + block-size: 44px; inline-size: 100%; + font-family: var(--fontMetropolis); } .half-onboarding-button { @@ -350,7 +1408,7 @@ table { display: flex; flex: 1 0 auto; font-size: 14px; - height: 44px; + block-size: 44px; inline-size: 50%; justify-content: center; margin-inline-end: 4px; @@ -360,7 +1418,7 @@ table { .grey-button { background-color: #e3e3e3; - color: #000; + color: var(--grey50); } .onboarding-button:hover, @@ -421,6 +1479,20 @@ manage things like container crud */ filter: url('/img/filters.svg#fill'); } +.usercontext-icon::before { + transform: scale(1); + transform-origin: center; + transition: fill 0.1s ease-in-out, transform 0.1s ease-in-out; +} + +.radio-container:active .usercontext-icon::before { + transform: scale(0.95); +} + +#edit-container-panel-choose-icon .radio-container:hover .usercontext-icon::before { + fill: var(--grey50) !important; +} + .mac-icon { background-image: url('/img/multiaccountcontainer-16.svg'); background-position: center center; @@ -442,11 +1514,11 @@ manage things like container crud */ fill: #0094fb; } -/* Panel Footer */ +/* Panel footer */ .panel-footer { align-items: center; background: #efefef; - block-size: var(--icon-button-size); + block-size: var(--footerHeight); border-block-end: 1px solid #d8d8d8; color: #000; display: flex; @@ -455,6 +1527,10 @@ manage things like container crud */ justify-content: space-between; } +#container-info-panel { + block-size: 100vh; +} + .container-info-has-tabs, .container-info-tab-row { align-items: center; @@ -516,8 +1592,9 @@ manage things like container crud */ .radio-choice > .radio-container { align-items: center; - block-size: 25px; + block-size: 32px; display: flex; + justify-content: center; flex: 0 0 calc(100% / var(--icon-fit)); } @@ -557,6 +1634,9 @@ manage things like container crud */ -moz-appearance: none; display: inline; opacity: 0; + position: absolute; + margin-block: auto; + margin-inline: auto; } .radio-choice > .radio-container > [type="radio"]:checked + label { @@ -576,42 +1656,27 @@ manage things like container crud */ display: flex; flex-direction: row; flex-wrap: wrap; - inline-size: 80%; - margin-block-end: 10px; - margin-inline-end: 0; - margin-inline-start: 0; - padding-block-end: 0; - padding-block-start: 0; - padding-inline-end: 0; - padding-inline-start: 0; } -.edit-container-panel fieldset:last-of-type { - margin-block-start: 16px; +#edit-container-choose-color { + justify-content: space-between; } .edit-container-panel input[type="text"] { - block-size: 36px; - border-radius: 3px; - font-size: 14px; inline-size: 100%; - padding-block-end: 5px; - padding-block-start: 5px; - padding-inline-end: 5px; - padding-inline-start: 5px; + margin-inline: 4px; +} + +input[type="text"]:focus { + box-shadow: 0 0 0 3px var(--primaryCtafocus); + outline: none; + border-color: var(--blue70); } .edit-container-panel legend, .options-header { + margin-inline: 4px; flex: 1 0; - font-size: 14px !important; - margin-block-end: 4px; - margin-block-start: -6px; -} - -.options-header { - margin-block-end: 8px; - margin-block-start: 6px; } /* Achievement panel elements */ @@ -643,8 +1708,8 @@ manage things like container crud */ } .cta-icon { - height: 18px; - padding-right: 0.5em; + block-size: 18px; + padding-inline-end: 0.5em; vertical-align: middle; } @@ -665,31 +1730,38 @@ manage things like container crud */ } h3.title { - block-size: 40px; + block-size: 48px; color: #000; - font-size: 13px; + font-family: var(--fontMetropolis); + font-size: 14px; font-weight: bold; inline-size: 100%; letter-spacing: -0.1px; - line-height: 40px; + line-height: 48px; text-align: center; } .menu { border-style: none; inline-size: 100%; + padding-block: 8px; } .menu-item { cursor: pointer; - height: 24px; + block-size: var(--menuItemHeight); inline-size: 100%; - line-height: 24px; + line-height: var(--menuItemHeight); +} + +.menu-text { + display: flex; + flex: 1; } .menu-item td { + align-items: center; display: flex; - max-inline-size: 300px; } .menu-item.drag-over td { @@ -702,9 +1774,13 @@ h3.title { font-style: italic; } +.hover-highlight { + transition: background-color 0.1s ease-in-out, color 0.1s ease-in-out; +} + .hover-highlight:hover, .hover-highlight:focus { - background: var(--highlight-blue); + background-color: var(--highlight-blue); color: #fff; } @@ -712,155 +1788,162 @@ h3.title { display: flex; inline-size: calc(100% - 40px); max-inline-size: 260px; -} - -.menu-text { - line-height: 24px; + cursor: default; } .menu-icon { display: block; - height: 16px; + block-size: 16px; inline-size: 23px; - margin-block-end: 4px; - margin-block-start: 4px; + margin-block-end: auto; + margin-block-start: auto; margin-inline-end: 8px; - margin-inline-start: 16px; + margin-inline-start: var(--marginInline); text-align: center; } -/* Maintain 1:1 square ratio for Favicons of websites added to a specific container */ +/* Maintain 1:1 square ratio for favicons of websites added to a specific container */ #edit-sites-assigned .menu-icon, #container-info-table .menu-icon { inline-size: 16px; } .menu-right-float { - height: 24px; - inline-size: 60px; text-align: right; + margin-inline-start: auto; + margin-inline-end: 0; + display: flex; + justify-content: flex-end; + align-items: center; + padding-inline-start: 16px; } .container-count { - opacity: 0.6; - padding-block-end: 0; - padding-block-start: 0; - padding-inline-end: 6px; - padding-inline-start: 0; - text-align: right; + opacity: 0.7; + text-align: center; + min-inline-size: 24px; + margin-inline-end: 4px; } .menu-arrow { - display: inline-block; - float: right; - height: 24px; - inline-size: 18px; - padding-block-end: 6px; - padding-block-start: 6px; - padding-inline-end: 12px; - padding-inline-start: 0; + align-items: center; + display: flex; + justify-content: flex-end; + block-size: 24px; + margin-inline-end: 20px; text-align: center; } .menu-arrow img { - height: 12px; + block-size: 24px; inline-size: 12px; padding-block-end: 2px; padding-block-start: 2px; padding-inline-end: 2px; padding-inline-start: 2px; + opacity: 0.9; } hr { border: 0; border-block-start: 1px solid var(--hr-grey); display: block; - margin-block-end: 0; - margin-block-start: 6px; - margin-inline-end: 0; - margin-inline-start: 0; - padding-block-end: 6px; - padding-block-start: 0; - padding-inline-end: 0; - padding-inline-start: 0; +} + +.sub-header-wrapper { + margin-block-start: 12px; } .sub-header { - color: var(--text-grey); - height: 24px; + color: var(--text-heading-color); + block-size: 24px; line-height: 24px; padding-block-end: 0; padding-block-start: 0; - padding-inline-end: 16px; - padding-inline-start: 16px; + padding-inline-start: 20px; + font-family: var(--fontInterMedium); } .edit-form { color: var(--text-grey); flex: 1; - padding-block-end: 0; - padding-block-start: 0; + padding-block-end: 16px; + padding-block-start: 16px; padding-inline-end: 16px; padding-inline-start: 16px; } -.identities-list { - margin-block-end: 41px; - margin-block-start: 0; - margin-inline-end: 0; - margin-inline-start: 0; -} - .bottom-btn { - background-color: var(--hr-grey); - border: solid 1px #d9d9d9; - cursor: pointer; - height: 41px; - inline-size: 100%; inset-block-end: 0; - line-height: 41px; - overflow: hidden; - padding-block-end: 0; - padding-block-start: 0; + box-shadow: 0 0 0 1px var(--hr-grey); + cursor: pointer; + block-size: var(--footerHeight); + inline-size: 100%; + line-height: var(--footerHeight); padding-inline-end: 16px; padding-inline-start: 16px; -} - -.delete-container { - background-color: #fff; - border-block-start: solid 1px var(--hr-grey); - cursor: default; - display: flex; - height: 65px; - inline-size: 100%; - justify-content: space-between; - padding-block-end: 27px; - padding-block-start: 9px; - padding-inline-end: 18px; - padding-inline-start: 17px; + position: absolute; + text-align: center; + font-size: 14px; + font-family: var(--fontMetropolis); + color: var(--text-heading-color); + pointer-events: all; } .delete-btn { - background-color: rgba(12, 12, 13, 0.1); - border: 0; - border-radius: 2px; + background-color: var(--bgColor); + border: none; + border-left: none; + border-right: none; + border-block-end: none; + box-shadow: 0 0 0 1px var(--hr-grey); + color: var(--alertColor); + cursor: default; + display: flex; + block-size: var(--rowHeight); + justify-content: center; + line-height: var(--rowHeight); + pointer-events: all; + transition: background-color 0.1s ease-in-out, border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out; +} + +.alert-text { + font-family: var(--fontMetropolis); + background-color: var(--bgColor); + color: var(--alertColor); cursor: pointer; - height: 30px; - inline-size: 100%; - line-height: 30px; text-align: center; } +.alert-text:hover, +.alert-text:focus { + background-color: rgba(255, 79, 94, 0.05); + box-shadow: 0 0 0 1px rgba(255, 79, 94, 0.05); +} + +.delete-btn:active { + background-color: rgba(255, 79, 94, 0.1); + box-shadow: 0 0 0 1px var(--alertColor); +} + +.delete-btn:focus { + box-shadow: 0 0 0 1px var(--alertColor); + outline: none; +} + .btn-return.arrow-left { - background-color: rgba(255, 255, 255, 1); - background-image: url("/img/arrow-icon-left.svg"); + background-image: var(--iconArrowLeft); border: 0; cursor: pointer; - height: 1.2rem; - inline-size: 1.2rem; - inset-block-start: 15px; - left: 15px; + inset-block-start: 8px; + inset-inline-start: 8px; position: absolute; + z-index: 2; + block-size: 32px; + inline-size: 32px; + background-repeat: no-repeat; + border-radius: 4px; + background-position: center center; } input { @@ -869,8 +1952,6 @@ input { } .form-header { - height: 23px; - line-height: 23px; padding-block-end: 0; padding-block-start: 0; padding-inline-end: 0; @@ -878,11 +1959,15 @@ input { } .edit-container-panel-name-input { - height: 29px; + color: var(--text-grey); + block-size: 32px; } .container-options { - height: 23px; + block-size: 24px; + margin-inline: 4px; + display: flex; + justify-content: space-between; } .site-isolation { @@ -891,20 +1976,16 @@ input { .options-label { cursor: pointer; - padding-inline-start: 4px; -} - -.manage-assigned-sites-list { - color: var(--highlight-blue); + pointer-events: none; } .info-icon { cursor: pointer; - height: 16px; + block-size: 16px; inline-size: 16px; - inset-block-start: 13px; + inset-block-start: 16px; position: absolute; - right: 13px; + inset-inline-end: 20px; text-align: center; text-decoration: none; } @@ -918,9 +1999,8 @@ input { .trash-button { display: inline-block; - float: right; - height: 16px; - inline-size: 16px; + block-size: 20px; + inline-size: 20px; margin-block-end: 4px; margin-block-start: 4px; margin-inline-end: 10px; @@ -939,48 +2019,104 @@ tr:hover > td > .trash-button { .move-button { cursor: move; display: inline-block; - height: 100%; - inline-size: 16px; - margin-block-end: 4px; - margin-block-start: 4px; - margin-inline-end: 10px; - margin-inline-start: auto; - text-align: center; } .move-button > img { - height: 16px; + block-size: 16px; + margin-inline-end: 20px; + margin-inline-start: 8px; } @media (prefers-color-scheme: dark) { :root { + --iconCloseX: url("/img/close-light.svg"); + --iconGear: url("/img/gear-icon-light.svg"); + --iconArrowRight: url("/img/arrow-icon-right-light.svg"); + --iconArrowLeft: url("/img/arrow-icon-left-light.svg"); + --iconProxyWarning: url("/img/proxy-warning-light.svg"); + --logoMozillaVpn: url("/img/moz-vpn-logo-light.svg"); + --bgColor: #42404c; --title-text-color: #fff; --text-normal-color: #f9f9fa; --text-heading-color: #fff; - } - - html { - background-color: #4a4a4a; + --primaryCtaDefault: var(--blue40); + --primaryCtaHover: var(--blue50); + --primaryCtaActive: var(--blue60); + --highlight-blue: #52515d; + --bottomButtons: var(--highlight-blue); + --controllerHover: var(--highlight-blue); + --controllerActive: rgb(90, 89, 102); + --bgDark: #2b2932; } body { - color: #fff; + color: #ffffffd1; + --highlight-blue: #52515d; --hr-grey: #38383d; - --text-grey: #f9f9fa; + --text-grey: #fefffe; + } + + .tooltip { + background-color: var(--controllerActive); + } + + #moz-vpn-tout { + box-shadow: 0 0 21px 3px #323139; + } + + .blue-link { + color: #36abfc; + } + + .blue-link:hover { + color: var(--blue20); + } + + .drop-shadow { + box-shadow: 0 0 13px -2px #323139; + } + + .server-radio-control { + border-color: var(--grey40); + } + + .server-radio-control::after { + background-color: var(--grey30); + } + + .server-city-list-item:hover .server-radio-control { + border-color: var(--grey30); + } + + .server-city-list-item:active .server-radio-control { + border-color: var(--grey20); + } + + .primary-cta:focus { + box-shadow: 0 0 0 1px #00ddffd6, 0 0 0 3px var(--primaryCtaHover); + } + + .slider { + background-color: var(--grey30); + } + + input:hover + .slider { + background-color: var(--grey40); + } + + input:focus + .slider { + box-shadow: 0 0 0 2px var(--bgColor), 0 0 0 4px var(--grey20); } h3.title { color: #fff; } + .delete-btn, .bottom-btn { - background-color: #737373; - border: solid 1px #737373; - } - - .btn-return.arrow-left { - background-color: transparent; + background-color: var(--bottomButtons); + box-shadow: 0 0 0 1px #73737300; } .onboarding-title, @@ -992,24 +2128,19 @@ tr:hover > td > .trash-button { border: solid 1px #737373; } - #edit-container-panel-name-input { - background-color: #38383d; - color: #fff; + input[type=text] { + background-color: rgba(43, 41, 50, 0.79) !important; } .delete-container { background-color: #4a4a4a; } - .delete-btn { - background-color: #737373; - color: #f9f9fa; - } - + .delete-btn, .cancel-button, .grey-button { - background-color: #737373; - color: #fff; + background-color: var(--bottomButtons); + color: #f9f9fa; } .button.secondary:hover, @@ -1021,11 +2152,16 @@ tr:hover > td > .trash-button { border-block-end: solid 1px #4a4a4a; } + input[type="text"]:focus { + box-shadow: 0 0 0 3px var(--blue50); + border-color: var(--blue30); + } + + .trash-button, img.menu-icon, .menu-icon > img, .menu-arrow > img, - .info-icon > img, - .btn-return.arrow-left { + .info-icon > img { filter: invert(1); } @@ -1035,15 +2171,34 @@ tr:hover > td > .trash-button { } .truncate-text::after { - background: #4a4a4a; - mask-image: linear-gradient(to right, transparent, #4a4a4a 70%); + background: var(--bgColor); + mask-image: linear-gradient(to right, transparent, var(--bgColor) 70%); } [data-identity-color="grey"] { --identity-icon-color: #ededf0; } - [type="radio"]:checked + [data-identity-color="grey"] { - --identity-icon-color: #616161; + .radio-choice > .radio-container > [type="radio"]:checked + label { + background: var(--bgDark); + } + + #edit-container-panel-choose-icon .radio-container:hover .usercontext-icon::before { + fill: #fff !important; } } + +/* OVERFLOW MENU */ + +.overflow body, +.overflow html { + inline-size: 100%; +} + +.overflow .container-panel { + min-block-size: 100%; +} + +.overflow .panel.onboarding { + margin-block: auto; +} diff --git a/src/fonts/Inter-Medium.woff2 b/src/fonts/Inter-Medium.woff2 new file mode 100644 index 0000000..7d0fbe9 Binary files /dev/null and b/src/fonts/Inter-Medium.woff2 differ diff --git a/src/fonts/Inter-Regular.woff2 b/src/fonts/Inter-Regular.woff2 new file mode 100644 index 0000000..554aed6 Binary files /dev/null and b/src/fonts/Inter-Regular.woff2 differ diff --git a/src/fonts/Metropolis-Light.woff2 b/src/fonts/Metropolis-Light.woff2 new file mode 100755 index 0000000..d276865 Binary files /dev/null and b/src/fonts/Metropolis-Light.woff2 differ diff --git a/src/fonts/Metropolis-Medium.woff2 b/src/fonts/Metropolis-Medium.woff2 new file mode 100755 index 0000000..d5aabb6 Binary files /dev/null and b/src/fonts/Metropolis-Medium.woff2 differ diff --git a/src/img/arrow-icon-left-light.svg b/src/img/arrow-icon-left-light.svg new file mode 100644 index 0000000..5a35ea8 --- /dev/null +++ b/src/img/arrow-icon-left-light.svg @@ -0,0 +1,3 @@ + diff --git a/src/img/arrow-icon-right-light.svg b/src/img/arrow-icon-right-light.svg new file mode 100644 index 0000000..d8549ce --- /dev/null +++ b/src/img/arrow-icon-right-light.svg @@ -0,0 +1,24 @@ + + + + + Arrow + Created with Sketch. + + + + + + + + + + + + + + + + diff --git a/src/img/arrow-icon-right.svg b/src/img/arrow-icon-right.svg index fa99e25..ba8df85 100644 --- a/src/img/arrow-icon-right.svg +++ b/src/img/arrow-icon-right.svg @@ -16,7 +16,7 @@ - + diff --git a/src/img/arrow-toggle.svg b/src/img/arrow-toggle.svg new file mode 100644 index 0000000..a16112c --- /dev/null +++ b/src/img/arrow-toggle.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/img/close-light.svg b/src/img/close-light.svg new file mode 100644 index 0000000..a2a88f1 --- /dev/null +++ b/src/img/close-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/img/close.svg b/src/img/close.svg new file mode 100644 index 0000000..1a004fc --- /dev/null +++ b/src/img/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/img/flags/AC.png b/src/img/flags/AC.png new file mode 100644 index 0000000..8e7a630 Binary files /dev/null and b/src/img/flags/AC.png differ diff --git a/src/img/flags/AD.png b/src/img/flags/AD.png new file mode 100644 index 0000000..69972df Binary files /dev/null and b/src/img/flags/AD.png differ diff --git a/src/img/flags/AE.png b/src/img/flags/AE.png new file mode 100644 index 0000000..11d2bb6 Binary files /dev/null and b/src/img/flags/AE.png differ diff --git a/src/img/flags/AF.png b/src/img/flags/AF.png new file mode 100644 index 0000000..7a37ec2 Binary files /dev/null and b/src/img/flags/AF.png differ diff --git a/src/img/flags/AG.png b/src/img/flags/AG.png new file mode 100644 index 0000000..8602fff Binary files /dev/null and b/src/img/flags/AG.png differ diff --git a/src/img/flags/AI.png b/src/img/flags/AI.png new file mode 100644 index 0000000..73f0c20 Binary files /dev/null and b/src/img/flags/AI.png differ diff --git a/src/img/flags/AL.png b/src/img/flags/AL.png new file mode 100644 index 0000000..a6d4573 Binary files /dev/null and b/src/img/flags/AL.png differ diff --git a/src/img/flags/AM.png b/src/img/flags/AM.png new file mode 100644 index 0000000..16ef38a Binary files /dev/null and b/src/img/flags/AM.png differ diff --git a/src/img/flags/AO.png b/src/img/flags/AO.png new file mode 100644 index 0000000..9349525 Binary files /dev/null and b/src/img/flags/AO.png differ diff --git a/src/img/flags/AQ.png b/src/img/flags/AQ.png new file mode 100644 index 0000000..d21e4ba Binary files /dev/null and b/src/img/flags/AQ.png differ diff --git a/src/img/flags/AR.png b/src/img/flags/AR.png new file mode 100644 index 0000000..a7d8a31 Binary files /dev/null and b/src/img/flags/AR.png differ diff --git a/src/img/flags/AS.png b/src/img/flags/AS.png new file mode 100644 index 0000000..a5cdfcc Binary files /dev/null and b/src/img/flags/AS.png differ diff --git a/src/img/flags/AT.png b/src/img/flags/AT.png new file mode 100644 index 0000000..3937efe Binary files /dev/null and b/src/img/flags/AT.png differ diff --git a/src/img/flags/AU.png b/src/img/flags/AU.png new file mode 100644 index 0000000..84a5180 Binary files /dev/null and b/src/img/flags/AU.png differ diff --git a/src/img/flags/AW.png b/src/img/flags/AW.png new file mode 100644 index 0000000..e250be9 Binary files /dev/null and b/src/img/flags/AW.png differ diff --git a/src/img/flags/AX.png b/src/img/flags/AX.png new file mode 100644 index 0000000..a5444fc Binary files /dev/null and b/src/img/flags/AX.png differ diff --git a/src/img/flags/AZ.png b/src/img/flags/AZ.png new file mode 100644 index 0000000..4f0c1c8 Binary files /dev/null and b/src/img/flags/AZ.png differ diff --git a/src/img/flags/BA.png b/src/img/flags/BA.png new file mode 100644 index 0000000..3ffe114 Binary files /dev/null and b/src/img/flags/BA.png differ diff --git a/src/img/flags/BB.png b/src/img/flags/BB.png new file mode 100644 index 0000000..e6fb3ed Binary files /dev/null and b/src/img/flags/BB.png differ diff --git a/src/img/flags/BD.png b/src/img/flags/BD.png new file mode 100644 index 0000000..c1c933e Binary files /dev/null and b/src/img/flags/BD.png differ diff --git a/src/img/flags/BE.png b/src/img/flags/BE.png new file mode 100644 index 0000000..d309207 Binary files /dev/null and b/src/img/flags/BE.png differ diff --git a/src/img/flags/BF.png b/src/img/flags/BF.png new file mode 100644 index 0000000..29064ff Binary files /dev/null and b/src/img/flags/BF.png differ diff --git a/src/img/flags/BG.png b/src/img/flags/BG.png new file mode 100644 index 0000000..0519f96 Binary files /dev/null and b/src/img/flags/BG.png differ diff --git a/src/img/flags/BH.png b/src/img/flags/BH.png new file mode 100644 index 0000000..28c3ec6 Binary files /dev/null and b/src/img/flags/BH.png differ diff --git a/src/img/flags/BI.png b/src/img/flags/BI.png new file mode 100644 index 0000000..7133116 Binary files /dev/null and b/src/img/flags/BI.png differ diff --git a/src/img/flags/BJ.png b/src/img/flags/BJ.png new file mode 100644 index 0000000..3ac1d99 Binary files /dev/null and b/src/img/flags/BJ.png differ diff --git a/src/img/flags/BL.png b/src/img/flags/BL.png new file mode 100644 index 0000000..aa9bb06 Binary files /dev/null and b/src/img/flags/BL.png differ diff --git a/src/img/flags/BM.png b/src/img/flags/BM.png new file mode 100644 index 0000000..1353129 Binary files /dev/null and b/src/img/flags/BM.png differ diff --git a/src/img/flags/BN.png b/src/img/flags/BN.png new file mode 100644 index 0000000..f861221 Binary files /dev/null and b/src/img/flags/BN.png differ diff --git a/src/img/flags/BO.png b/src/img/flags/BO.png new file mode 100644 index 0000000..21c555b Binary files /dev/null and b/src/img/flags/BO.png differ diff --git a/src/img/flags/BQ.png b/src/img/flags/BQ.png new file mode 100644 index 0000000..be922b0 Binary files /dev/null and b/src/img/flags/BQ.png differ diff --git a/src/img/flags/BR.png b/src/img/flags/BR.png new file mode 100644 index 0000000..642f3a5 Binary files /dev/null and b/src/img/flags/BR.png differ diff --git a/src/img/flags/BS.png b/src/img/flags/BS.png new file mode 100644 index 0000000..f959101 Binary files /dev/null and b/src/img/flags/BS.png differ diff --git a/src/img/flags/BT.png b/src/img/flags/BT.png new file mode 100644 index 0000000..ee668fb Binary files /dev/null and b/src/img/flags/BT.png differ diff --git a/src/img/flags/BV.png b/src/img/flags/BV.png new file mode 100644 index 0000000..d3a19fd Binary files /dev/null and b/src/img/flags/BV.png differ diff --git a/src/img/flags/BW.png b/src/img/flags/BW.png new file mode 100644 index 0000000..4aeeb13 Binary files /dev/null and b/src/img/flags/BW.png differ diff --git a/src/img/flags/BY.png b/src/img/flags/BY.png new file mode 100644 index 0000000..fc2051b Binary files /dev/null and b/src/img/flags/BY.png differ diff --git a/src/img/flags/BZ.png b/src/img/flags/BZ.png new file mode 100644 index 0000000..0c23f80 Binary files /dev/null and b/src/img/flags/BZ.png differ diff --git a/src/img/flags/CA.png b/src/img/flags/CA.png new file mode 100644 index 0000000..fe777da Binary files /dev/null and b/src/img/flags/CA.png differ diff --git a/src/img/flags/CC.png b/src/img/flags/CC.png new file mode 100644 index 0000000..f232d71 Binary files /dev/null and b/src/img/flags/CC.png differ diff --git a/src/img/flags/CD.png b/src/img/flags/CD.png new file mode 100644 index 0000000..f0855b2 Binary files /dev/null and b/src/img/flags/CD.png differ diff --git a/src/img/flags/CF.png b/src/img/flags/CF.png new file mode 100644 index 0000000..18a6891 Binary files /dev/null and b/src/img/flags/CF.png differ diff --git a/src/img/flags/CG.png b/src/img/flags/CG.png new file mode 100644 index 0000000..113face Binary files /dev/null and b/src/img/flags/CG.png differ diff --git a/src/img/flags/CH.png b/src/img/flags/CH.png new file mode 100644 index 0000000..bc50b99 Binary files /dev/null and b/src/img/flags/CH.png differ diff --git a/src/img/flags/CI.png b/src/img/flags/CI.png new file mode 100644 index 0000000..e19e84b Binary files /dev/null and b/src/img/flags/CI.png differ diff --git a/src/img/flags/CK.png b/src/img/flags/CK.png new file mode 100644 index 0000000..e5ca391 Binary files /dev/null and b/src/img/flags/CK.png differ diff --git a/src/img/flags/CL.png b/src/img/flags/CL.png new file mode 100644 index 0000000..d4d91d0 Binary files /dev/null and b/src/img/flags/CL.png differ diff --git a/src/img/flags/CM.png b/src/img/flags/CM.png new file mode 100644 index 0000000..457a061 Binary files /dev/null and b/src/img/flags/CM.png differ diff --git a/src/img/flags/CN.png b/src/img/flags/CN.png new file mode 100644 index 0000000..dcc0fb1 Binary files /dev/null and b/src/img/flags/CN.png differ diff --git a/src/img/flags/CO.png b/src/img/flags/CO.png new file mode 100644 index 0000000..0d2cf35 Binary files /dev/null and b/src/img/flags/CO.png differ diff --git a/src/img/flags/CP.png b/src/img/flags/CP.png new file mode 100644 index 0000000..662adc7 Binary files /dev/null and b/src/img/flags/CP.png differ diff --git a/src/img/flags/CR.png b/src/img/flags/CR.png new file mode 100644 index 0000000..69b41ac Binary files /dev/null and b/src/img/flags/CR.png differ diff --git a/src/img/flags/CU.png b/src/img/flags/CU.png new file mode 100644 index 0000000..00e3299 Binary files /dev/null and b/src/img/flags/CU.png differ diff --git a/src/img/flags/CV.png b/src/img/flags/CV.png new file mode 100644 index 0000000..88ac363 Binary files /dev/null and b/src/img/flags/CV.png differ diff --git a/src/img/flags/CW.png b/src/img/flags/CW.png new file mode 100644 index 0000000..83a5a7d Binary files /dev/null and b/src/img/flags/CW.png differ diff --git a/src/img/flags/CX.png b/src/img/flags/CX.png new file mode 100644 index 0000000..b6f3608 Binary files /dev/null and b/src/img/flags/CX.png differ diff --git a/src/img/flags/CY.png b/src/img/flags/CY.png new file mode 100644 index 0000000..5c333b0 Binary files /dev/null and b/src/img/flags/CY.png differ diff --git a/src/img/flags/CZ.png b/src/img/flags/CZ.png new file mode 100644 index 0000000..ecad9fd Binary files /dev/null and b/src/img/flags/CZ.png differ diff --git a/src/img/flags/DE.png b/src/img/flags/DE.png new file mode 100644 index 0000000..2933ab8 Binary files /dev/null and b/src/img/flags/DE.png differ diff --git a/src/img/flags/DG.png b/src/img/flags/DG.png new file mode 100644 index 0000000..aee82ba Binary files /dev/null and b/src/img/flags/DG.png differ diff --git a/src/img/flags/DJ.png b/src/img/flags/DJ.png new file mode 100644 index 0000000..24602c1 Binary files /dev/null and b/src/img/flags/DJ.png differ diff --git a/src/img/flags/DK.png b/src/img/flags/DK.png new file mode 100644 index 0000000..095ff86 Binary files /dev/null and b/src/img/flags/DK.png differ diff --git a/src/img/flags/DM.png b/src/img/flags/DM.png new file mode 100644 index 0000000..05f78c9 Binary files /dev/null and b/src/img/flags/DM.png differ diff --git a/src/img/flags/DO.png b/src/img/flags/DO.png new file mode 100644 index 0000000..4cb2f4a Binary files /dev/null and b/src/img/flags/DO.png differ diff --git a/src/img/flags/DZ.png b/src/img/flags/DZ.png new file mode 100644 index 0000000..8bdb882 Binary files /dev/null and b/src/img/flags/DZ.png differ diff --git a/src/img/flags/EA.png b/src/img/flags/EA.png new file mode 100644 index 0000000..fddf21a Binary files /dev/null and b/src/img/flags/EA.png differ diff --git a/src/img/flags/EC.png b/src/img/flags/EC.png new file mode 100644 index 0000000..05b0a2a Binary files /dev/null and b/src/img/flags/EC.png differ diff --git a/src/img/flags/EE.png b/src/img/flags/EE.png new file mode 100644 index 0000000..94d8d46 Binary files /dev/null and b/src/img/flags/EE.png differ diff --git a/src/img/flags/EG.png b/src/img/flags/EG.png new file mode 100644 index 0000000..29dfd5b Binary files /dev/null and b/src/img/flags/EG.png differ diff --git a/src/img/flags/EH.png b/src/img/flags/EH.png new file mode 100644 index 0000000..29d0791 Binary files /dev/null and b/src/img/flags/EH.png differ diff --git a/src/img/flags/ER.png b/src/img/flags/ER.png new file mode 100644 index 0000000..fd25d0e Binary files /dev/null and b/src/img/flags/ER.png differ diff --git a/src/img/flags/ES.png b/src/img/flags/ES.png new file mode 100644 index 0000000..5c449da Binary files /dev/null and b/src/img/flags/ES.png differ diff --git a/src/img/flags/ET.png b/src/img/flags/ET.png new file mode 100644 index 0000000..4f4e7fc Binary files /dev/null and b/src/img/flags/ET.png differ diff --git a/src/img/flags/EU.png b/src/img/flags/EU.png new file mode 100644 index 0000000..4f0b5d7 Binary files /dev/null and b/src/img/flags/EU.png differ diff --git a/src/img/flags/FI.png b/src/img/flags/FI.png new file mode 100644 index 0000000..34096f2 Binary files /dev/null and b/src/img/flags/FI.png differ diff --git a/src/img/flags/FJ.png b/src/img/flags/FJ.png new file mode 100644 index 0000000..3f4c0e0 Binary files /dev/null and b/src/img/flags/FJ.png differ diff --git a/src/img/flags/FK.png b/src/img/flags/FK.png new file mode 100644 index 0000000..5b2ecff Binary files /dev/null and b/src/img/flags/FK.png differ diff --git a/src/img/flags/FM.png b/src/img/flags/FM.png new file mode 100644 index 0000000..0fc25e8 Binary files /dev/null and b/src/img/flags/FM.png differ diff --git a/src/img/flags/FO.png b/src/img/flags/FO.png new file mode 100644 index 0000000..7f8e443 Binary files /dev/null and b/src/img/flags/FO.png differ diff --git a/src/img/flags/FR.png b/src/img/flags/FR.png new file mode 100644 index 0000000..662adc7 Binary files /dev/null and b/src/img/flags/FR.png differ diff --git a/src/img/flags/GA.png b/src/img/flags/GA.png new file mode 100644 index 0000000..6f73a37 Binary files /dev/null and b/src/img/flags/GA.png differ diff --git a/src/img/flags/GB.png b/src/img/flags/GB.png new file mode 100644 index 0000000..af56765 Binary files /dev/null and b/src/img/flags/GB.png differ diff --git a/src/img/flags/GD.png b/src/img/flags/GD.png new file mode 100644 index 0000000..66f160e Binary files /dev/null and b/src/img/flags/GD.png differ diff --git a/src/img/flags/GE.png b/src/img/flags/GE.png new file mode 100644 index 0000000..31af128 Binary files /dev/null and b/src/img/flags/GE.png differ diff --git a/src/img/flags/GF.png b/src/img/flags/GF.png new file mode 100644 index 0000000..99ff31b Binary files /dev/null and b/src/img/flags/GF.png differ diff --git a/src/img/flags/GG.png b/src/img/flags/GG.png new file mode 100644 index 0000000..72ac329 Binary files /dev/null and b/src/img/flags/GG.png differ diff --git a/src/img/flags/GH.png b/src/img/flags/GH.png new file mode 100644 index 0000000..2b19dbd Binary files /dev/null and b/src/img/flags/GH.png differ diff --git a/src/img/flags/GI.png b/src/img/flags/GI.png new file mode 100644 index 0000000..26d4ef7 Binary files /dev/null and b/src/img/flags/GI.png differ diff --git a/src/img/flags/GL.png b/src/img/flags/GL.png new file mode 100644 index 0000000..5df66b3 Binary files /dev/null and b/src/img/flags/GL.png differ diff --git a/src/img/flags/GM.png b/src/img/flags/GM.png new file mode 100644 index 0000000..4d1a3b4 Binary files /dev/null and b/src/img/flags/GM.png differ diff --git a/src/img/flags/GN.png b/src/img/flags/GN.png new file mode 100644 index 0000000..813c3ca Binary files /dev/null and b/src/img/flags/GN.png differ diff --git a/src/img/flags/GP.png b/src/img/flags/GP.png new file mode 100644 index 0000000..97a3dd9 Binary files /dev/null and b/src/img/flags/GP.png differ diff --git a/src/img/flags/GQ.png b/src/img/flags/GQ.png new file mode 100644 index 0000000..02b7aec Binary files /dev/null and b/src/img/flags/GQ.png differ diff --git a/src/img/flags/GR.png b/src/img/flags/GR.png new file mode 100644 index 0000000..0478442 Binary files /dev/null and b/src/img/flags/GR.png differ diff --git a/src/img/flags/GS.png b/src/img/flags/GS.png new file mode 100644 index 0000000..da4bbff Binary files /dev/null and b/src/img/flags/GS.png differ diff --git a/src/img/flags/GT.png b/src/img/flags/GT.png new file mode 100644 index 0000000..23cec33 Binary files /dev/null and b/src/img/flags/GT.png differ diff --git a/src/img/flags/GU.png b/src/img/flags/GU.png new file mode 100644 index 0000000..75c0945 Binary files /dev/null and b/src/img/flags/GU.png differ diff --git a/src/img/flags/GW.png b/src/img/flags/GW.png new file mode 100644 index 0000000..cf8c941 Binary files /dev/null and b/src/img/flags/GW.png differ diff --git a/src/img/flags/GY.png b/src/img/flags/GY.png new file mode 100644 index 0000000..2e102fd Binary files /dev/null and b/src/img/flags/GY.png differ diff --git a/src/img/flags/HK.png b/src/img/flags/HK.png new file mode 100644 index 0000000..412b684 Binary files /dev/null and b/src/img/flags/HK.png differ diff --git a/src/img/flags/HM.png b/src/img/flags/HM.png new file mode 100644 index 0000000..9972434 Binary files /dev/null and b/src/img/flags/HM.png differ diff --git a/src/img/flags/HN.png b/src/img/flags/HN.png new file mode 100644 index 0000000..e161777 Binary files /dev/null and b/src/img/flags/HN.png differ diff --git a/src/img/flags/HR.png b/src/img/flags/HR.png new file mode 100644 index 0000000..2dafc9a Binary files /dev/null and b/src/img/flags/HR.png differ diff --git a/src/img/flags/HT.png b/src/img/flags/HT.png new file mode 100644 index 0000000..afbf028 Binary files /dev/null and b/src/img/flags/HT.png differ diff --git a/src/img/flags/HU.png b/src/img/flags/HU.png new file mode 100644 index 0000000..b2f43f7 Binary files /dev/null and b/src/img/flags/HU.png differ diff --git a/src/img/flags/IC.png b/src/img/flags/IC.png new file mode 100644 index 0000000..44cb511 Binary files /dev/null and b/src/img/flags/IC.png differ diff --git a/src/img/flags/ID.png b/src/img/flags/ID.png new file mode 100644 index 0000000..4e8df64 Binary files /dev/null and b/src/img/flags/ID.png differ diff --git a/src/img/flags/IE.png b/src/img/flags/IE.png new file mode 100644 index 0000000..bbbeada Binary files /dev/null and b/src/img/flags/IE.png differ diff --git a/src/img/flags/IL.png b/src/img/flags/IL.png new file mode 100644 index 0000000..6c390c3 Binary files /dev/null and b/src/img/flags/IL.png differ diff --git a/src/img/flags/IM.png b/src/img/flags/IM.png new file mode 100644 index 0000000..99304fc Binary files /dev/null and b/src/img/flags/IM.png differ diff --git a/src/img/flags/IN.png b/src/img/flags/IN.png new file mode 100644 index 0000000..fcacf4c Binary files /dev/null and b/src/img/flags/IN.png differ diff --git a/src/img/flags/IO.png b/src/img/flags/IO.png new file mode 100644 index 0000000..7ef54ae Binary files /dev/null and b/src/img/flags/IO.png differ diff --git a/src/img/flags/IQ.png b/src/img/flags/IQ.png new file mode 100644 index 0000000..81de697 Binary files /dev/null and b/src/img/flags/IQ.png differ diff --git a/src/img/flags/IR.png b/src/img/flags/IR.png new file mode 100644 index 0000000..5147905 Binary files /dev/null and b/src/img/flags/IR.png differ diff --git a/src/img/flags/IS.png b/src/img/flags/IS.png new file mode 100644 index 0000000..349e9ef Binary files /dev/null and b/src/img/flags/IS.png differ diff --git a/src/img/flags/IT.png b/src/img/flags/IT.png new file mode 100644 index 0000000..2cd1da7 Binary files /dev/null and b/src/img/flags/IT.png differ diff --git a/src/img/flags/JE.png b/src/img/flags/JE.png new file mode 100644 index 0000000..bc974c1 Binary files /dev/null and b/src/img/flags/JE.png differ diff --git a/src/img/flags/JM.png b/src/img/flags/JM.png new file mode 100644 index 0000000..2a48a73 Binary files /dev/null and b/src/img/flags/JM.png differ diff --git a/src/img/flags/JO.png b/src/img/flags/JO.png new file mode 100644 index 0000000..5161701 Binary files /dev/null and b/src/img/flags/JO.png differ diff --git a/src/img/flags/JP.png b/src/img/flags/JP.png new file mode 100644 index 0000000..dd515aa Binary files /dev/null and b/src/img/flags/JP.png differ diff --git a/src/img/flags/KE.png b/src/img/flags/KE.png new file mode 100644 index 0000000..468ab95 Binary files /dev/null and b/src/img/flags/KE.png differ diff --git a/src/img/flags/KG.png b/src/img/flags/KG.png new file mode 100644 index 0000000..58f07a7 Binary files /dev/null and b/src/img/flags/KG.png differ diff --git a/src/img/flags/KH.png b/src/img/flags/KH.png new file mode 100644 index 0000000..cf9c1a6 Binary files /dev/null and b/src/img/flags/KH.png differ diff --git a/src/img/flags/KI.png b/src/img/flags/KI.png new file mode 100644 index 0000000..ee10d01 Binary files /dev/null and b/src/img/flags/KI.png differ diff --git a/src/img/flags/KM.png b/src/img/flags/KM.png new file mode 100644 index 0000000..1035f14 Binary files /dev/null and b/src/img/flags/KM.png differ diff --git a/src/img/flags/KN.png b/src/img/flags/KN.png new file mode 100644 index 0000000..e021417 Binary files /dev/null and b/src/img/flags/KN.png differ diff --git a/src/img/flags/KP.png b/src/img/flags/KP.png new file mode 100644 index 0000000..7e05f75 Binary files /dev/null and b/src/img/flags/KP.png differ diff --git a/src/img/flags/KR.png b/src/img/flags/KR.png new file mode 100644 index 0000000..8ff7ccd Binary files /dev/null and b/src/img/flags/KR.png differ diff --git a/src/img/flags/KW.png b/src/img/flags/KW.png new file mode 100644 index 0000000..76f53c2 Binary files /dev/null and b/src/img/flags/KW.png differ diff --git a/src/img/flags/KY.png b/src/img/flags/KY.png new file mode 100644 index 0000000..158d589 Binary files /dev/null and b/src/img/flags/KY.png differ diff --git a/src/img/flags/KZ.png b/src/img/flags/KZ.png new file mode 100644 index 0000000..d7e3401 Binary files /dev/null and b/src/img/flags/KZ.png differ diff --git a/src/img/flags/LA.png b/src/img/flags/LA.png new file mode 100644 index 0000000..44f5e8d Binary files /dev/null and b/src/img/flags/LA.png differ diff --git a/src/img/flags/LB.png b/src/img/flags/LB.png new file mode 100644 index 0000000..f506228 Binary files /dev/null and b/src/img/flags/LB.png differ diff --git a/src/img/flags/LC.png b/src/img/flags/LC.png new file mode 100644 index 0000000..1b7e53a Binary files /dev/null and b/src/img/flags/LC.png differ diff --git a/src/img/flags/LI.png b/src/img/flags/LI.png new file mode 100644 index 0000000..9a69e9a Binary files /dev/null and b/src/img/flags/LI.png differ diff --git a/src/img/flags/LK.png b/src/img/flags/LK.png new file mode 100644 index 0000000..8f8d0b3 Binary files /dev/null and b/src/img/flags/LK.png differ diff --git a/src/img/flags/LR.png b/src/img/flags/LR.png new file mode 100644 index 0000000..8ed6a5a Binary files /dev/null and b/src/img/flags/LR.png differ diff --git a/src/img/flags/LS.png b/src/img/flags/LS.png new file mode 100644 index 0000000..051b53a Binary files /dev/null and b/src/img/flags/LS.png differ diff --git a/src/img/flags/LT.png b/src/img/flags/LT.png new file mode 100644 index 0000000..69de64e Binary files /dev/null and b/src/img/flags/LT.png differ diff --git a/src/img/flags/LU.png b/src/img/flags/LU.png new file mode 100644 index 0000000..d7a507d Binary files /dev/null and b/src/img/flags/LU.png differ diff --git a/src/img/flags/LV.png b/src/img/flags/LV.png new file mode 100644 index 0000000..5505550 Binary files /dev/null and b/src/img/flags/LV.png differ diff --git a/src/img/flags/LY.png b/src/img/flags/LY.png new file mode 100644 index 0000000..426e931 Binary files /dev/null and b/src/img/flags/LY.png differ diff --git a/src/img/flags/MA.png b/src/img/flags/MA.png new file mode 100644 index 0000000..49d5f2f Binary files /dev/null and b/src/img/flags/MA.png differ diff --git a/src/img/flags/MC.png b/src/img/flags/MC.png new file mode 100644 index 0000000..cc71565 Binary files /dev/null and b/src/img/flags/MC.png differ diff --git a/src/img/flags/MD.png b/src/img/flags/MD.png new file mode 100644 index 0000000..72ab452 Binary files /dev/null and b/src/img/flags/MD.png differ diff --git a/src/img/flags/ME.png b/src/img/flags/ME.png new file mode 100644 index 0000000..ed5d0c4 Binary files /dev/null and b/src/img/flags/ME.png differ diff --git a/src/img/flags/MF.png b/src/img/flags/MF.png new file mode 100644 index 0000000..662adc7 Binary files /dev/null and b/src/img/flags/MF.png differ diff --git a/src/img/flags/MG.png b/src/img/flags/MG.png new file mode 100644 index 0000000..460baba Binary files /dev/null and b/src/img/flags/MG.png differ diff --git a/src/img/flags/MH.png b/src/img/flags/MH.png new file mode 100644 index 0000000..6b69a8d Binary files /dev/null and b/src/img/flags/MH.png differ diff --git a/src/img/flags/MK.png b/src/img/flags/MK.png new file mode 100644 index 0000000..9db397c Binary files /dev/null and b/src/img/flags/MK.png differ diff --git a/src/img/flags/ML.png b/src/img/flags/ML.png new file mode 100644 index 0000000..d7db739 Binary files /dev/null and b/src/img/flags/ML.png differ diff --git a/src/img/flags/MM.png b/src/img/flags/MM.png new file mode 100644 index 0000000..d4b642c Binary files /dev/null and b/src/img/flags/MM.png differ diff --git a/src/img/flags/MN.png b/src/img/flags/MN.png new file mode 100644 index 0000000..7f2225c Binary files /dev/null and b/src/img/flags/MN.png differ diff --git a/src/img/flags/MO.png b/src/img/flags/MO.png new file mode 100644 index 0000000..2fe5c8c Binary files /dev/null and b/src/img/flags/MO.png differ diff --git a/src/img/flags/MP.png b/src/img/flags/MP.png new file mode 100644 index 0000000..c9d6d57 Binary files /dev/null and b/src/img/flags/MP.png differ diff --git a/src/img/flags/MQ.png b/src/img/flags/MQ.png new file mode 100644 index 0000000..aa46f11 Binary files /dev/null and b/src/img/flags/MQ.png differ diff --git a/src/img/flags/MR.png b/src/img/flags/MR.png new file mode 100644 index 0000000..e976797 Binary files /dev/null and b/src/img/flags/MR.png differ diff --git a/src/img/flags/MS.png b/src/img/flags/MS.png new file mode 100644 index 0000000..fd6b759 Binary files /dev/null and b/src/img/flags/MS.png differ diff --git a/src/img/flags/MT.png b/src/img/flags/MT.png new file mode 100644 index 0000000..9265b06 Binary files /dev/null and b/src/img/flags/MT.png differ diff --git a/src/img/flags/MU.png b/src/img/flags/MU.png new file mode 100644 index 0000000..b48e01b Binary files /dev/null and b/src/img/flags/MU.png differ diff --git a/src/img/flags/MV.png b/src/img/flags/MV.png new file mode 100644 index 0000000..c666d7a Binary files /dev/null and b/src/img/flags/MV.png differ diff --git a/src/img/flags/MW.png b/src/img/flags/MW.png new file mode 100644 index 0000000..e58fe38 Binary files /dev/null and b/src/img/flags/MW.png differ diff --git a/src/img/flags/MX.png b/src/img/flags/MX.png new file mode 100644 index 0000000..61775bf Binary files /dev/null and b/src/img/flags/MX.png differ diff --git a/src/img/flags/MY.png b/src/img/flags/MY.png new file mode 100644 index 0000000..108dd99 Binary files /dev/null and b/src/img/flags/MY.png differ diff --git a/src/img/flags/MZ.png b/src/img/flags/MZ.png new file mode 100644 index 0000000..1a33e0c Binary files /dev/null and b/src/img/flags/MZ.png differ diff --git a/src/img/flags/NA.png b/src/img/flags/NA.png new file mode 100644 index 0000000..860139d Binary files /dev/null and b/src/img/flags/NA.png differ diff --git a/src/img/flags/NC.png b/src/img/flags/NC.png new file mode 100644 index 0000000..81fa763 Binary files /dev/null and b/src/img/flags/NC.png differ diff --git a/src/img/flags/NE.png b/src/img/flags/NE.png new file mode 100644 index 0000000..1f1dc36 Binary files /dev/null and b/src/img/flags/NE.png differ diff --git a/src/img/flags/NF.png b/src/img/flags/NF.png new file mode 100644 index 0000000..599da68 Binary files /dev/null and b/src/img/flags/NF.png differ diff --git a/src/img/flags/NG.png b/src/img/flags/NG.png new file mode 100644 index 0000000..6cbb424 Binary files /dev/null and b/src/img/flags/NG.png differ diff --git a/src/img/flags/NI.png b/src/img/flags/NI.png new file mode 100644 index 0000000..3f14038 Binary files /dev/null and b/src/img/flags/NI.png differ diff --git a/src/img/flags/NL.png b/src/img/flags/NL.png new file mode 100644 index 0000000..619bf8c Binary files /dev/null and b/src/img/flags/NL.png differ diff --git a/src/img/flags/NO.png b/src/img/flags/NO.png new file mode 100644 index 0000000..d758735 Binary files /dev/null and b/src/img/flags/NO.png differ diff --git a/src/img/flags/NP.png b/src/img/flags/NP.png new file mode 100644 index 0000000..48acf5f Binary files /dev/null and b/src/img/flags/NP.png differ diff --git a/src/img/flags/NR.png b/src/img/flags/NR.png new file mode 100644 index 0000000..1748da9 Binary files /dev/null and b/src/img/flags/NR.png differ diff --git a/src/img/flags/NU.png b/src/img/flags/NU.png new file mode 100644 index 0000000..9bd5ec1 Binary files /dev/null and b/src/img/flags/NU.png differ diff --git a/src/img/flags/NZ.png b/src/img/flags/NZ.png new file mode 100644 index 0000000..0d193b3 Binary files /dev/null and b/src/img/flags/NZ.png differ diff --git a/src/img/flags/OM.png b/src/img/flags/OM.png new file mode 100644 index 0000000..41176aa Binary files /dev/null and b/src/img/flags/OM.png differ diff --git a/src/img/flags/PA.png b/src/img/flags/PA.png new file mode 100644 index 0000000..6174229 Binary files /dev/null and b/src/img/flags/PA.png differ diff --git a/src/img/flags/PE.png b/src/img/flags/PE.png new file mode 100644 index 0000000..f7e5409 Binary files /dev/null and b/src/img/flags/PE.png differ diff --git a/src/img/flags/PF.png b/src/img/flags/PF.png new file mode 100644 index 0000000..f89b755 Binary files /dev/null and b/src/img/flags/PF.png differ diff --git a/src/img/flags/PG.png b/src/img/flags/PG.png new file mode 100644 index 0000000..d75762c Binary files /dev/null and b/src/img/flags/PG.png differ diff --git a/src/img/flags/PH.png b/src/img/flags/PH.png new file mode 100644 index 0000000..a0adbef Binary files /dev/null and b/src/img/flags/PH.png differ diff --git a/src/img/flags/PK.png b/src/img/flags/PK.png new file mode 100644 index 0000000..311ca9a Binary files /dev/null and b/src/img/flags/PK.png differ diff --git a/src/img/flags/PL.png b/src/img/flags/PL.png new file mode 100644 index 0000000..8d6921d Binary files /dev/null and b/src/img/flags/PL.png differ diff --git a/src/img/flags/PM.png b/src/img/flags/PM.png new file mode 100644 index 0000000..357a863 Binary files /dev/null and b/src/img/flags/PM.png differ diff --git a/src/img/flags/PN.png b/src/img/flags/PN.png new file mode 100644 index 0000000..a7ced0f Binary files /dev/null and b/src/img/flags/PN.png differ diff --git a/src/img/flags/PR.png b/src/img/flags/PR.png new file mode 100644 index 0000000..867df29 Binary files /dev/null and b/src/img/flags/PR.png differ diff --git a/src/img/flags/PS.png b/src/img/flags/PS.png new file mode 100644 index 0000000..9756c04 Binary files /dev/null and b/src/img/flags/PS.png differ diff --git a/src/img/flags/PT.png b/src/img/flags/PT.png new file mode 100644 index 0000000..246e2ce Binary files /dev/null and b/src/img/flags/PT.png differ diff --git a/src/img/flags/PW.png b/src/img/flags/PW.png new file mode 100644 index 0000000..8a7aea6 Binary files /dev/null and b/src/img/flags/PW.png differ diff --git a/src/img/flags/PY.png b/src/img/flags/PY.png new file mode 100644 index 0000000..8bc9da3 Binary files /dev/null and b/src/img/flags/PY.png differ diff --git a/src/img/flags/QA.png b/src/img/flags/QA.png new file mode 100644 index 0000000..3630990 Binary files /dev/null and b/src/img/flags/QA.png differ diff --git a/src/img/flags/RE.png b/src/img/flags/RE.png new file mode 100644 index 0000000..8010d88 Binary files /dev/null and b/src/img/flags/RE.png differ diff --git a/src/img/flags/RO.png b/src/img/flags/RO.png new file mode 100644 index 0000000..ce8f8e8 Binary files /dev/null and b/src/img/flags/RO.png differ diff --git a/src/img/flags/RS.png b/src/img/flags/RS.png new file mode 100644 index 0000000..0485b86 Binary files /dev/null and b/src/img/flags/RS.png differ diff --git a/src/img/flags/RU.png b/src/img/flags/RU.png new file mode 100644 index 0000000..9af1cb8 Binary files /dev/null and b/src/img/flags/RU.png differ diff --git a/src/img/flags/RW.png b/src/img/flags/RW.png new file mode 100644 index 0000000..2802d1a Binary files /dev/null and b/src/img/flags/RW.png differ diff --git a/src/img/flags/SA.png b/src/img/flags/SA.png new file mode 100644 index 0000000..5f90f43 Binary files /dev/null and b/src/img/flags/SA.png differ diff --git a/src/img/flags/SB.png b/src/img/flags/SB.png new file mode 100644 index 0000000..385dbaa Binary files /dev/null and b/src/img/flags/SB.png differ diff --git a/src/img/flags/SC.png b/src/img/flags/SC.png new file mode 100644 index 0000000..908f6b8 Binary files /dev/null and b/src/img/flags/SC.png differ diff --git a/src/img/flags/SD.png b/src/img/flags/SD.png new file mode 100644 index 0000000..5ef2fd9 Binary files /dev/null and b/src/img/flags/SD.png differ diff --git a/src/img/flags/SE.png b/src/img/flags/SE.png new file mode 100644 index 0000000..2cf2258 Binary files /dev/null and b/src/img/flags/SE.png differ diff --git a/src/img/flags/SG.png b/src/img/flags/SG.png new file mode 100644 index 0000000..454b82a Binary files /dev/null and b/src/img/flags/SG.png differ diff --git a/src/img/flags/SH.png b/src/img/flags/SH.png new file mode 100644 index 0000000..2d0df51 Binary files /dev/null and b/src/img/flags/SH.png differ diff --git a/src/img/flags/SI.png b/src/img/flags/SI.png new file mode 100644 index 0000000..86bffaf Binary files /dev/null and b/src/img/flags/SI.png differ diff --git a/src/img/flags/SJ.png b/src/img/flags/SJ.png new file mode 100644 index 0000000..d758735 Binary files /dev/null and b/src/img/flags/SJ.png differ diff --git a/src/img/flags/SK.png b/src/img/flags/SK.png new file mode 100644 index 0000000..276c387 Binary files /dev/null and b/src/img/flags/SK.png differ diff --git a/src/img/flags/SL.png b/src/img/flags/SL.png new file mode 100644 index 0000000..de88763 Binary files /dev/null and b/src/img/flags/SL.png differ diff --git a/src/img/flags/SM.png b/src/img/flags/SM.png new file mode 100644 index 0000000..ddecba8 Binary files /dev/null and b/src/img/flags/SM.png differ diff --git a/src/img/flags/SN.png b/src/img/flags/SN.png new file mode 100644 index 0000000..843bda4 Binary files /dev/null and b/src/img/flags/SN.png differ diff --git a/src/img/flags/SO.png b/src/img/flags/SO.png new file mode 100644 index 0000000..a4c573d Binary files /dev/null and b/src/img/flags/SO.png differ diff --git a/src/img/flags/SR.png b/src/img/flags/SR.png new file mode 100644 index 0000000..77cd1d3 Binary files /dev/null and b/src/img/flags/SR.png differ diff --git a/src/img/flags/SS.png b/src/img/flags/SS.png new file mode 100644 index 0000000..9cbf721 Binary files /dev/null and b/src/img/flags/SS.png differ diff --git a/src/img/flags/ST.png b/src/img/flags/ST.png new file mode 100644 index 0000000..f209bcd Binary files /dev/null and b/src/img/flags/ST.png differ diff --git a/src/img/flags/SV.png b/src/img/flags/SV.png new file mode 100644 index 0000000..333063f Binary files /dev/null and b/src/img/flags/SV.png differ diff --git a/src/img/flags/SX.png b/src/img/flags/SX.png new file mode 100644 index 0000000..72401f5 Binary files /dev/null and b/src/img/flags/SX.png differ diff --git a/src/img/flags/SY.png b/src/img/flags/SY.png new file mode 100644 index 0000000..3dae2a2 Binary files /dev/null and b/src/img/flags/SY.png differ diff --git a/src/img/flags/SZ.png b/src/img/flags/SZ.png new file mode 100644 index 0000000..0cf3fb1 Binary files /dev/null and b/src/img/flags/SZ.png differ diff --git a/src/img/flags/TA.png b/src/img/flags/TA.png new file mode 100644 index 0000000..15e4c3e Binary files /dev/null and b/src/img/flags/TA.png differ diff --git a/src/img/flags/TC.png b/src/img/flags/TC.png new file mode 100644 index 0000000..d3da08b Binary files /dev/null and b/src/img/flags/TC.png differ diff --git a/src/img/flags/TD.png b/src/img/flags/TD.png new file mode 100644 index 0000000..77184f4 Binary files /dev/null and b/src/img/flags/TD.png differ diff --git a/src/img/flags/TF.png b/src/img/flags/TF.png new file mode 100644 index 0000000..2c17f5e Binary files /dev/null and b/src/img/flags/TF.png differ diff --git a/src/img/flags/TG.png b/src/img/flags/TG.png new file mode 100644 index 0000000..d9b238a Binary files /dev/null and b/src/img/flags/TG.png differ diff --git a/src/img/flags/TH.png b/src/img/flags/TH.png new file mode 100644 index 0000000..218a284 Binary files /dev/null and b/src/img/flags/TH.png differ diff --git a/src/img/flags/TJ.png b/src/img/flags/TJ.png new file mode 100644 index 0000000..2fc5e4e Binary files /dev/null and b/src/img/flags/TJ.png differ diff --git a/src/img/flags/TK.png b/src/img/flags/TK.png new file mode 100644 index 0000000..122903d Binary files /dev/null and b/src/img/flags/TK.png differ diff --git a/src/img/flags/TL.png b/src/img/flags/TL.png new file mode 100644 index 0000000..2f69d8d Binary files /dev/null and b/src/img/flags/TL.png differ diff --git a/src/img/flags/TM.png b/src/img/flags/TM.png new file mode 100644 index 0000000..8e6fbb1 Binary files /dev/null and b/src/img/flags/TM.png differ diff --git a/src/img/flags/TN.png b/src/img/flags/TN.png new file mode 100644 index 0000000..0838b93 Binary files /dev/null and b/src/img/flags/TN.png differ diff --git a/src/img/flags/TO.png b/src/img/flags/TO.png new file mode 100644 index 0000000..6a680b1 Binary files /dev/null and b/src/img/flags/TO.png differ diff --git a/src/img/flags/TR.png b/src/img/flags/TR.png new file mode 100644 index 0000000..a80ec23 Binary files /dev/null and b/src/img/flags/TR.png differ diff --git a/src/img/flags/TT.png b/src/img/flags/TT.png new file mode 100644 index 0000000..7052a39 Binary files /dev/null and b/src/img/flags/TT.png differ diff --git a/src/img/flags/TV.png b/src/img/flags/TV.png new file mode 100644 index 0000000..44880af Binary files /dev/null and b/src/img/flags/TV.png differ diff --git a/src/img/flags/TW.png b/src/img/flags/TW.png new file mode 100644 index 0000000..d5d14ae Binary files /dev/null and b/src/img/flags/TW.png differ diff --git a/src/img/flags/TZ.png b/src/img/flags/TZ.png new file mode 100644 index 0000000..87c990d Binary files /dev/null and b/src/img/flags/TZ.png differ diff --git a/src/img/flags/UA.png b/src/img/flags/UA.png new file mode 100644 index 0000000..81db6c2 Binary files /dev/null and b/src/img/flags/UA.png differ diff --git a/src/img/flags/UG.png b/src/img/flags/UG.png new file mode 100644 index 0000000..f560449 Binary files /dev/null and b/src/img/flags/UG.png differ diff --git a/src/img/flags/UM.png b/src/img/flags/UM.png new file mode 100644 index 0000000..6d18cb7 Binary files /dev/null and b/src/img/flags/UM.png differ diff --git a/src/img/flags/UN.png b/src/img/flags/UN.png new file mode 100644 index 0000000..ea7fc4c Binary files /dev/null and b/src/img/flags/UN.png differ diff --git a/src/img/flags/US.png b/src/img/flags/US.png new file mode 100644 index 0000000..0ba0642 Binary files /dev/null and b/src/img/flags/US.png differ diff --git a/src/img/flags/UY.png b/src/img/flags/UY.png new file mode 100644 index 0000000..aa981ca Binary files /dev/null and b/src/img/flags/UY.png differ diff --git a/src/img/flags/UZ.png b/src/img/flags/UZ.png new file mode 100644 index 0000000..ae196dd Binary files /dev/null and b/src/img/flags/UZ.png differ diff --git a/src/img/flags/VA.png b/src/img/flags/VA.png new file mode 100644 index 0000000..f0fe36f Binary files /dev/null and b/src/img/flags/VA.png differ diff --git a/src/img/flags/VC.png b/src/img/flags/VC.png new file mode 100644 index 0000000..234bf65 Binary files /dev/null and b/src/img/flags/VC.png differ diff --git a/src/img/flags/VE.png b/src/img/flags/VE.png new file mode 100644 index 0000000..70a249f Binary files /dev/null and b/src/img/flags/VE.png differ diff --git a/src/img/flags/VG.png b/src/img/flags/VG.png new file mode 100644 index 0000000..7201718 Binary files /dev/null and b/src/img/flags/VG.png differ diff --git a/src/img/flags/VI.png b/src/img/flags/VI.png new file mode 100644 index 0000000..0feb6ae Binary files /dev/null and b/src/img/flags/VI.png differ diff --git a/src/img/flags/VN.png b/src/img/flags/VN.png new file mode 100644 index 0000000..5282bd4 Binary files /dev/null and b/src/img/flags/VN.png differ diff --git a/src/img/flags/VU.png b/src/img/flags/VU.png new file mode 100644 index 0000000..6047a7b Binary files /dev/null and b/src/img/flags/VU.png differ diff --git a/src/img/flags/WF.png b/src/img/flags/WF.png new file mode 100644 index 0000000..15746da Binary files /dev/null and b/src/img/flags/WF.png differ diff --git a/src/img/flags/WS.png b/src/img/flags/WS.png new file mode 100644 index 0000000..5356f6d Binary files /dev/null and b/src/img/flags/WS.png differ diff --git a/src/img/flags/XK.png b/src/img/flags/XK.png new file mode 100644 index 0000000..043e9b5 Binary files /dev/null and b/src/img/flags/XK.png differ diff --git a/src/img/flags/YE.png b/src/img/flags/YE.png new file mode 100644 index 0000000..e858bb2 Binary files /dev/null and b/src/img/flags/YE.png differ diff --git a/src/img/flags/YT.png b/src/img/flags/YT.png new file mode 100644 index 0000000..642b133 Binary files /dev/null and b/src/img/flags/YT.png differ diff --git a/src/img/flags/ZA.png b/src/img/flags/ZA.png new file mode 100644 index 0000000..4535007 Binary files /dev/null and b/src/img/flags/ZA.png differ diff --git a/src/img/flags/ZM.png b/src/img/flags/ZM.png new file mode 100644 index 0000000..6283325 Binary files /dev/null and b/src/img/flags/ZM.png differ diff --git a/src/img/flags/ZW.png b/src/img/flags/ZW.png new file mode 100644 index 0000000..d87fd6a Binary files /dev/null and b/src/img/flags/ZW.png differ diff --git a/src/img/gear-icon-light.svg b/src/img/gear-icon-light.svg new file mode 100644 index 0000000..c52fe68 --- /dev/null +++ b/src/img/gear-icon-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/img/gear-icon.svg b/src/img/gear-icon.svg new file mode 100644 index 0000000..ce8b1cb --- /dev/null +++ b/src/img/gear-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/img/info.svg b/src/img/info.svg new file mode 100644 index 0000000..a5f000a --- /dev/null +++ b/src/img/info.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/img/moz-vpn-connected.svg b/src/img/moz-vpn-connected.svg new file mode 100644 index 0000000..c28a9e9 --- /dev/null +++ b/src/img/moz-vpn-connected.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/img/moz-vpn-disconnected.svg b/src/img/moz-vpn-disconnected.svg new file mode 100644 index 0000000..bd7b5fd --- /dev/null +++ b/src/img/moz-vpn-disconnected.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/img/moz-vpn-logo-light.svg b/src/img/moz-vpn-logo-light.svg new file mode 100644 index 0000000..305e401 --- /dev/null +++ b/src/img/moz-vpn-logo-light.svg @@ -0,0 +1,14 @@ + + + + diff --git a/src/img/moz-vpn-logo.svg b/src/img/moz-vpn-logo.svg new file mode 100644 index 0000000..79449c4 --- /dev/null +++ b/src/img/moz-vpn-logo.svg @@ -0,0 +1,14 @@ + + + + diff --git a/src/img/moz-vpn-onboarding.svg b/src/img/moz-vpn-onboarding.svg new file mode 100644 index 0000000..488645f --- /dev/null +++ b/src/img/moz-vpn-onboarding.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/img/moz-vpn-status-icons/moz-vpn-connected.svg b/src/img/moz-vpn-status-icons/moz-vpn-connected.svg new file mode 100644 index 0000000..31e5581 --- /dev/null +++ b/src/img/moz-vpn-status-icons/moz-vpn-connected.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/img/moz-vpn-status-icons/moz-vpn-disconnected.svg b/src/img/moz-vpn-status-icons/moz-vpn-disconnected.svg new file mode 100644 index 0000000..c90bf81 --- /dev/null +++ b/src/img/moz-vpn-status-icons/moz-vpn-disconnected.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/img/no-connection.svg b/src/img/no-connection.svg new file mode 100644 index 0000000..02b8663 --- /dev/null +++ b/src/img/no-connection.svg @@ -0,0 +1,21 @@ + + + + + + image/svg+xml + + + + + + + diff --git a/src/img/onboarding-moz-vpn.svg b/src/img/onboarding-moz-vpn.svg new file mode 100644 index 0000000..cd451b2 --- /dev/null +++ b/src/img/onboarding-moz-vpn.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/img/proxy-warning-light.svg b/src/img/proxy-warning-light.svg new file mode 100644 index 0000000..72b5332 --- /dev/null +++ b/src/img/proxy-warning-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/img/proxy-warning.svg b/src/img/proxy-warning.svg new file mode 100644 index 0000000..ce5a29d --- /dev/null +++ b/src/img/proxy-warning.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/js/background/assignManager.js b/src/js/background/assignManager.js index eefbbda..7593ef7 100644 --- a/src/js/background/assignManager.js +++ b/src/js/background/assignManager.js @@ -186,13 +186,23 @@ window.assignManager = { async handleProxifiedRequest(requestInfo) { // The following blocks potentially dangerous requests for privacy that come without a tabId - if(requestInfo.tabId === -1) - return Utils.getBogusProxy(); + + if(requestInfo.tabId === -1) { + return {type: "direct"}; + } const tab = await browser.tabs.get(requestInfo.tabId); - const proxy = await proxifiedContainers.retrieveFromBackground(tab.cookieStoreId); + const result = await proxifiedContainers.retrieve(tab.cookieStoreId); + if (!result || !result.proxy) { + return {type: "direct"}; + } - return proxy; + if (!result.proxy.mozProxyEnabled) { + return result.proxy; + } + + // Let's add the isolation key. + return [{ ...result.proxy, connectionIsolationKey: "" + MozillaVPN_Background.isolationKey }]; }, // Before a request is handled by the browser we decide if we should diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index e33ee6a..05cad39 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -41,9 +41,11 @@ const backgroundLogic = { async deleteContainer(userContextId, removed = false) { await this._closeTabs(userContextId); + if (!removed) { await browser.contextualIdentities.remove(this.cookieStoreId(userContextId)); } + assignManager.deleteContainer(userContextId); // Now remove the identity->proxy association in proxifiedContainers also @@ -53,25 +55,13 @@ const backgroundLogic = { }, async createOrUpdateContainer(options) { - let donePromise; if (options.userContextId !== "new") { - donePromise = browser.contextualIdentities.update( + return await browser.contextualIdentities.update( this.cookieStoreId(options.userContextId), options.params ); - - proxifiedContainers.set(this.cookieStoreId(options.userContextId), options.proxy); - } else { - donePromise = browser.contextualIdentities.create(options.params); - - // We cannot yet access the new cookieStoreId via this.cookieStoreId(...), so we take this from the resolved promise - donePromise.then((identity) => { - proxifiedContainers.set(identity.cookieStoreId, options.proxy); - }).catch(() => { - // Empty because this should never happen theoretically. - }); } - await donePromise; + return await browser.contextualIdentities.create(options.params); }, async openNewTab(options) { @@ -160,7 +150,7 @@ const backgroundLogic = { } return await identityState.storageArea.set(cookieStoreId, containerState); } catch (error) { - console.error(`No container: ${cookieStoreId}`); + // console.error(`No container: ${cookieStoreId}`); } }, @@ -376,4 +366,4 @@ const backgroundLogic = { }; -backgroundLogic.init(); \ No newline at end of file +backgroundLogic.init(); diff --git a/src/js/background/badge.js b/src/js/background/badge.js index 7b6ccf3..b38d2a3 100644 --- a/src/js/background/badge.js +++ b/src/js/background/badge.js @@ -1,4 +1,4 @@ -const MAJOR_VERSIONS = ["2.3.0", "2.4.0", "6.2.0"]; +const MAJOR_VERSIONS = ["2.3.0", "2.4.0", "6.2.0", "8.0.0"]; const badge = { async init() { const currentWindow = await browser.windows.getCurrent(); diff --git a/src/js/background/index.html b/src/js/background/index.html index b29b062..818dbb4 100644 --- a/src/js/background/index.html +++ b/src/js/background/index.html @@ -16,6 +16,7 @@ + diff --git a/src/js/background/messageHandler.js b/src/js/background/messageHandler.js index b3270e5..37182bb 100644 --- a/src/js/background/messageHandler.js +++ b/src/js/background/messageHandler.js @@ -83,10 +83,10 @@ const messageHandler = { break; case "reloadInContainer": response = assignManager.reloadPageInContainer( - m.url, - m.currentUserContextId, - m.newUserContextId, - m.tabIndex, + m.url, + m.currentUserContextId, + m.newUserContextId, + m.tabIndex, m.active, true ); @@ -94,7 +94,7 @@ const messageHandler = { case "assignAndReloadInContainer": tab = await assignManager.reloadPageInContainer( m.url, - m.currentUserContextId, + m.currentUserContextId, m.newUserContextId, m.tabIndex, m.active, @@ -106,6 +106,22 @@ const messageHandler = { return assignManager._setOrRemoveAssignment(tab.id, m.url, m.newUserContextId, m.value); }); break; + + case "MozillaVPN_attemptPort": + MozillaVPN_Background.maybeInitPort(); + break; + case "MozillaVPN_queryServers": + MozillaVPN_Background.postToApp("servers"); + break; + case "MozillaVPN_queryStatus": + response = MozillaVPN_Background.postToApp("status"); + break; + case "MozillaVPN_getConnectionStatus": + response = MozillaVPN_Background.getConnectionStatus(); + break; + case "MozillaVPN_getInstallationStatus": + response = MozillaVPN_Background.getInstallationStatus(); + break; } return response; }); diff --git a/src/js/background/mozillaVpnBackground.js b/src/js/background/mozillaVpnBackground.js new file mode 100644 index 0000000..8a12730 --- /dev/null +++ b/src/js/background/mozillaVpnBackground.js @@ -0,0 +1,105 @@ +const MozillaVPN_Background = { + MOZILLA_VPN_SERVERS_KEY: "mozillaVpnServers", + MOZILLA_VPN_HIDDEN_TOUTS_LIST_KEY: "mozillaVpnHiddenToutsList", + + _isolationKey: 0, + + async maybeInitPort() { + if (this.port && this.port.error === null) { + return; + } + try { + /* + Find a way to not spam the console when MozillaVPN client is not installed + File at path ".../../MozillaVPN/..." is not executable.` thrown by resource://gre/modules/Subprocess.jsm:152` + Which does is not caught by this try/catch + */ + this.port = await browser.runtime.connectNative("mozillavpn"); + this.port.onMessage.addListener(response => this.handleResponse(response)); + + this.port.onMessage.addListener(this.handleResponse); + this.postToApp("status"); + this.postToApp("servers"); + + // When the mozillavpn dies or the VPN disconnects, we need to increase + // the isolation key in order to create new proxy connections. Otherwise + // we could see random timeout when the browser tries to connect to an + // invalid proxy connection. + this.port.onDisconnect.addListener(() => this.increaseIsolationKey()); + + } catch(e) { + this._installed = false; + this._connected = false; + } + }, + + async init() { + const { mozillaVpnServers } = await browser.storage.local.get(this.MOZILLA_VPN_SERVERS_KEY); + if (typeof(mozillaVpnServers) === "undefined") { + await browser.storage.local.set({ [this.MOZILLA_VPN_SERVERS_KEY]:[] }); + await browser.storage.local.set({ [this.MOZILLA_VPN_HIDDEN_TOUTS_LIST_KEY]:[] }); + this._installed = false; + this._connected = false; + } + this.maybeInitPort(); + }, + + getConnectionStatus() { + return this._connected; + }, + + getInstallationStatus() { + return this._installed; + }, + + // Post messages to MozillaVPN client + postToApp(message) { + try { + this.port.postMessage({t: message}); + } catch(e) { + if (e.message === "Attempt to postMessage on disconnected port") { + this._installed = false; + this._connected = false; + } + } + }, + + // Handle responses from MozillaVPN client + async handleResponse(response) { + if (response.error && response.error === "vpn-client-down") { + MozillaVPN_Background._connected = false; + return; + } + MozillaVPN_Background._installed = true; + if (response.servers) { + const servers = response.servers.countries; + browser.storage.local.set({ [MozillaVPN_Background.MOZILLA_VPN_SERVERS_KEY]: servers}); + return; + } + + if ((response.status && response.status.vpn) || response.t === "status") { + const status = response.status ? response.status.vpn : response.vpn; + + if (status === "StateOn") { + MozillaVPN_Background._connected = true; + } + + if (status === "StateOff" || status === "StateDisconnecting") { + MozillaVPN_Background._connected = false; + } + + // Let's increase the network key isolation at any vpn status change. + MozillaVPN_Background.increaseIsolationKey(); + } + }, + + increaseIsolationKey() { + ++this._isolationKey; + }, + + get isolationKey() { + return this._isolationKey; + }, +}; + +MozillaVPN_Background.init(); diff --git a/src/js/mozillaVpn.js b/src/js/mozillaVpn.js new file mode 100644 index 0000000..3f6a78d --- /dev/null +++ b/src/js/mozillaVpn.js @@ -0,0 +1,246 @@ +const MozillaVPN = { + + async handleContainerList(identities) { + const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); + const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); + this.handleStatusIndicatorsInContainerLists(mozillaVpnInstalled); + + const proxies = await this.getProxies(identities); + if (Object.keys(proxies).length === 0) { + return; + } + + for (const el of document.querySelectorAll("[data-cookie-store-id]")) { + const cookieStoreId = el.dataset.cookieStoreId; + + if (!proxies[cookieStoreId]) { + continue; + } + const { proxy } = proxies[cookieStoreId]; + + if (typeof(proxy) !== "undefined") { + const flag = el.querySelector(".flag-img"); + if (proxy.countryCode) { + flag.src = `/img/flags/${proxy.countryCode.toUpperCase()}.png`; + } + if (typeof(proxy.mozProxyEnabled) === "undefined" && typeof(proxy.countryCode) !== "undefined") { + flag.classList.add("proxy-disabled"); + } + if (!mozillaVpnConnected && proxy.mozProxyEnabled) { + flag.classList.add("proxy-unavailable"); + const menuItemName = el.querySelector(".menu-item-name"); + if (menuItemName) { + el.querySelector(".menu-item-name").dataset.mozProxyWarning = "proxy-unavailable"; + } + } + } + } + }, + + async setStatusIndicatorIcons(mozillaVpnInstalled) { + + const statusIconEls = document.querySelectorAll(".moz-vpn-connection-status-indicator"); + + if (!mozillaVpnInstalled) { + statusIconEls.forEach(el => { + el.style.backgroundImage = "none"; + if (el.querySelector(".tooltip")) { + el.querySelector(".tooltip").textContent = ""; + } + el.textContent = ""; + }); + return; + } + + const connectedIndicatorSrc = "url(./img/moz-vpn-connected.svg)"; + const disconnectedIndicatorSrc = "url(./img/moz-vpn-disconnected.svg)"; + + const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); + const connectionStatusStringId = mozillaVpnConnected ? "moz-vpn-connected" : "moz-vpn-disconnected"; + const connectionStatusLocalizedString = browser.i18n.getMessage(connectionStatusStringId); + + statusIconEls.forEach(el => { + el.style.backgroundImage = mozillaVpnConnected ? connectedIndicatorSrc : disconnectedIndicatorSrc; + if (el.querySelector(".tooltip")) { + el.querySelector(".tooltip").textContent = connectionStatusLocalizedString; + } else { + el.textContent = connectionStatusLocalizedString; + } + }); + }, + + async handleStatusIndicatorsInContainerLists(mozillaVpnInstalled) { + const mozVpnLogotypes = document.querySelectorAll(".moz-vpn-logotype.vpn-status-container-list"); + + try { + if (!mozillaVpnInstalled) { + mozVpnLogotypes.forEach(el => { + el.style.display = "none"; + }); + return; + } + mozVpnLogotypes.forEach(el => { + el.style.display = "flex"; + el.classList.remove("display-none"); + }); + this.setStatusIndicatorIcons(mozillaVpnInstalled); + } catch (e) { + mozVpnLogotypes.forEach(el => { + el.style.display = "none"; + }); + return; + } + }, + + handleMozillaCtaClick(buttonIdentifier) { + browser.tabs.create({ + url: MozillaVPN.attachUtmParameters("https://www.mozilla.org/products/vpn", buttonIdentifier), + }); + }, + + getRandomInteger(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; + }, + + proxyIsDisabled(proxy) { + return ( + // Mozilla VPN proxy is disabled, last location data is stored + (proxy.mozProxyEnabled === undefined && proxy.countryCode !== undefined && proxy.cityName !== undefined) || + // Mozilla VPN proxy is enabled but Mozilla VPN is not connected + proxy.mozProxyEnabled !== undefined + ); + }, + + attachUtmParameters(baseUrl, utmContent) { + const url = new URL(baseUrl); + const utmParameters = { + utm_source: "multi.account.containers", + utm_medium: "mac-browser-addon", + utm_content: utmContent, + utm_campaign: "vpn-better-together", + }; + + for (const param in utmParameters) { + url.searchParams.append(param, utmParameters[param]); + } + return url.href; + }, + + async getProxies(identities) { + const proxies = {}; + const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); + + if (mozillaVpnInstalled) { + for (const identity of identities) { + try { + const proxy = await proxifiedContainers.retrieve(identity.cookieStoreId); + proxies[identity.cookieStoreId] = proxy; + } catch (e) { + proxies[identity.cookieStoreId] = {}; + } + } + } + return proxies; + }, + + getMozillaProxyInfoObj() { + return { + countryCode: undefined, + cityName: undefined, + mozProxyEnabled: undefined + }; + }, + + + async getProxyWarnings(proxyObj) { + if (!proxyObj) { + return ""; + } + + const { proxy } = proxyObj; + + if (typeof(proxy) === "undefined") { + return ""; + } + + const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); + if (typeof(proxy.mozProxyEnabled) !== "undefined" && !mozillaVpnConnected) { + return "proxy-unavailable"; + } + }, + + async getFlag(proxyObj) { + const flag = { + imgCode: "default", + elemClasses: "display-none", + imgAlt: "", + }; + + if (!proxyObj) { + return flag; + } + + const { proxy } = proxyObj; + const mozillaVpnInstalled = await browser.runtime.sendMessage({ method: "MozillaVPN_getInstallationStatus" }); + if (typeof(proxy) === "undefined" || !mozillaVpnInstalled) { + return flag; + } + + const mozillaVpnConnected = await browser.runtime.sendMessage({ method: "MozillaVPN_getConnectionStatus" }); + if (mozillaVpnInstalled && typeof(proxy.cityName) !== "undefined") { + flag.imgCode = proxy.countryCode.toUpperCase(); + flag.imgAlt = proxy.cityName; + flag.elemClasses = typeof(proxy.mozProxyEnabled) === "undefined" || !mozillaVpnConnected ? "proxy-disabled" : ""; + } + + return flag; + }, + + getProxy(countryCode, cityName, mozProxyEnabled, mozillaVpnServers) { + const selectedServerCountry = mozillaVpnServers.find(({code}) => code === countryCode); + const selectedServerCity = selectedServerCountry.cities.find(({name}) => name === cityName); + const proxyServer = this.pickServerBasedOnWeight(selectedServerCity.servers); + return proxifiedContainers.parseProxy( + this.makeProxyString(proxyServer.socksName), + { + countryCode: countryCode, + cityName: cityName, + mozProxyEnabled, + } + ); + }, + + makeProxyString(socksName) { + return `socks://${socksName}.mullvad.net:1080`; + }, + + async pickRandomLocation() { + const { mozillaVpnServers } = await browser.storage.local.get("mozillaVpnServers"); + const randomInteger = this.getRandomInteger(0, mozillaVpnServers.length - 1); + const randomServerCountry = mozillaVpnServers[randomInteger]; + + return { + randomServerCountryCode: randomServerCountry.code, + randomServerCityName: randomServerCountry.cities[0].name, + }; + + }, + + pickServerBasedOnWeight(serverList) { + const filteredServerList = serverList.filter(server => typeof(server.socksName) !== "undefined" && server.socksName !== ""); + + const sumWeight = filteredServerList.reduce((sum, { weight }) => sum + weight, 0); + let randomInteger = this.getRandomInteger(0, sumWeight); + + let nextServer = {}; + for (const server of filteredServerList) { + if (server.weight >= randomInteger) { + return nextServer = server; + } + randomInteger = (randomInteger - server.weight); + } + return nextServer; + } +}; + +window.MozillaVPN = MozillaVPN; diff --git a/src/js/pageAction.js b/src/js/pageAction.js index 91445ce..bc0ba3c 100644 --- a/src/js/pageAction.js +++ b/src/js/pageAction.js @@ -1,22 +1,23 @@ async function init() { const fragment = document.createDocumentFragment(); - const identities = await browser.contextualIdentities.query({}); - identities.forEach(identity => { + for (const identity of identities) { const tr = document.createElement("tr"); tr.classList.add("menu-item", "hover-highlight"); + tr.setAttribute("data-cookie-store-id", identity.cookieStoreId); const td = document.createElement("td"); - - td.innerHTML = Utils.escaped` + td.innerHTML = Utils.escaped` - ${identity.name}`; - + ${identity.name} + + `; + tr.appendChild(td); fragment.appendChild(tr); @@ -24,12 +25,13 @@ async function init() { Utils.alwaysOpenInContainer(identity); window.close(); }); - }); + } const list = document.querySelector("#picker-identities-list"); - list.innerHTML = ""; list.appendChild(fragment); + + MozillaVPN.handleContainerList(identities); } init(); diff --git a/src/js/popup.js b/src/js/popup.js index ce91c91..33ddb09 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -21,6 +21,8 @@ const P_ONBOARDING_4 = "onboarding4"; const P_ONBOARDING_5 = "onboarding5"; const P_ONBOARDING_6 = "onboarding6"; const P_ONBOARDING_7 = "onboarding7"; +const P_ONBOARDING_8 = "onboarding8"; + const P_CONTAINERS_LIST = "containersList"; const OPEN_NEW_CONTAINER_PICKER = "new-tab"; const MANAGE_CONTAINERS_PICKER = "manage"; @@ -32,6 +34,9 @@ const P_CONTAINER_DELETE = "containerDelete"; const P_CONTAINERS_ACHIEVEMENT = "containersAchievement"; const P_CONTAINER_ASSIGNMENTS = "containerAssignments"; +const P_MOZILLA_VPN_SERVER_LIST = "moz-vpn-server-list"; +const P_ADVANCED_PROXY_SETTINGS = "advanced-proxy-settings-panel"; + function addRemoveSiteIsolation() { const identity = Logic.currentIdentity(); browser.runtime.sendMessage({ @@ -57,6 +62,10 @@ const Logic = { _onboardingVariation: null, async init() { + browser.runtime.sendMessage({ + method: "MozillaVPN_attemptPort" + }), + // Remove browserAction "upgraded" badge when opening panel this.clearBrowserActionBadge(); @@ -74,16 +83,19 @@ const Logic = { const onboardingData = await browser.storage.local.get([ONBOARDING_STORAGE_KEY]); let onboarded = onboardingData[ONBOARDING_STORAGE_KEY]; if (!onboarded) { - onboarded = 0; + onboarded = 9; this.setOnboardingStage(onboarded); } switch (onboarded) { - case 7: + case 8: this.showAchievementOrContainersListPanel(); break; + case 7: + this.showPanel(P_ONBOARDING_8); + break; case 6: - this.showPanel(P_ONBOARDING_7); + this.showPanel(P_ONBOARDING_8); break; case 5: this.showPanel(P_ONBOARDING_6); @@ -148,7 +160,7 @@ const Logic = { async clearBrowserActionBadge() { const extensionInfo = await getExtensionInfo(); const storage = await browser.storage.local.get({ browserActionBadgesClicked: [] }); - browser.browserAction.setBadgeBackgroundColor({ color: null }); + browser.browserAction.setBadgeBackgroundColor({ color: "#ffffff" }); browser.browserAction.setBadgeText({ text: "" }); storage.browserActionBadgesClicked.push(extensionInfo.version); // use set and spread to create a unique array @@ -243,8 +255,8 @@ const Logic = { } }, - async showPanel(panel, currentIdentity = null, backwards = false) { - if (!backwards || !this._currentPanel) { + async showPanel(panel, currentIdentity = null, backwards = false, addToPreviousPanelPath = true) { + if ((!backwards && addToPreviousPanelPath) || !this._currentPanel) { this._previousPanelPath.push(this._currentPanel); } @@ -375,7 +387,7 @@ const Logic = { const closeContEl = document.querySelector("#close-container-picker-panel"); if (!this._listenerSet) { Utils.addEnterHandler(closeContEl, () => { - Logic.showPreviousPanel(); + Logic.showPanel(P_CONTAINERS_LIST); }); this._listenerSet = true; } @@ -585,12 +597,12 @@ Logic.registerPanel(P_ONBOARDING_6, { Logic.showPanel(P_ONBOARDING_7); }); Utils.addEnterHandler(document.querySelector("#no-sync"), async () => { - await Logic.setOnboardingStage(7); + await Logic.setOnboardingStage(6); await browser.storage.local.set({syncEnabled: false}); await browser.runtime.sendMessage({ method: "resetSync" }); - Logic.showPanel(P_CONTAINERS_LIST); + Logic.showPanel(P_ONBOARDING_8); }); }, @@ -599,9 +611,7 @@ Logic.registerPanel(P_ONBOARDING_6, { return Promise.resolve(null); }, }); - -// P_ONBOARDING_6: Sixth page for Onboarding: new tab long-press behavior -// ---------------------------------------------------------------------------- +// ----------------------------------------------------------------------- Logic.registerPanel(P_ONBOARDING_7, { panelSelector: ".onboarding-panel-7", @@ -614,10 +624,27 @@ Logic.registerPanel(P_ONBOARDING_7, { url: "https://accounts.firefox.com/?service=sync&action=email&context=fx_desktop_v3&entrypoint=multi-account-containers&utm_source=addon&utm_medium=panel&utm_campaign=container-sync", }); await Logic.setOnboardingStage(7); - Logic.showPanel(P_CONTAINERS_LIST); + Logic.showPanel(P_ONBOARDING_8); }); Utils.addEnterHandler(document.querySelector("#no-sign-in"), async () => { await Logic.setOnboardingStage(7); + Logic.showPanel(P_ONBOARDING_8); + }); + }, + + // This method is called when the panel is shown. + prepare() { + return Promise.resolve(null); + }, +}); + +Logic.registerPanel(P_ONBOARDING_8, { + panelSelector: ".onboarding-panel-8", + + // This method is called when the object is registered. + initialize() { + Utils.addEnterHandler(document.querySelector("#onboarding-done-btn"), async () => { + await Logic.setOnboardingStage(8); Logic.showPanel(P_CONTAINERS_LIST); }); }, @@ -635,6 +662,24 @@ Logic.registerPanel(P_CONTAINERS_LIST, { // This method is called when the object is registered. async initialize() { + const mozillaVpnToutName = "moz-tout-main-panel"; + + await browser.runtime.sendMessage({ method: "MozillaVPN_queryStatus" }); + Utils.addEnterHandler(document.querySelector("#moz-vpn-learn-more"), () => { + MozillaVPN.handleMozillaCtaClick("mac-main-panel-btn"); + window.close(); + }); + Utils.addEnterHandler(document.querySelector(".dismiss-moz-vpn-tout"), async() => { + const { mozillaVpnHiddenToutsList } = await browser.storage.local.get("mozillaVpnHiddenToutsList"); + if (typeof(mozillaVpnHiddenToutsList) === "undefined") { + await browser.storage.local.set({ "mozillaVpnHiddenToutsList": [] }); + } + document.querySelector("#moz-vpn-tout").classList.add("disappear"); + mozillaVpnHiddenToutsList.push({ + name: mozillaVpnToutName + }); + await browser.storage.local.set({ mozillaVpnHiddenToutsList }); + }); Utils.addEnterHandler(document.querySelector("#manage-containers-link"), (e) => { if (!e.target.classList.contains("disable-edit-containers")) { Logic.showPanel(MANAGE_CONTAINERS_PICKER); @@ -663,6 +708,13 @@ Logic.registerPanel(P_CONTAINERS_LIST, { } }); + const { mozillaVpnHiddenToutsList } = await browser.storage.local.get("mozillaVpnHiddenToutsList"); + const mozillaVpnToutShouldBeHidden = mozillaVpnHiddenToutsList && mozillaVpnHiddenToutsList.find(tout => tout.name === mozillaVpnToutName); + + const mozVpnTout = document.getElementById("moz-vpn-tout"); + if (mozillaVpnToutShouldBeHidden) { + mozVpnTout.remove(); + } }, unregister() { @@ -671,37 +723,54 @@ Logic.registerPanel(P_CONTAINERS_LIST, { // This method is called when the panel is shown. async prepare() { const fragment = document.createDocumentFragment(); + const identities = Logic.identities(); - Logic.identities().forEach(identity => { + for (const identity of identities) { const tr = document.createElement("tr"); tr.classList.add("menu-item", "hover-highlight", "keyboard-nav", "keyboard-right-arrow-override"); tr.setAttribute("tabindex", "0"); + tr.setAttribute("data-cookie-store-id", identity.cookieStoreId); const td = document.createElement("td"); const openTabs = identity.numberOfOpenTabs || "" ; + // TODO get UX and content decision on how to message and block clicks to containers with Mozilla VPN proxy configs + // when Mozilla VPN app is disconnected. + td.innerHTML = Utils.escaped` - + + diff --git a/src/popup.html b/src/popup.html index f50a2ce..b563e10 100644 --- a/src/popup.html +++ b/src/popup.html @@ -13,13 +13,6 @@ -
- -

-

- -
-

@@ -27,13 +20,6 @@
-
- -

-

- -
-

@@ -41,13 +27,6 @@
-
- -

-

- -
-

@@ -82,6 +61,15 @@
+
+ +

+

+
+ +
+
+

@@ -110,7 +98,7 @@ @@ -240,7 +248,7 @@

Multi-Account Containers

- +
@@ -262,39 +270,87 @@