diff --git a/Chrome Extension/img/google-icon.png b/Chrome Extension/img/google-icon.png new file mode 100644 index 0000000..133eea3 Binary files /dev/null and b/Chrome Extension/img/google-icon.png differ diff --git a/Chrome Extension/img/logo_white.png b/Chrome Extension/img/logo_white.png new file mode 100644 index 0000000..363a0b5 Binary files /dev/null and b/Chrome Extension/img/logo_white.png differ diff --git a/Chrome Extension/manifest.json b/Chrome Extension/manifest.json index bfb22b6..c0e9835 100644 --- a/Chrome Extension/manifest.json +++ b/Chrome Extension/manifest.json @@ -1,39 +1,62 @@ { "name": "CircuitVerse", - "version": "0.0.1", - "manifest_version": 2, + "version": "0.0.2", + "manifest_version": 3, "description": "CircuitVerse Chrome Extension - Embed Live Circuit in Google Slides", "homepage_url": "https://circuitverse.org", - "icons": { - "16": "icons/icon16.png", - "19": "icons/icon19.png", - "32": "icons/icon32.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" - }, - "browser_action": { - "default_icon": "icons/icon32.png", - "default_title": "Embed CircuitVerse Live Circuit", - "default_popup": "views/browser_action.html" + "action": { + "default_icon": { + "16": "icons/icon16.png", + "19": "icons/icon19.png", + "32": "icons/icon32.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + }, + "default_title": "CircuitVerse", + "default_popup": "views/popup.html" }, "default_locale": "en", - "background": { - "scripts": [ - "src/bg/background.js" - ], - "persistent": true - }, "permissions": [ - "https://docs.google.com/*" + "storage", + "tabs" + ], + "host_permissions": [ + "https://docs.google.com/*", + "https://circuitverse.org/*", + "https://www.googleapis.com/*", + "https://googleapis.com/*", + "https://slides.googleapis.com/*" ], + "background": { + "service_worker": "src/bg/background.js" + }, "content_scripts": [ { "matches": [ - "https://docs.google.com/*" + "https://docs.google.com/presentation/*" ], "js": [ "src/inject/inject.js" + ], + "run_at": "document_idle" + } + ], + "web_accessible_resources": [ + { + "resources": [ + "views/embedTool.html", + "styles/embedTool.css", + "src/inject/embedTool.js", + "src/inject/gsi.client.js", + "img/google-icon.png", + "img/logo_white.png" + ], + "matches": [ + "https://docs.google.com/*" ] } - ] + ], + "externally_connectable": { + "matches": ["https://docs.google.com/*"] + } } diff --git a/Chrome Extension/src/bg/background.js b/Chrome Extension/src/bg/background.js index 65144c7..8cc9793 100644 --- a/Chrome Extension/src/bg/background.js +++ b/Chrome Extension/src/bg/background.js @@ -1,17 +1,301 @@ -// if you checked "fancy-settings" in extensionizr.com, uncomment this lines +// On install, open the CircuitVerse Docs in a new tab +chrome.runtime.onInstalled.addListener(function(object) { + chrome.tabs.create({url: 'https://docs.circuitverse.org/#/chapter2/2cvforeducators?id=embed-circuitverse-simulation-in-google-slides'}); +}); -// var settings = new Store("settings", { -// "sample_setting": "This is how you use Store.js to remember values" -// }); +// Handle messages from the injected Embed tool +chrome.runtime.onMessageExternal.addListener(async function(request, sender, sendResponse) { + //? Handle new successful authentication callback + if (request.message_type === "USER_AUTHENTICATION_SUCCESSFUL") { + var access_token = request.access_token; + var expires_in = request.expires_in - 30; // as the internal process takes some time deduct 30 seconds + var expires_in_timestamp = Date.now() + expires_in * 1000; + var email; + // Fetch user profile + var headers = new Headers(); + headers.append("Authorization", "Bearer " + access_token); -// example of using a message handler from the inject scripts + var requestOptions = { + method: 'GET', + headers: headers, + redirect: 'follow' + }; -// chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { -// chrome.pageAction.show(sender.tab.id); -// sendResponse(); -// }); + fetch("https://www.googleapis.com/oauth2/v1/userinfo?alt=json", requestOptions) + .then(response => response.json()) + .then(async(result) => { + email = result.email; + // Store the access token in the local session storage + // as we dont want to keep temporary tokens permerantly as they have max ttl of 1 hour + var payload_ = {} + payload_[email] = { + access_token: access_token, + expires_in: expires_in_timestamp, + }; + await chrome.storage.session.set(payload_) + sendResponse({ + "message_type": "USER_AUTHENTICATION_SUCCESSFUL", + "email": email + }) + }) + .catch(error => { + console.log('error', error); + sendResponse({ + "message_type": "USER_AUTHENTICATION_FAILED" + }) + }); + } + //? Used to check whether the email id is logged in and access_token is still valid + else if(request.message_type === "CHECK_LOGIN_STATUS"){ + var email = request.email; + var result = await chrome.storage.session.get(email); + // If no record in storage, user is not logged in + if(result[email] === undefined || result[email] === null){ + sendResponse({ + "message_type": "USER_NOT_LOGGED_IN", + "email": email + }) + }else{ + // If record is present, check if access_token is still valid and expires_in is not expired + var access_token = result[email].access_token; + var expires_in = result[email].expires_in; + if(expires_in <= Date.now() || access_token === "" || access_token === null || access_token === undefined){ + await chrome.storage.session.remove(email); + sendResponse({ + "message_type": "USER_NOT_LOGGED_IN", + "email": email + }) + }else{ + sendResponse({ + "message_type": "USER_LOGGED_IN", + "email": email + }) + } + } + } + //? Embed the circuit in slides + else if(request.message_type === "EMBED_CIRCUIT"){ + var email = request.email; + var link_of_page = request.link_of_page; // extract page id and presentation id + var circuitverse_link = request.circuitverse_link; -chrome.runtime.onInstalled.addListener(function(object) { - chrome.tabs.create({url: 'https://docs.circuitverse.org/#/embedding_circuits?id=embedding-in-google-slides'}); -}); + // Parse the presentation id and slide id from the link + var tmp_ = parsePresentationLink(link_of_page); + var link_parse_status = tmp_[0]; + var presentation_id = tmp_[1]; + var slide_id = tmp_[2]; + if(link_parse_status === false){ + sendResponse({ + "message_type": "INVALID_PRESENTATION_LINK" + }) + return; + }else{ + // Fetch the access token from the local storage + var result = await chrome.storage.session.get(email); + // If no record in storage, user is not logged in + if(result[email] === undefined || result[email] === null){ + sendResponse({ + "message_type": "USER_NOT_LOGGED_IN", + "email": email + }) + }else{ + // If record is present, check if access_token is still valid and expires_in is not expired + var access_token = result[email].access_token; + var expires_in = result[email].expires_in; + if(expires_in <= Date.now() || access_token === "" || access_token === null || access_token === undefined){ + chrome.storage.session.remove([email]); // we need not to wait for this to complete + sendResponse({ + "message_type": "USER_LOGIN_SESSION_EXPIRED", + "email": email + }) + } + // If access_token is valid, embed the circuit in the slide + // Step 1: prepare the preview image link and hyperlink + var circuitverse_project_id = getProjectId(circuitverse_link); + var preview_image_link = await getCircuitPreviewImagePath(circuitverse_project_id); + var circuit_hyperlink = getCircuitEmbedPath(circuitverse_project_id); + // Step 2: fetch revison id of the slide + var revison_id_request = await fetchPresentationRevisionId(presentation_id, slide_id, access_token); + if(revison_id_request[0] === false) { + sendResponse({ + "message_type": "CIRCUIT_EMBEDDING_FAILED" + }) + return; + } + var presentation_revision_id = revison_id_request[1]; + // Step 3: insert image + var insert_image_request = await insertImageInSlide(presentation_id, slide_id, presentation_revision_id, preview_image_link, access_token); + if(insert_image_request[0] === false) { + sendResponse({ + "message_type": "CIRCUIT_EMBEDDING_FAILED" + }) + return; + } + // Step 4: insert hyperlink + var insert_hyperlink_request = await insertHyperlinkInImage(presentation_id, slide_id, insert_image_request[2], insert_image_request[1],circuit_hyperlink, access_token); + if(insert_hyperlink_request[0] === false) { + sendResponse({ + "message_type": "CIRCUIT_EMBEDDING_FAILED" + }) + return; + } + // TODO refetch revison id and give one retry + // Send success message + sendResponse({ + "message_type": "CIRCUIT_EMBEDDING_SUCCESSFUL" + }) + } + } + } +}) + +// Parse project id from url +function getProjectId(url) { + var re1= /https:\/\/circuitverse\.org\/users\/\d*\/projects\/(.*)/; + var re2 = /"https:\/\/circuitverse\.org\/simulator\/embed\/(.*?)"/; + var re3 = /https:\/\/circuitverse\.org\/simulator\/edit\/(.*)/; + var re4 = /https:\/\/circuitverse\.org\/simulator\/embed\/(.*)/; + var re5 = /https:\/\/circuitverse\.org\/simulator\/(.*)/; + + if(re1.test(url)) return url.match(re1)[1]; + if(re2.test(url)) return url.match(re2)[1]; + if(re3.test(url)) return url.match(re3)[1]; + if(re4.test(url)) return url.match(re4)[1]; + if(re5.test(url)) return url.match(re5)[1]; + return ""; +} + +// Get embed path of circuit from ID +function getCircuitEmbedPath(id) { + return `https://circuitverse.org/simulator/embed/${id}`; +} + +// Get circuit image path from ID +async function getCircuitPreviewImagePath(id) { + var queryUrl = `https://circuitverse.org/api/v1/projects/${id}/image_preview`; + var response = await fetch(queryUrl); + var data = await response.json(); + return data.project_preview; +} + +// Parse presentation id and slide id from url of page +function parsePresentationLink(url) { + // Check whether `link_of_page` is a valid google slides link and consists the slide_id + var re = /https:\/\/docs\.google\.com\/presentation\/d\/(.*)\/edit#slide=id\.(.*)/; + if(!re.test(url)){ + returrn [false, null, null]; + } + // Extract the slide_id and presentation_id from the link + var presentation_id = url.match(re)[1]; + var slide_id = url.match(re)[2]; + return [true, presentation_id, slide_id]; +} + +// Fetch Slides Revison Id +async function fetchPresentationRevisionId(presentation_id, slide_id, access_token) { + var queryUrl = `https://slides.googleapis.com/v1/presentations/${presentation_id}/pages/${slide_id}`; + var response = await fetch(queryUrl, { + headers: { + Authorization: `Bearer ${access_token}`, + } + }); + if(response.status !== 200) return [false, null]; + var data = await response.json(); + return [true, data.revisionId]; +} + +// Insert image in slide +async function insertImageInSlide(presentation_id, slide_id, revision_id, img_link, access_token) { + // Generate object id for image + var objectId = generateObjectId(); + // Prepare headers + var request_headers = new Headers(); + request_headers.append("Authorization", `Bearer ${access_token}`); + // Prepare body + var body = { + "requests": [ + { + "createImage": { + "objectId": objectId, + "elementProperties": { + "pageObjectId": slide_id, + "size": { + "width": { + "magnitude": 320, + "unit": "pt" + }, + "height": { + "magnitude": 240, + "unit": "pt" + } + } + }, + "url": img_link + } + } + ], + "writeControl": { + "requiredRevisionId": revision_id + } + }; + var request_options = { + method: 'POST', + headers: request_headers, + body: JSON.stringify(body), + redirect: 'follow' + }; + // Send request + var request = await fetch(`https://slides.googleapis.com/v1/presentations/${presentation_id}:batchUpdate`, request_options); + if(request.status !== 200) return [false, null, null]; + var data = await request.json(); + // return [status, image object id, revison id] + return [true, objectId, data.writeControl.requiredRevisionId]; +} + +// Insert hyperlink to image +async function insertHyperlinkInImage(presentation_id, slide_id, revision_id, object_id, hyperlink, access_token) { + // Prepare headers + var request_headers = new Headers(); + request_headers.append("Authorization", `Bearer ${access_token}`); + // body + var body = { + "requests": [ + { + "updateImageProperties": { + "objectId": object_id, + "fields": "link", + "imageProperties": { + "link": { + "url": hyperlink + } + } + } + } + ], + "writeControl": { + "requiredRevisionId": revision_id + } + } + var request_options = { + method: 'POST', + headers: request_headers, + body: JSON.stringify(body), + redirect: 'follow' + } + // Send request + var request = await fetch(`https://slides.googleapis.com/v1/presentations/${presentation_id}:batchUpdate`, request_options); + if(request.status !== 200) return false; + else return true; +} + +// Generate object id +function generateObjectId() { + var result = ''; + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-:123456789'; + var charactersLength = Math.floor(Math.random()*(50-10+1)+10); // random number between 10 and 50 + for ( var i = 0; i < charactersLength; i++ ) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} \ No newline at end of file diff --git a/Chrome Extension/src/inject/embedTool.js b/Chrome Extension/src/inject/embedTool.js new file mode 100644 index 0000000..63e4786 --- /dev/null +++ b/Chrome Extension/src/inject/embedTool.js @@ -0,0 +1,219 @@ +// Get current page url +function getCurrentPageUrl() { + return window.location.href || document.location.href; +} +// Get the extension id +function fetchExtensionId() { + return document.getElementById('circuitverse-extension-id').innerText; +} + +// Get logged in user e-mail id -> returnn empty string if not found +function getLoggedInEmail() { + let email = null; + try { + email = gbar_.CONFIG[0][4]["ya"][5] + }catch(err) { + try { + email = IJ_values[32]; + } catch (error) { + email = null; + } + } + return (email === null || email === undefined) ? "unknown" : email +} + +// Send message to background +function sendMessageToBackground(message, callback) { + chrome.runtime.sendMessage(fetchExtensionId(), message, callback); +} + +// Authorize user +function authorizeUser() { + // TODO : update oauth token + const client = google.accounts.oauth2.initTokenClient({ + client_id: '707727329587-7t91s6ri6ob0j01ok04t4iddkectvs0r.apps.googleusercontent.com', + scope: 'https://www.googleapis.com/auth/presentations', + hint: getLoggedInEmail(), + callback: function(response){ + var access_token = response.access_token; + console.log(access_token); + var expires_in = response.expires_in; + sendMessageToBackground({ + message_type: "USER_AUTHENTICATION_SUCCESSFUL", + access_token: access_token, + expires_in: expires_in + }, function(response) { + var type = response.message_type; + if(type === "USER_AUTHENTICATION_SUCCESSFUL"){ + var email = response.email; + updateLoggedinEmail(email); + showFormScreen(); + }else if(type === "USER_AUTHENTICATION_FAILED"){ + console.log("CircuitVerse : Failed User Authentication by Implicit OAuth 2.0") + } + }) + } + }); + client.requestAccessToken() +} + +// Check login status +function checkLoginStatus() { + sendMessageToBackground({ + message_type: "CHECK_LOGIN_STATUS", + email: getLoggedInEmail() + }, function(response) { + var type_ = response.message_type; + var email_ = response.email; + if(type_ === "USER_NOT_LOGGED_IN"){ + showAuthorizeScreen(); + }else if(type_ === "USER_LOGGED_IN"){ + updateLoggedinEmail(email_); + showFormScreen(); + } + }) +} + +// Insert Circuit Embed with link +function insertLink() { + const circuitVerseLink = document.getElementById('circuitverse__link_input').value; + if(circuitVerseLink === null || circuitVerseLink === undefined || circuitVerseLink === "") return; + showLoadingScreen(); + sendMessageToBackground({ + message_type: "EMBED_CIRCUIT", + link_of_page: getCurrentPageUrl(), + email: getLoggedInEmail(), + circuitverse_link: circuitVerseLink + }, function(response) { + showFormScreen(); + var type_ = response.message_type; + if(type_ === "INVALID_PRESENTATION_LINK"){ + showMessageOnScreen("Invalid presentation link", false, 5); + }else if(type_ === "USER_NOT_LOGGED_IN"){ + showMessageOnScreen("User not logged in", false, 5); + setTimeout(()=>showAuthorizeScreen(), 5000); + }else if(type_ === "USER_LOGIN_SESSION_EXPIRED"){ + showMessageOnScreen("Login session expired", false, 5); + setTimeout(()=>showAuthorizeScreen(), 5000); + }else if(type_ === "CIRCUIT_EMBEDDING_FAILED"){ + showMessageOnScreen("Circuit embedding failed", false, 5); + }else if(type_ === "CIRCUIT_EMBEDDING_SUCCESSFUL"){ + showMessageOnScreen("Successfully inserted circuit in slide", true, 5); + document.getElementById('circuitverse__link_input').value = ""; + } + showFormScreen(); + }); +} + +function getAbsoluteUrl(path) { + return "chrome-extension://"+fetchExtensionId()+"/"+path +} + + +//? UI Related functions and variables +// Main window +let circuitverse_embed_tool_window = document.getElementById("circuitverse__embed_tool_window"); +// Screens +let circuitverse__embed_tool_window_authorize_screen = document.getElementsByClassName("authorize_screen")[0]; +let circuitverse__embed_tool_window_loading_screen = document.getElementsByClassName("loading_container")[0]; +let circuitverse__embed_tool_window_form_screen = document.getElementsByClassName("form_screen")[0]; +// Components +let circuitverse__msg_box = document.getElementsByClassName("msg_box")[0]; +let circuitverse__link_input = document.getElementById("circuitverse__link_input"); +let circuitverse__logged_in_email = document.getElementById("circuitverse__logged_in_email"); +// Buttons +let circuitverse__embed_tool_open_btn = document.getElementsByClassName("circuitverse__embed_open_btn")[0]; +let circuitverse__embed_tool_close_btn = document.getElementsByClassName("circuitverse__embed_close_btn")[0]; +let circuitverse__authorize_btn = document.getElementById("circuitverse__authorize_btn"); +let circuitverse__embed_btn = document.getElementById("circuitverse__embed_btn"); + + +function onclickOpenButton(){ + // Make sure to disable open button + circuitverse__embed_tool_open_btn.classList.add("hide"); + // Show close button + circuitverse__embed_tool_close_btn.classList.remove("hide"); + // Make circuitverse_embed_tool_window visible + circuitverse_embed_tool_window.classList.remove("hide"); +} + +function onclickCloseButton(){ + // Make sure to disable open button + circuitverse__embed_tool_open_btn.classList.remove("hide"); + // Show close button + circuitverse__embed_tool_close_btn.classList.add("hide"); + // Make circuitverse_embed_tool_window visible + circuitverse_embed_tool_window.classList.add("hide"); +} + +function showLoadingScreen(){ + circuitverse__embed_tool_window_authorize_screen.classList.add("hide"); + circuitverse__embed_tool_window_form_screen.classList.add("hide"); + circuitverse__embed_tool_window_loading_screen.classList.remove("hide"); +} + +function showAuthorizeScreen() { + circuitverse__embed_tool_window_form_screen.classList.add("hide"); + circuitverse__embed_tool_window_loading_screen.classList.add("hide"); + circuitverse__embed_tool_window_authorize_screen.classList.remove("hide"); +} + +function showFormScreen(){ + circuitverse__embed_tool_window_authorize_screen.classList.add("hide"); + circuitverse__embed_tool_window_loading_screen.classList.add("hide"); + circuitverse__embed_tool_window_form_screen.classList.remove("hide"); +} + +function showMessageOnScreen(message, successful, duration_seconds) { + if(successful){ + circuitverse__msg_box.classList.remove("error"); + circuitverse__msg_box.classList.add("success"); + }else{ + circuitverse__msg_box.classList.remove("success"); + circuitverse__msg_box.classList.add("error"); + } + circuitverse__msg_box.innerText = message; + circuitverse__msg_box.classList.remove("invisible"); + setTimeout(()=>{ + circuitverse__msg_box.classList.add("invisible"); + }, duration_seconds*1000); +} + +function updateLoggedinEmail(email) { + circuitverse__logged_in_email.innerText = email; +} + + +// Initialization function + +function initEmbedTool(){ + var interval = setInterval(function(){ + if(document.readyState === 'complete') { + clearInterval(interval); + // Insert assets + let logo_white_url = getAbsoluteUrl("img/logo_white.png"); + document.getElementById("logo_white_1").src = logo_white_url; + document.getElementById("logo_white_2").src = logo_white_url; + document.getElementById("logo_white_3").src = logo_white_url; + document.getElementById("logo_white_4").src = logo_white_url; + + let google_icon_url = getAbsoluteUrl("img/google-icon.png"); + document.getElementById("google_icon").src = google_icon_url; + + // Initialize all event listeners + circuitverse__authorize_btn.addEventListener('click', authorizeUser); + circuitverse__embed_btn.addEventListener("click", insertLink); + circuitverse__embed_tool_open_btn.addEventListener("click", onclickOpenButton); + circuitverse__embed_tool_close_btn.addEventListener("click", onclickCloseButton); + + // Show loading screen by default + showLoadingScreen(); + + // Check for login status + checkLoginStatus(); + + } + }, 10); +} + +initEmbedTool(); \ No newline at end of file diff --git a/Chrome Extension/src/inject/gsi.client.js b/Chrome Extension/src/inject/gsi.client.js new file mode 100644 index 0000000..08b9565 --- /dev/null +++ b/Chrome Extension/src/inject/gsi.client.js @@ -0,0 +1,384 @@ +"use strict";this.default_gsi=this.default_gsi||{};(function(_){var window=this; + try{ + var aa,ba,ca,da,q,ea,fa,ha,ja;aa=function(a){var b=0;return function(){return b>>0)+"_",d=0,e=function(f){if(this instanceof e)throw new TypeError("b");return new b(c+(f||"")+"_"+d++,f)};return e}); + q("Symbol.iterator",function(a){if(a)return a;a=Symbol("c");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c=f}}); + q("Array.prototype.find",function(a){return a?a:function(b,c){a:{var d=this;d instanceof String&&(d=String(d));for(var e=d.length,f=0;f=e}}); + var pa=function(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&cc&&(c=Math.max(0,e+c));if(null==d||d>e)d=e;d=Number(d);0>d&&(d=Math.max(0,e+d));for(c=Number(c||0);cc&&(c=Math.max(c+e,0));c=b};_.Ka=function(a){return a?"[GSI_LOGGER-"+a+"]: ":"[GSI_LOGGER]: "};_.x=function(a,b){try{_.Ja("debug")&&window.console&&window.console.log&&window.console.log(_.Ka(b)+a)}catch(c){}}; + _.y=function(a,b){try{_.Ja("warn")&&window.console&&window.console.warn&&window.console.warn(_.Ka(b)+a)}catch(c){}};_.A=function(a,b){try{_.Ja("error")&&window.console&&window.console.error&&window.console.error(_.Ka(b)+a)}catch(c){}};_.La=function(a,b,c){for(var d in a)b.call(c,a[d],d,a)};Na=function(a,b){for(var c,d,e=1;eb?1:0}; + _.Da=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;cparseFloat(gb)){fb=String(ib);break a}}fb=gb}_.kb=fb; + var Ga=new Map;Ga.set("debug",0);Ga.set("info",1);Ga.set("warn",2);Ga.set("error",3);_.Ha="warn"; + for(var lb=[],mb=0;63>mb;mb++)lb[mb]=0;_.nb=[].concat(128,lb); + var Ma="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "); + _.C=function(a,b){this.h=b===_.ob?a:""};_.C.prototype.toString=function(){return this.h.toString()};_.C.prototype.ha=!0;_.C.prototype.ea=function(){return this.h.toString()};_.pb=function(a){return a instanceof _.C&&a.constructor===_.C?a.h:"type_error:SafeUrl"};_.qb=/^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))/i;_.ob={};_.rb=new _.C("about:invalid#zClosurez",_.ob); + var vb;_.sb={};_.tb=function(a,b){this.h=b===_.sb?a:"";this.ha=!0};_.tb.prototype.ea=function(){return this.h.toString()};_.tb.prototype.toString=function(){return this.h.toString()};_.ub=function(a){return a instanceof _.tb&&a.constructor===_.tb?a.h:"type_error:SafeHtml"};vb=new _.tb(_.v.trustedTypes&&_.v.trustedTypes.emptyHTML||"",_.sb); + _.wb=function(a){var b=!1,c;return function(){b||(c=a(),b=!0);return c}}(function(){var a=document.createElement("div"),b=document.createElement("div");b.appendChild(document.createElement("div"));a.appendChild(b);b=a.firstChild.firstChild;a.innerHTML=_.ub(vb);return!b.parentElement}); + _.xb=String.prototype.repeat?function(a,b){return a.repeat(b)}:function(a,b){return Array(b+1).join(a)}; + _.yb=function(){this.o=this.o;this.m=this.m};_.yb.prototype.o=!1;_.yb.prototype.jc=function(){return this.o};_.yb.prototype.V=function(){this.o||(this.o=!0,this.aa())};_.yb.prototype.aa=function(){if(this.m)for(;this.m.length;)this.m.shift()()}; + _.zb=function(a,b){this.type=a;this.h=this.target=b;this.defaultPrevented=this.i=!1};_.zb.prototype.stopPropagation=function(){this.i=!0};_.zb.prototype.preventDefault=function(){this.defaultPrevented=!0}; + var Ab=function(){if(!_.v.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});try{_.v.addEventListener("test",function(){},b),_.v.removeEventListener("test",function(){},b)}catch(c){}return a}(); + var Cb=function(a,b){_.zb.call(this,a?a.type:"");this.relatedTarget=this.h=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=this.l=this.j=0;this.key="";this.charCode=this.keyCode=0;this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.state=null;this.pointerId=0;this.pointerType="";this.W=null;if(a){var c=this.type=a.type,d=a.changedTouches&&a.changedTouches.length?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.h=b;if(b=a.relatedTarget){if(_.db){a:{try{$a(b.nodeName); + var e=!0;break a}catch(f){}e=!1}e||(b=null)}}else"mouseover"==c?b=a.fromElement:"mouseout"==c&&(b=a.toElement);this.relatedTarget=b;d?(this.clientX=void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX||0,this.screenY=d.screenY||0):(this.j=_.eb||void 0!==a.offsetX?a.offsetX:a.layerX,this.l=_.eb||void 0!==a.offsetY?a.offsetY:a.layerY,this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX= + a.screenX||0,this.screenY=a.screenY||0);this.button=a.button;this.keyCode=a.keyCode||0;this.key=a.key||"";this.charCode=a.charCode||("keypress"==c?a.keyCode:0);this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=a.metaKey;this.pointerId=a.pointerId||0;this.pointerType="string"===typeof a.pointerType?a.pointerType:Bb[a.pointerType]||"";this.state=a.state;this.W=a;a.defaultPrevented&&Cb.ra.preventDefault.call(this)}};_.Sa(Cb,_.zb);var Bb={2:"touch",3:"pen",4:"mouse"}; + Cb.prototype.stopPropagation=function(){Cb.ra.stopPropagation.call(this);this.W.stopPropagation?this.W.stopPropagation():this.W.cancelBubble=!0};Cb.prototype.preventDefault=function(){Cb.ra.preventDefault.call(this);var a=this.W;a.preventDefault?a.preventDefault():a.returnValue=!1};Cb.prototype.Zc=function(){return this.W}; + var Db;Db="closure_listenable_"+(1E6*Math.random()|0);_.Eb=function(a){return!(!a||!a[Db])}; + var Fb=0; + var Gb=function(a,b,c,d,e){this.listener=a;this.proxy=null;this.src=b;this.type=c;this.capture=!!d;this.Ba=e;this.key=++Fb;this.Sa=this.ab=!1},Hb=function(a){a.Sa=!0;a.listener=null;a.proxy=null;a.src=null;a.Ba=null}; + var Ib=function(a){this.src=a;this.h={};this.i=0},Kb;Ib.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.h[f];a||(a=this.h[f]=[],this.i++);var g=Jb(a,b,d,e);-1>>0);_.Rb=function(a){if("function"===typeof a)return a;a[Zb]||(a[Zb]=function(b){return a.handleEvent(b)});return a[Zb]}; + _.$b=function(){_.yb.call(this);this.ba=new Ib(this);this.Ga=this;this.L=null};_.Sa(_.$b,_.yb);_.$b.prototype[Db]=!0;_.l=_.$b.prototype;_.l.addEventListener=function(a,b,c,d){_.D(this,a,b,c,d)};_.l.removeEventListener=function(a,b,c,d){Xb(this,a,b,c,d)}; + _.l.dispatchEvent=function(a){var b,c=this.L;if(c)for(b=[];c;c=c.L)b.push(c);c=this.Ga;var d=a.type||a;if("string"===typeof a)a=new _.zb(a,c);else if(a instanceof _.zb)a.target=a.target||c;else{var e=a;a=new _.zb(d,c);Na(a,e)}e=!0;if(b)for(var f=b.length-1;!a.i&&0<=f;f--){var g=a.h=b[f];e=ac(g,d,!0,a)&&e}a.i||(g=a.h=c,e=ac(g,d,!0,a)&&e,a.i||(e=ac(g,d,!1,a)&&e));if(b)for(f=0;!a.i&&fb)throw Error("v`"+b);a.v=b}else a.v=null};_.mc=function(a,b,c){b instanceof pc?(a.l=b,vc(a.l,a.m)):(c||(b=qc(b,wc)),a.l=new pc(b,a.m))};_.xc=function(a){return a instanceof _.ic?new _.ic(a):new _.ic(a)}; + oc=function(a,b){return a?b?decodeURI(a.replace(/%25/g,"%2525")):decodeURIComponent(a):""};qc=function(a,b,c){return"string"===typeof a?(a=encodeURI(a).replace(b,yc),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,"%$1")),a):null};yc=function(a){a=a.charCodeAt(0);return"%"+(a>>4&15).toString(16)+(a&15).toString(16)};rc=/[#\/\?@]/g;tc=/[#\?:]/g;sc=/[#\?]/g;wc=/[#\?@]/g;uc=/#/g;pc=function(a,b){this.i=this.h=null;this.j=a||null;this.l=!!b}; + zc=function(a){a.h||(a.h=new Map,a.i=0,a.j&&fc(a.j,function(b,c){a.add(decodeURIComponent(b.replace(/\+/g," ")),c)}))};_.Bc=function(a){var b=hc(a);if("undefined"==typeof b)throw Error("x");var c=new pc(null);a=gc(a);for(var d=0;dh?"":0==h?";expires="+(new Date(1970,1,1)).toUTCString():";expires="+(new Date(Date.now()+1E3*h)).toUTCString())+(d?";secure":"")+(null!=e?";samesite="+e:"")}; + _.Oc.prototype.get=function(a,b){for(var c=a+"=",d=(this.h.cookie||"").split(";"),e=0,f;e=a.h||d)return td(a)[b]=c,a;a.J[b+a.ya]=c;(c=a.Z)&&b in c&&delete c[b];return a};wd=function(a){var b=_.H(a);if(b&2)return a;a=_.Xa(a,vd);fd(b,a);Object.freeze(a);return a}; + zd=function(a,b,c){c=void 0===c?fd:c;if(null!=a){if(Wc&&a instanceof Uint8Array)return a.length?new _.nd(new Uint8Array(a),_.xd):_.yd();if(Array.isArray(a)){var d=_.H(a);if(d&2)return a;if(b&&!(d&32)&&(d&16||0===d))return _.ad(a,d|2),a;a=_.pd(a,zd,c,!0);b=_.H(a);b&4&&b&2&&Object.freeze(a);return a}return a.fb===_.kd?vd(a):a}};vd=function(a){if(_.cd(a.J))return a;a=Ad(a,!0);_.Zc(a.J,2);return a}; + Ad=function(a,b){var c=a.J,d=_.dd([]),e=a.constructor.h;e&&d.push(e);e=a.Z;if(e){d.length=c.length;d.fill(void 0,d.length,c.length);var f={};d[d.length-1]=f}0!==(_.H(c)&128)&&hd(d);b=b||a.ia()?fd:_.ed;d=jd(a.constructor,d);a.Da&&(d.Da=a.Da.slice());for(var g=!!(_.H(c)&16),h=e?c.length-1:c.length,k=0;k/g;le=/"/g;me=/'/g;ne=/\x00/g;oe=/[\x00&<>"']/;pe=function(){this.blockSize=-1}; + se=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909, + 275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];te=function(a,b){this.blockSize=-1;this.blockSize=64;this.j=_.v.Uint8Array?new Uint8Array(this.blockSize):Array(this.blockSize);this.l=this.i=0;this.h=[];this.o=a;this.m=b;this.s=_.v.Int32Array?new Int32Array(64):Array(64);void 0===qe&&(_.v.Int32Array?qe=new Int32Array(se):qe=se);this.reset()};_.Sa(te,pe); + te.prototype.reset=function(){this.l=this.i=0;this.h=_.v.Int32Array?new Int32Array(this.m):_.Fa(this.m)}; + var ue=function(a){for(var b=a.j,c=a.s,d=0,e=0;eb;b++){e=c[b-15]|0;d=c[b-2]|0;var f=(c[b-16]|0)+((e>>>7|e<<25)^(e>>>18|e<<14)^e>>>3)|0,g=(c[b-7]|0)+((d>>>17|d<<15)^(d>>>19|d<<13)^d>>>10)|0;c[b]=f+g|0}d=a.h[0]|0;e=a.h[1]|0;var h=a.h[2]|0,k=a.h[3]|0,m=a.h[4]|0,n=a.h[5]|0,p=a.h[6]|0;f=a.h[7]|0;for(b=0;64>b;b++){var t=((d>>>2|d<<30)^(d>>>13|d<<19)^(d>>>22|d<<10))+(d&e^d&h^e&h)|0;g=m&n^~m&p;f=f+((m>>>6|m<<26)^(m>>>11|m<<21)^(m>>> + 25|m<<7))|0;g=g+(qe[b]|0)|0;g=f+(g+(c[b]|0)|0)|0;f=p;p=n;n=m;m=k+g|0;k=h;h=e;e=d;d=g+t|0}a.h[0]=a.h[0]+d|0;a.h[1]=a.h[1]+e|0;a.h[2]=a.h[2]+h|0;a.h[3]=a.h[3]+k|0;a.h[4]=a.h[4]+m|0;a.h[5]=a.h[5]+n|0;a.h[6]=a.h[6]+p|0;a.h[7]=a.h[7]+f|0}; + te.prototype.update=function(a,b){void 0===b&&(b=a.length);var c=0,d=this.i;if("string"===typeof a)for(;c=e&&e==(e|0)))throw Error("m");this.j[d++]=e;d==this.blockSize&&(ue(this),d=0)}else throw Error("n");this.i=d;this.l+=b}; + te.prototype.digest=function(){var a=[],b=8*this.l;56>this.i?this.update(_.nb,56-this.i):this.update(_.nb,this.blockSize-(this.i-56));for(var c=63;56<=c;c--)this.j[c]=b&255,b/=256;ue(this);for(c=b=0;c>d&255;return a};var ve=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],Tc=function(){te.call(this,8,ve)};_.Sa(Tc,te);xe={};_.ye=function(a,b){this.h=b===xe?a:""}; + _.ye.prototype.toString=function(){return this.h+""};_.ye.prototype.ha=!0;_.ye.prototype.ea=function(){return this.h.toString()};_.ze=function(a){return a instanceof _.ye&&a.constructor===_.ye?a.h:"type_error:TrustedResourceUrl"}; + Jd=function(a){if(void 0===we){var b=null;var c=_.v.trustedTypes;if(c&&c.createPolicy){try{b=c.createPolicy("goog#html",{createHTML:he,createScript:he,createScriptURL:he})}catch(d){_.v.console&&_.v.console.error(d.message)}we=b}else we=b}a=(b=we)?b.createHTML(a):a;return new _.tb(a,_.sb)}; + Kd=function(a){a instanceof _.tb||(a="object"==typeof a&&a.ha?a.ea():String(a),oe.test(a)&&(-1!=a.indexOf("&")&&(a=a.replace(ie,"&")),-1!=a.indexOf("<")&&(a=a.replace(je,"<")),-1!=a.indexOf(">")&&(a=a.replace(ke,">")),-1!=a.indexOf('"')&&(a=a.replace(le,""")),-1!=a.indexOf("'")&&(a=a.replace(me,"'")),-1!=a.indexOf("\x00")&&(a=a.replace(ne,"�"))),a=Jd(a));return a}; + Ae=function(a,b,c){var d;a=c||a;if(a.querySelectorAll&&a.querySelector&&b)return a.querySelectorAll(b?"."+b:"");if(b&&a.getElementsByClassName){var e=a.getElementsByClassName(b);return e}e=a.getElementsByTagName("*");if(b){var f={};for(c=d=0;a=e[c];c++){var g=a.className,h;if(h="function"==typeof g.split)h=0<=(0,_.Da)(g.split(/\s+/),b);h&&(f[d++]=a)}f.length=d;return f}return e}; + _.Be=function(a,b){var c=b||document;return c.querySelectorAll&&c.querySelector?c.querySelectorAll("."+a):Ae(document,a,b)};_.Ce=function(a,b){var c=b||document;if(c.getElementsByClassName)a=c.getElementsByClassName(a)[0];else{c=document;var d=b||c;a=d.querySelectorAll&&d.querySelector&&a?d.querySelector(a?"."+a:""):Ae(c,a,b)[0]||null}return a||null};_.De=function(a){for(var b;b=a.firstChild;)a.removeChild(b)};_.Ee=function(a){return a&&a.parentNode?a.parentNode.removeChild(a):null}; + _.Fe=function(a,b){if(a)if(_.Eb(a))a.ba&&_.Mb(a.ba,b);else if(a=_.Tb(a)){var c=0;b=b&&b.toString();for(var d in a.h)if(!b||d==b)for(var e=a.h[d].concat(),f=0;f>2];g=b[(g&3)<<4|h>>4];h=b[(h&15)<<2|k>>6];k=b[k&63];c[f++]=m+g+h+k}m=0;k=d;switch(a.length-e){case 2:m=a[e+1],k=b[(m&15)<<2]||d;case 1:a=a[e],c[f]=b[a>>2]+b[(a&3)<<4|m>>4]+k+d}return c.join("")}; + _.Me=function(){if(!_.Le){_.Le={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),b=["+/=","+/","-_=","-_.","-_"],c=0;5>c;c++){var d=a.concat(b[c].split(""));Ke[c]=d;for(var e=0;e=a.h?a.Z?a.Z[b]:void 0:c&&a.Z&&(c=a.Z[b],null!=c)?c:a.J[b+a.ya]};_.I=function(a,b,c,d){_.Re(a);return _.ud(a,b,c,d)};_.Te=function(a,b,c){return void 0!==Se(a,b,c,!1)};_.L=function(a,b){a=_.F(a,b);return null==a?a:!!a};Se=function(a,b,c,d){var e=_.F(a,c,d);b=_.ld(e,b);b!==e&&null!=b&&(_.ud(a,c,b,d),_.Zc(b.J,_.H(a.J)&18));return b}; + _.M=function(a,b,c,d){d=void 0===d?!1:d;b=Se(a,b,c,d);if(null==b)return b;if(!_.cd(a.J)){var e=_.Ue(b);e!==b&&(b=e,_.ud(a,c,b,d))}return b};_.Bd=function(a,b,c,d){_.Re(a);if(null!=c){var e=_.bd([]);for(var f=!1,g=0;g":">","`":"`","\u0085":"…","\u00a0":" ","\u2028":"
","\u2029":"
"};tf=function(a){return Ef[a]}; + Ff={"\x00":"%00","\u0001":"%01","\u0002":"%02","\u0003":"%03","\u0004":"%04","\u0005":"%05","\u0006":"%06","\u0007":"%07","\b":"%08","\t":"%09","\n":"%0A","\v":"%0B","\f":"%0C","\r":"%0D","\u000e":"%0E","\u000f":"%0F","\u0010":"%10","\u0011":"%11","\u0012":"%12","\u0013":"%13","\u0014":"%14","\u0015":"%15","\u0016":"%16","\u0017":"%17","\u0018":"%18","\u0019":"%19","\u001a":"%1A","\u001b":"%1B","\u001c":"%1C","\u001d":"%1D","\u001e":"%1E","\u001f":"%1F"," ":"%20",'"':"%22","'":"%27","(":"%28",")":"%29", + "<":"%3C",">":"%3E","\\":"%5C","{":"%7B","}":"%7D","\u007f":"%7F","\u0085":"%C2%85","\u00a0":"%C2%A0","\u2028":"%E2%80%A8","\u2029":"%E2%80%A9","\uff01":"%EF%BC%81","\uff03":"%EF%BC%83","\uff04":"%EF%BC%84","\uff06":"%EF%BC%86","\uff07":"%EF%BC%87","\uff08":"%EF%BC%88","\uff09":"%EF%BC%89","\uff0a":"%EF%BC%8A","\uff0b":"%EF%BC%8B","\uff0c":"%EF%BC%8C","\uff0f":"%EF%BC%8F","\uff1a":"%EF%BC%9A","\uff1b":"%EF%BC%9B","\uff1d":"%EF%BC%9D","\uff1f":"%EF%BC%9F","\uff20":"%EF%BC%A0","\uff3b":"%EF%BC%BB", + "\uff3d":"%EF%BC%BD"};_.Cf=function(a){return Ff[a]};sf=/[\x00\x22\x26\x27\x3c\x3e]/g;Gf=/[\x00\x22\x27\x3c\x3e]/g;_.Bf=/[\x00- \x22\x27-\x29\x3c\x3e\\\x7b\x7d\x7f\x85\xa0\u2028\u2029\uff01\uff03\uff04\uff06-\uff0c\uff0f\uff1a\uff1b\uff1d\uff1f\uff20\uff3b\uff3d]/g;Af=/^[^&:\/?#]*(?:[\/?#]|$)|^https?:|^ftp:|^data:image\/[a-z0-9+]+;base64,[a-z0-9+\/]+=*$|^blob:/i;_.yf=function(a){return String(a).replace(Gf,tf)};_.zf=function(a){return String(a).replace(_.Bf,_.Cf)};wf=/<(?:!|\/?([a-zA-Z][a-zA-Z0-9:\-]*))(?:[^>'"]|"[^"]*"|'[^']*')*>/g; + xf=/':'')}; + + _.gf("cancelable_auto_select"); + + _.gf("enable_clearcut_logs"); + + _.gf("enable_intermediate_iframe"); + + _.gf("enable_revoke_without_credentials"); + + }catch(e){_._DumpException(e)} + try{ + var ki,ni,oi;_.li=function(a,b,c){c=void 0===c?!0:c;if(b&&2===_.F(b,7)){var d={};b&&(d={kc:_.F(b,6),shape:_.F(b,3),size:_.F(b,1),text:_.F(b,5),theme:_.F(b,2),width:_.F(b,4),Oa:void 0===c?!0:c});_.Ld(a,ii,d)}else b&&2===_.F(b,10)&&!_.hf("disable_personalized_button")?(c=void 0===c?!0:c,b&&_.Te(b,_.bf,8)?(d={},b&&(d={shape:_.F(b,3),text:_.F(b,5),theme:_.F(b,2),width:_.F(b,4),md:_.Md(_.M(b,_.bf,8)),nd:_.F(b,9),Oa:c}),_.Ld(a,ji,d)):ki(a,b,c)):ki(a,b,c)}; + ki=function(a,b,c){var d={};b&&(d={kc:_.F(b,6),shape:_.F(b,3),size:_.F(b,1),text:_.F(b,5),theme:_.F(b,2),width:_.F(b,4),Oa:void 0===c?!0:c});_.Ld(a,mi,d)};ni={};oi=function(a,b){this.h=b===ni?a:"";this.ha=!0};oi.prototype.ea=function(){return this.h};oi.prototype.toString=function(){return this.h.toString()};var pi=function(a){return a instanceof oi&&a.constructor===oi?a.h:"type_error:SafeStyle"},qi={},ri=function(a,b){this.h=b===qi?a:"";this.ha=!0};ri.prototype.toString=function(){return this.h.toString()}; + ri.prototype.ea=function(){return this.h}; + var si=function(a){return a instanceof ri&&a.constructor===ri?a.h:"type_error:SafeStyleSheet"},ti={},ui=function(a,b){return a&&b&&a.bd&&b.bd?a.za!==b.za?!1:a.toString()===b.toString():a instanceof _.Hd&&b instanceof _.Hd?a.za!=b.za?!1:a.toString()==b.toString():a==b},vi=function(a){return a.replace(/<\//g,"<\\/").replace(/\]\]>/g,"]]\\>")},wi=/^(?!-*(?:expression|(?:moz-)?binding))(?:(?:[.#]?-?(?:[_a-z0-9-]+)(?:-[_a-z0-9-]+)*-?|(?:rgb|rgba|hsl|hsla|calc|max|min|cubic-bezier)\([-\u0020\t,+.!#%_0-9a-zA-Z]+\)|[-+]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:e-?[0-9]+)?(?:[a-z]{1,4}|%)?|!important)(?:\s*[,\u0020]\s*|$))*$/i,xi= + function(a){_.qf(a,ti)?a=vi(a.Ka):null==a?a="":a instanceof oi?a=vi(pi(a)):a instanceof oi?a=vi(pi(a)):a instanceof ri?a=vi(si(a)):a instanceof ri?a=vi(si(a)):(a=String(a),a=wi.test(a)?a:"zSoyz");return a},yi=function(){return(0,_.P)('')}; + _.zi=function(a){_.N.call(this,a)};_.K(_.zi,_.N);_.l=_.zi.prototype;_.l.zc=function(){return _.Ve(this,1)};_.l.Bc=function(){return _.Ve(this,2)};_.l.yc=function(){return _.Ve(this,3)};_.l.Dc=function(){return _.Ve(this,4)};_.l.Ac=function(){return _.Ve(this,5)};_.l.wc=function(){return _.Ve(this,6)};_.l.Cc=function(){return _.Ve(this,7)};_.l.xc=function(){return _.Ve(this,9)}; + var Ei=function(a,b,c,d,e,f,g,h){var k=void 0===g?!0:g;h=void 0===h?!1:h;g=e&&1!=e?_.Q(Ai(e)):_.Q(Ai(2));var m=_.P;k="
'+Di(ui(c,2)||ui(c,3))+(h?"":''+_.Q(Ai(e))+"")+''+g+"
")},Bi=function(a){var b="";switch(a){case 2:b+="MFS4be-v3pZbf-Ia7Qfc MFS4be-Ia7Qfc";break;case 3:b+="MFS4be-JaPV2b-Ia7Qfc MFS4be-Ia7Qfc";break;default:b+="i5vt6e-Ia7Qfc"}return b}, + Ci=function(a){var b="";switch(a){case 2:b+="JGcpL-RbRzK";break;case 4:b+="JGcpL-RbRzK";break;default:b+="uaxL4e-RbRzK"}return b},Ai=function(a){var b="";switch(a){case 1:b+="Sign in";break;case 3:b+="Sign up with Google";break;case 4:b+="Continue with Google";break;default:b+="Sign in with Google"}return b},Di=function(a){return(0,_.P)((void 0===a?0:a)?'
'+yi()+"
":'
'+yi()+"
")}; + var mi=function(a){a=a||{};var b=a.Oa;return(0,_.P)(Ei(a.kc,a.size,a.theme,a.shape,a.text,a.width,void 0===b?!0:b))},ii=function(a){a=a||{};var b=a.Oa;return(0,_.P)(Ei(void 0,a.size,a.theme,a.shape,a.text,void 0,void 0===b?!0:b,!0))},ji=function(a){var b=a.Oa,c=a.md,d=a.nd,e=a.shape,f=a.text,g=a.theme,h=a.width;a=_.P;var k=void 0===b?!0:b;b=c.ic?c.ic:c.displayName;e="
';c.pa?(e+='',h=_.R(b?b:c.id)+'):e+=_.Kf();h='
';k="";if(b)switch(f){case 4:k+="Continue as "+ + b;break;default:k+="Sign in as "+b}else k+=Ai(f);e+=h+_.Q(k)+'
'+_.Q(c.id)+"
"+(1'):"")+"
"+Di(ui(g,2)||ui(g,3))+"
";c=(0,_.P)(e);return a(c)}; + + }catch(e){_._DumpException(e)} + try{ + _.Oi=function(){var a=_.ra();if(_.ua())return _.za(a);a=_.sa(a);var b=_.ya(a);return _.ta()?b(["Version","Opera"]):_.w("Edge")?b(["Edge"]):_.w("Edg/")?b(["Edg"]):_.w("Silk")?b(["Silk"]):_.wa()?b(["Chrome","CriOS","HeadlessChrome"]):(a=a[2])&&a[1]||""};_.Ri=function(){return![_.wa()&&!_.Pi()&&!_.Qi(),_.wa()&&_.w("Android"),_.w("Edge")].some(function(a){return a})}; + _.Si=function(){return _.xa()||(_.w("iPad")||_.w("iPhone"))&&!_.xa()&&!_.wa()&&!_.w("Coast")&&!_.va()&&_.w("AppleWebKit")||_.Ba()&&0<=_.Va(_.Ca(),"14.4")||_.va()&&0<=_.Va(_.Oi(),"100")}; + _.Pi=function(){return!_.Qi()&&(_.w("iPod")||_.w("iPhone")||_.w("Android")||_.w("IEMobile"))};_.Qi=function(){return _.w("iPad")||_.w("Android")&&!_.w("Mobile")||_.w("Silk")}; + var Ti;Ti={}; + _.Ui=(Ti.enable_fedcm="28250620661-550h2e8djhee3ri2nma0u294i6ks921r.apps.googleusercontent.com 28250620661-jplop9r4d3uj679blu2nechmlm3h89gk.apps.googleusercontent.com 721418733929-55iv503445sqh9rospct8lthb3n46f3k.apps.googleusercontent.com 538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com 780994550302-0b687p4i9l66nunnvkvlje5bjfdm4tb3.apps.googleusercontent.com 817667923408-mm67cha4vukqtq6aj0faaibfofl1memo.apps.googleusercontent.com 916232382604-225e0sa3bdsq7k0ekpoh9sl1nne7okf8.apps.googleusercontent.com 488525074229-5rqhf4jaqmqpiosqevcmbclbo5nmsdh4.apps.googleusercontent.com 687088973437-38pnelafhrqnth469mvgm2ma64aev0il.apps.googleusercontent.com 402150438060-mvb4nhmp3o8rh83452qqlqq8bch09bnt.apps.googleusercontent.com 58828047352-u541mjj0fguhe0v26j4f2lm6q647anvh.apps.googleusercontent.com 965288796332-0h7v07k49r7ggo08nggbg2sdop6eop7d.apps.googleusercontent.com 834141296178-3itknsh2mneibsovevaoltkhrcadp6vv.apps.googleusercontent.com 624372386952-1kbovj4d6ejmlib859olmuq89qlonqbh.apps.googleusercontent.com 731494682028-3n7jsq8ladl31e4s02ehpbvvdh0ee613.apps.googleusercontent.com 918187601222-03rud06q74l0dc8ni8vmv10s7jrfo29e.apps.googleusercontent.com 269789103163-vupssne2p7gtgs30ms2ta2sd0ujlgf6s.apps.googleusercontent.com 34426703102-s53835smi0gfuba2u3f5d5trhdj15p5p.apps.googleusercontent.com 629251271814-hbnj6o76ofknqot961urbdqeoaujvvkh.apps.googleusercontent.com 289442006438-040a42cbidr6v5d178f3iqi9q95821r3.apps.googleusercontent.com 690222127349-t1i7h5njnm024hlum1df998qopl24l1o.apps.googleusercontent.com".split(" "),Ti); + + }catch(e){_._DumpException(e)} + try{ + _.wk=function(a){if(a instanceof _.C)a=_.pb(a);else{b:if(_.lf){try{var b=new URL(a)}catch(c){b="https:";break b}b=b.protocol}else c:{b=document.createElement("a");try{b.href=a}catch(c){b=void 0;break c}b=b.protocol;b=":"===b||""===b?"https:":b}a="javascript:"!==b?a:void 0}return a};_.xk=function(a){var b=void 0===b?_.mf:b;a:{b=void 0===b?_.mf:b;for(var c=0;cf.length&&(f=g));var h=jn(d.j,a);0h.length&&h.length!=g.length&& + (a=a.substr(h.length+1),h+="."+a.split(".")[0],h.length>f.length&&(f=h));var k=f.split("").reverse().join("");if(2>c.indexOf("."+k))return _.A("Invalid origin pattern. Patterns cannot be composed of a wildcard and a top level domain."),!1}catch(m){return!1}return!0}; + cn=function(){kn||(kn=_.D(window,"message",function(a){a=a.W;if(a.data){var b=a.data;"onetap_google"===b.sentinel&&"parent_frame_ready"===b.command&&(_.x("Message received: "+JSON.stringify(b)),window.parent&&window.parent===a.source?$m?b.nonce!==$m?_.y("Message ignored due to invalid nonce."):(ln(a.origin)?(_.Ym=a.origin,_.mn=b.parentMode||"amp_client",dn&&dn()):(_.y("Origin verification failed. Invalid origin - "+a.origin+"."),en&&en()),en=dn=$m=void 0,kn&&(_.Yb(kn),kn=void 0)):_.y("Message ignored. Origin verifier is not ready, or already done."): + _.y("Message ignored due to invalid source."))}}))};ln=function(a){return"string"===typeof bn?nn(bn,a):Array.isArray(bn)?bn.some(function(b){return nn(b,a)}):!1};nn=function(a,b){a=_.xc(a);b=_.xc(b);if(a.i!==b.i)return!1;a=a.h;b=b.h;return a.startsWith("*.")?b.endsWith(a.substr(1))||b===a.substr(2):a===b};_.on=function(a){_.Ym?_.Zm({command:"intermediate_iframe_resize",height:a}):_.y("Resize command was not sent due to missing verified parent origin.")}; + _.pn=function(){_.Ym?_.Zm({command:"intermediate_iframe_close"}):_.y("Close command was not sent due to missing verified parent origin.")};_.qn=function(a){_.Ym?_.Zm({command:"set_tap_outside_mode",cancel:a}):_.y("Set tap outside mode command was not sent due to missing verified parent origin.")}; + var rn=function(){this.S=void 0;this.h={}};rn.prototype.set=function(a,b){sn(this,a,b,!1)};rn.prototype.add=function(a,b){sn(this,a,b,!0)};var sn=function(a,b,c,d){for(var e=0;ec&&(c=d);return b.substr(0,c+1)},vn=function(a){var b=new rn;wn(0,"",a,b);return b},wn=function(a,b,c,d){for(var e="\x00";a=(void 0===b?100:b)||(b=new _.ic(Pn),_.mc(b,_.Bc({client_id:Qn,as:Rn,event:a.toString()})),_.Ie(b.toString(),void 0,"POST",void 0,void 0,void 0,"https://accounts.google.com/gsi/log"!==Pn))},Wn=function(a){var b=new (Function.prototype.bind.apply(Tn,[null,"onetap",a,"prompt"].concat(Un(Vn.apply(1,arguments)))));Sn(b)}, + Xn=function(){var a=new (Function.prototype.bind.apply(Tn,[null,"onetap",void 0,"closed"].concat(Un(Vn.apply(0,arguments)))));Sn(a)},Yn=function(){var a=new (Function.prototype.bind.apply(Tn,[null,"id",void 0,"init"].concat(Un(Vn.apply(0,arguments)))));Sn(a)},eo=function(){var a=_.E("g_id_onload");if(a){var b=_.Tm(a);a=_.Pm(b,Zn);void 0===a.auto_prompt&&(a.auto_prompt=!0);a.auto_prompt&&a.skip_prompt_cookie&&_.Qc.get(a.skip_prompt_cookie)&&(a.auto_prompt=!1);delete a.skip_prompt_cookie;var c={},d; + for(d in b)b.hasOwnProperty(d)&&0>$n.indexOf(d.toLowerCase())&&(c[d]=b[d]);a.state&&(c.state=a.state);if(d=a.login_uri){b=_.xc(d);b.h||(_.jc(b,location.protocol),b.h=location.hostname,_.lc(b,location.port),Yn("relativeLoginUri",d),_.y("Relative login_uri was provided. Use absolute url instead. Relative login_uri may be considered invalid in the future."));if("https"!==b.i&&"localhost"!==b.h)throw Yn("unsecuredLoginUri",d),new ao("Unsecured login_uri provided.");d=b.toString();a.login_uri=d}d&&!a.callback&& + (a.callback=bo(d,c));"redirect"!==a.ux_mode||d||_.A("Missing required login_uri parameter for the redirect flow.");d=a.native_login_uri;delete a.native_login_uri;d&&a.native_callback?_.A("Cannot set both data-native_login_uri and data-native_callback."):d&&(a.native_callback=co(d,c,a.native_id_param||"email",a.native_password_param||"password"));return a}},bo=function(a,b){return function(c){c&&c.credential?(b.credential=c.credential,b.g_csrf_token=En(),_.nl(a,b)):Z("No credential found in the response.")}}, + co=function(a,b,c,d){return function(e){e&&"password"===e.type?(b[c]=e.id,b[d]=e.password,_.nl(a,b)):Z("No password credential returned.")}},go=function(a){a=_.Tm(a);return _.Pm(a,fo)},ko=function(a){a=new ho(a);io.__G_ID_CLIENT__=a;Hn(a.Nc);jo(a);return a},lo=function(a,b,c){var d=io.__G_ID_CLIENT__;d||(ko(),d=io.__G_ID_CLIENT__);d.T(a,b,c)},no=function(a,b,c){if(a&&b){var d=io.__G_ID_CLIENT__;d?mo(d,a,b,c):_.y("Failed to render button before calling initialize().")}else _.y("Failed to render button because there is no parent or options set.")}, + po=function(){var a=io.__G_ID_CLIENT__;a||(ko(),a=io.__G_ID_CLIENT__);oo(a.s)},qo=function(){var a=void 0===a?document.readyState:a;for(var b=_.Be("g_id_signout"),c=0;c=c?c:0};d=b[a.h+"p"];void 0!==d&&(c.disable_auto_prompt=d);a=b[a.h+"t"];void 0!==a&&(c.disable_auto_select_to=a);return c},Uo=function(a,b){var c=a.h+"p",d=a.h+"t",e=a.h+"l",f=So(a);void 0=== + b.disable_auto_prompt?delete f[c]:f[c]=b.disable_auto_prompt;void 0===b.disable_auto_select_to?delete f[d]:f[d]=b.disable_auto_select_to;f[e]=b.prompt_suppress_level;b=JSON.stringify(f);c=_.w("Android")&&_.wa()&&0<=_.Va(_.Oi(),"67");_.Qc.set(a.i,b,{lc:15552E3,path:"/",domain:a.j||void 0,Lb:c?!0:void 0,Kb:c?"none":void 0})},Vo=function(a){a=To(a).disable_auto_prompt;return void 0!==a&&a>(new Date).getTime()},oo=function(a){var b=To(a);b.disable_auto_select_to=Date.now()+864E5;Uo(a,b)},Wo=function(a){var b= + To(a);delete b.disable_auto_select_to;Uo(a,b)}; + var Xo=RegExp("^((?!\\s)[a-zA-Z0-9\u0080-\u3001\u3003-\uff0d\uff0f-\uff60\uff62-\uffffFF-]+[\\.\\uFF0E\\u3002\\uFF61])+(?!\\s)[a-zA-Z0-9\u0080-\u3001\u3003-\uff0d\uff0f-\uff60\uff62-\uffffFF-]{2,63}$"); + var Yo=function(){};Yo.prototype.next=function(){return Zo};var Zo={done:!0,value:void 0};Yo.prototype.Ia=function(){return this}; + var cp=function(a){if(a instanceof $o||a instanceof ap||a instanceof bp)return a;if("function"==typeof a.next)return new $o(function(){return a});if("function"==typeof a[Symbol.iterator])return new $o(function(){return a[Symbol.iterator]()});if("function"==typeof a.Ia)return new $o(function(){return a.Ia()});throw Error("za");},$o=function(a){this.h=a};$o.prototype.Ia=function(){return new ap(this.h())};$o.prototype[Symbol.iterator]=function(){return new bp(this.h())};$o.prototype.i=function(){return new bp(this.h())}; + var ap=function(a){this.h=a};_.K(ap,Yo);ap.prototype.next=function(){return this.h.next()};ap.prototype[Symbol.iterator]=function(){return new bp(this.h)};ap.prototype.i=function(){return new bp(this.h)};var bp=function(a){$o.call(this,function(){return a});this.j=a};_.K(bp,$o);bp.prototype.next=function(){return this.j.next()}; + var dp=function(){}; + var ep=function(){};_.Sa(ep,dp);ep.prototype[Symbol.iterator]=function(){return cp(this.Ia(!0)).i()}; + var fp=function(a){this.h=a};_.Sa(fp,ep);_.l=fp.prototype;_.l.set=function(a,b){try{this.h.setItem(a,b)}catch(c){if(0==this.h.length)throw"Storage mechanism: Storage disabled";throw"Storage mechanism: Quota exceeded";}};_.l.get=function(a){a=this.h.getItem(a);if("string"!==typeof a&&null!==a)throw"Storage mechanism: Invalid value was encountered";return a};_.l.tb=function(a){this.h.removeItem(a)}; + _.l.Ia=function(a){var b=0,c=this.h,d=new Yo;d.next=function(){if(b>=c.length)return Zo;var e=c.key(b++);if(a)return{value:e,done:!1};e=c.getItem(e);if("string"!==typeof e)throw"Storage mechanism: Invalid value was encountered";return{value:e,done:!1}};return d};_.l.key=function(a){return this.h.key(a)}; + var gp=function(){var a=null;try{a=window.sessionStorage||null}catch(b){}this.h=a};_.Sa(gp,fp); + var hp=function(a,b){this.i=a;this.h=b+"::"};_.Sa(hp,ep);hp.prototype.set=function(a,b){this.i.set(this.h+a,b)};hp.prototype.get=function(a){return this.i.get(this.h+a)};hp.prototype.tb=function(a){this.i.tb(this.h+a)};hp.prototype.Ia=function(a){var b=this.i[Symbol.iterator](),c=this,d=new Yo;d.next=function(){var e=b.next();if(e.done)return e;for(e=e.value;e.slice(0,c.h.length)!=c.h;){e=b.next();if(e.done)return e;e=e.value}return{value:a?e.slice(c.h.length):c.i.get(e),done:!1}};return d}; + var ip=new _.Ll("g_credential_picker"),kp=function(a,b){b=void 0===b?"i_":b;var c=new gp;if(c.h)try{c.h.setItem("__sak","1");c.h.removeItem("__sak");var d=!0}catch(e){d=!1}else d=!1;this.G=d?new hp(c,"g_state_id_"):null;this.Rc=b;this.j=a=Object.assign({},a);this.Fa=!1;this.B=!0;this.Y=null;b=new Uint8Array(16);(window.crypto||_.Fc.msCrypto).getRandomValues(b);this.D=btoa(String.fromCharCode.apply(String,Un(b))).replace(/=+$/,"");this.H=new Map;this.wa=this.xa=!1;jp(this,a)};_.K(kp,_.cf); + var jp=function(a,b){var c=a.G?a.G.get("ll")||void 0:void 0;if(c)lp(a,c);else{if(c=void 0!==b.log_level)c=b.log_level,c=void 0===c||0<=(0,_.Da)(Co,c);c&&lp(a,b.log_level)}a.Lc=b.button_url||"https://accounts.google.com/gsi/button";a.Wa=b.picker_url||"https://accounts.google.com/gsi/select";a.Wc=b.prompt_url||"https://accounts.google.com/gsi/iframe/select";a.cc=b.status_url||"https://accounts.google.com/gsi/status";a.O=_.Rm(a.cc);a.Nc=b.container_css_url||"https://accounts.google.com/gsi/style";a.Yc= + b.revoke_url||"https://accounts.google.com/gsi/revoke";c=a.O;var d=b.client_id,e=a.D;Pn=c?c+"/gsi/log":"https://accounts.google.com/gsi/log";Qn=d;Rn=e;a.callback=b.callback;a.ta="redirect"===b.ux_mode?"redirect":"popup";c=b.ui_mode;void 0!==c&&Object.values(Eo).includes(c)||(c=_.Pi()&&!_.Qi()?"bottom_sheet":"card");a.uiMode=c;a.u=(b.prompt_parent_id?document.getElementById(b.prompt_parent_id):null)||document.body;a.Vc=9E4;a.la=!1!==b.cancel_on_tap_outside;a.xa=!1!==b.itp_support;a.dc=void 0===b.use_fedcm_for_prompt? + void 0:!!b.use_fedcm_for_prompt;c=b.state_cookie_domain;!c||null!=c&&Xo.test(c)||(c=void 0);a.s=new Ro(c,a.Rc,b.state_cookie_name);a.Va(b);c={};void 0!==b.client_id&&(c.client_id=b.client_id);void 0!==b.origin&&(c.origin=b.origin);void 0!==b.auto_select&&(c.auto_select=b.auto_select);c.ux_mode=a.ta;"redirect"===c.ux_mode&&b.login_uri&&(c.login_uri=b.login_uri);c.ui_mode=a.uiMode;void 0!==b.context&&Object.values(Do).includes(b.context)&&(c.context=b.context);void 0!==b.hint&&(c.hint=b.hint);void 0!== + b.hosted_domain&&(c.hosted_domain=b.hosted_domain);void 0!==b.existing&&(c.existing=b.existing);void 0!==b.special_accounts&&(c.special_accounts=b.special_accounts);void 0!==b.nonce&&(c.nonce=b.nonce);void 0!==b.channel_id&&(c.channel_id=b.channel_id);void 0!==b.state&&(c.state=b.state);"warn"!==_.Ha&&(c.log_level=_.Ha);void 0!==b.hl&&(c.hl=b.hl);void 0!==b.disable_auto_focus&&(c.disable_auto_focus=b.disable_auto_focus);c.as=a.D;_.hf("rp_cancelable_auto_select")&&(c.feature="cancelableAutoSelect"); + a.Ha(c);a.h=c};kp.prototype.Va=function(){};kp.prototype.Ha=function(){}; + var jo=function(a){a.Fa||(a.Fa=!0,_.D(window,"message",function(b){mp(a,b.W)},!1),a.Y=_.D(document,"click",function(){a.la&&np(a,!1)&&(op(a,"tap_outside"),Xn("tapOutside"))}))},pp=function(){var a=window;return"IdentityCredential"in window||"FederatedCredential"in window&&a.FederatedCredential.prototype.login},rp=function(a){a.v=new AbortController;var b={url:"https://accounts.google.com/gsi/",configURL:"https://accounts.google.com/gsi/fedcm.json",clientId:a.h.client_id};a.h.nonce&&(b.nonce=a.h.nonce); + b={providers:[b],mode:"mediated",preferAutoSignIn:!!a.h.auto_select};navigator.credentials.get({ed:"optional",signal:a.v.signal,federated:b,identity:b}).then(function(c){var d={signal:a.v.signal};a.h.nonce&&(d.nonce=a.h.nonce);a.wa=!0;var e=function(f){a.callback&&(f={credential:f&&(f.idToken||f.token),select_by:"fedcm"},qp({data:{announcement:_.Jf({})}}),a.callback.call(a,f),_.x("FedCM response :"+JSON.stringify(f)))};"login"in c?c.login(d).then(e,function(f){_.A("FedCM login() rejects with "+f)}): + e(c)},function(c){_.A("FedCM get() rejects with "+c)})}; + kp.prototype.T=function(a,b,c){var d=this;np(this,!0)&&(sp(this,"flow_restarted"),Xn("flowRestarted"));this.m=a;this.ma=c;a=Object.assign({},this.j,b);jp(this,a);a="bottom_sheet"===this.h.ui_mode?"bottomSheet":"card";this.h.client_id?_.hf("unsupported_browser")?(Z("One Tap is not supported in this User Agent."),this.l("browser_not_supported"),_.ef(this,"prompt_display_failed",{cause:"Unsupported user agent for one tap."}),Wn(a,"browserNotSupported")):Vo(this.s)?(Z("User has closed One Tap before. Still in the cool down period."), + this.l("suppressed_by_user"),_.ef(this,"prompt_display_failed",{cause:"Prompt disabled by the user."}),Wn(a,"cooldown",(To(this.s).prompt_suppress_level||0).toString())):pp()&&(this.dc||void 0===this.dc&&_.Ui.enable_fedcm.includes(this.h.client_id)&&_.hf("enable_fedcm_via_userid"))?rp(this):tp(this,function(e){e&&_.L(e,3)?(up(d),vp(d),wp(d,!0)):e&&_.Te(e,_.O,2)?(_.Sc(_.M(e,_.O,2)),e=_.M(e,_.O,2),e=_.F(e,1),d.l(2===e?"opt_out_or_no_session":7===e?"secure_http_required":5===e?"unregistered_origin": + 3===e||4===e?"invalid_client":9===e?"browser_not_supported":12===e?"web_view_not_supported":"unknown_reason"),_.ef(d,"prompt_display_failed",{cause:"Error while checking for the credential status."})):e&&!_.L(e,3)&&_.Si()&&d.xa?(d.h.is_itp=!0,up(d),vp(d),wp(d,!0),delete d.h.is_itp):e&&!_.L(e,3)?(_.x("No sessions found in the browser."),d.l("opt_out_or_no_session"),_.ef(d,"prompt_display_failed",{cause:"No signed in Google accounts available."})):(_.x("Invalid response from check credential status."), + d.l("unknown_reason"),_.ef(d,"prompt_display_failed",{cause:"A network error was encountered while checking for the credential status."}))}):(_.A("Missing required parameter: client_id."),this.l("missing_client_id"),_.ef(this,"prompt_display_failed",{cause:"Missing required parameter: client_id."}),Wn(a,"noClientId"))}; + var mo=function(a,b,c,d){_.De(b);_.Fe(b);var e="gsi_"+Date.now()%1E6+"_"+Math.floor(1E6*Math.random()),f=new _.ic(a.Lc),g=Object.assign({},c),h=_.Hc(document,"div");h.classList.add("S9gUrf-YoZ4jf");h.style.position="relative";b.appendChild(h);b=xp(a,h,c,e);a.H.set(e,{iframeId:e,Ba:d,fc:c.click_listener,Cb:b,data:{nonce:g.nonce||a.j.nonce,state:g.state||a.j.state}});delete g.nonce;delete g.state;c=_.Bc(g);c.add("client_id",a.j.client_id);c.add("iframe_id",e);c.add("as",a.D);g.locale&&(c.add("hl",g.locale), + _.Dc(c,"locale"));"warn"!==_.Ha&&c.add("log_level",_.Ha);a.j.hint&&c.add("hint",a.j.hint);a.j.hosted_domain&&c.add("hosted_domain",a.j.hosted_domain);_.mc(f,c);g=_.Ri();f=Kn(h,f.toString(),e,g);g&&Dn(f,function(k){k.preventDefault();k.stopPropagation();yp(a,e)})},xp=function(a,b,c,d){var e=_.Hc(document,"div");b.appendChild(e);b=new No(e,c,function(){yp(a,d)});Oo(b);return b},zp=function(a,b){var c=a.H.get(b);if(c&&c.Cb){var d=c.Cb;requestAnimationFrame(function(){requestAnimationFrame(function(){d.V(); + c.Cb=void 0;a:{if(performance&&performance.getEntriesByType){var e=performance.getEntriesByType("navigation");if(0=d.disable_auto_select_to&&(Wo(c),d=To(c));c=!(d.disable_auto_select_to&&Date.now() {const head = document.head; const css = ".qJTHM\x7b-webkit-user-select:none;color:#202124;direction:ltr;-webkit-touch-callout:none;font-family:\x22Roboto-Regular\x22,arial,sans-serif;-webkit-font-smoothing:antialiased;font-weight:400;margin:0;overflow:hidden;-webkit-text-size-adjust:100%\x7d.ynRLnc\x7bleft:-9999px;position:absolute;top:-9999px\x7d.L6cTce\x7bdisplay:none\x7d.bltWBb\x7bword-break:break-all\x7d.hSRGPd\x7bcolor:#1a73e8;cursor:pointer;font-weight:500;text-decoration:none\x7d.Bz112c-W3lGp\x7bheight:16px;width:16px\x7d.Bz112c-E3DyYd\x7bheight:20px;width:20px\x7d.Bz112c-r9oPif\x7bheight:24px;width:24px\x7d.Bz112c-uaxL4e\x7b-webkit-border-radius:10px;border-radius:10px\x7d.LgbsSe-Bz112c\x7bdisplay:block\x7d.S9gUrf-YoZ4jf,.S9gUrf-YoZ4jf *\x7bborder:none;margin:0;padding:0\x7d.fFW7wc-ibnC6b\x3e.aZ2wEe\x3ediv\x7bborder-color:#4285f4\x7d.P1ekSe-ZMv3u\x3ediv:nth-child(1)\x7bbackground-color:#1a73e8!important\x7d.P1ekSe-ZMv3u\x3ediv:nth-child(2),.P1ekSe-ZMv3u\x3ediv:nth-child(3)\x7bbackground-image:linear-gradient(to right,rgba(255,255,255,.7),rgba(255,255,255,.7)),linear-gradient(to right,#1a73e8,#1a73e8)!important\x7d.haAclf\x7bdisplay:inline-block\x7d.nsm7Bb-HzV7m-LgbsSe\x7b-webkit-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:background-color .218s,border-color .218s;transition:background-color .218s,border-color .218s;-webkit-user-select:none;-webkit-appearance:none;background-color:#fff;background-image:none;border:1px solid #dadce0;color:#3c4043;cursor:pointer;font-family:\x22Google Sans\x22,arial,sans-serif;font-size:14px;height:40px;letter-spacing:0.25px;outline:none;overflow:hidden;padding:0 12px;position:relative;text-align:center;vertical-align:middle;white-space:nowrap;width:auto\x7d@media screen and (-ms-high-contrast:active)\x7b.nsm7Bb-HzV7m-LgbsSe\x7bborder:2px solid windowText;color:windowText\x7d\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe\x7bfont-size:14px;height:32px;letter-spacing:0.25px;padding:0 10px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe\x7bfont-size:11px;height:20px;letter-spacing:0.3px;padding:0 8px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe\x7bpadding:0;width:40px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.pSzOP-SxQuSe\x7bwidth:32px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.purZT-SxQuSe\x7bwidth:20px\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK\x7b-webkit-border-radius:20px;border-radius:20px\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK.pSzOP-SxQuSe\x7b-webkit-border-radius:16px;border-radius:16px\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK.purZT-SxQuSe\x7b-webkit-border-radius:10px;border-radius:10px\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc\x7bborder:none;color:#fff\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-v3pZbf-Ia7Qfc\x7bbackground-color:#1a73e8\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-JaPV2b-Ia7Qfc\x7bbackground-color:#202124;color:#e8eaed\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bheight:18px;margin-right:8px;min-width:18px;width:18px\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bheight:14px;min-width:14px;width:14px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bheight:10px;min-width:10px;width:10px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bmargin-left:8px;margin-right:-4px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bmargin:0;padding:10px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.pSzOP-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bpadding:8px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bpadding:4px\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;display:-webkit-box;display:-webkit-flex;display:flex;justify-content:center;-webkit-align-items:center;align-items:center;background-color:#fff;height:36px;margin-left:-10px;margin-right:12px;min-width:36px;width:36px\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf .nsm7Bb-HzV7m-LgbsSe-Bz112c,.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bmargin:0;padding:0\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7bheight:28px;margin-left:-8px;margin-right:10px;min-width:28px;width:28px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7bheight:16px;margin-left:-6px;margin-right:8px;min-width:16px;width:16px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:3px;border-radius:3px;margin-left:2px;margin-right:0;padding:0\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:18px;border-radius:18px\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:14px;border-radius:14px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:8px;border-radius:8px\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-bN97Pc-sM5MNb\x7bdisplay:-webkit-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-flex-direction:row;flex-direction:row;justify-content:space-between;-webkit-flex-wrap:nowrap;flex-wrap:nowrap;height:100%;position:relative;width:100%\x7d.nsm7Bb-HzV7m-LgbsSe .oXtfBe-l4eHX\x7bjustify-content:center\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7b-webkit-flex-grow:1;flex-grow:1;font-family:\x22Google Sans\x22,arial,sans-serif;font-weight:500;overflow:hidden;text-overflow:ellipsis;vertical-align:top\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7bfont-weight:300\x7d.nsm7Bb-HzV7m-LgbsSe .oXtfBe-l4eHX .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7b-webkit-flex-grow:0;flex-grow:0\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7b-webkit-transition:background-color .218s;transition:background-color .218s;bottom:0;left:0;position:absolute;right:0;top:0\x7d.nsm7Bb-HzV7m-LgbsSe:hover,.nsm7Bb-HzV7m-LgbsSe:focus\x7b-webkit-box-shadow:none;box-shadow:none;border-color:#d2e3fc;outline:none\x7d.nsm7Bb-HzV7m-LgbsSe:hover .nsm7Bb-HzV7m-LgbsSe-MJoBVe,.nsm7Bb-HzV7m-LgbsSe:focus .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(66,133,244,.04)\x7d.nsm7Bb-HzV7m-LgbsSe:active .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(66,133,244,.1)\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc:hover .nsm7Bb-HzV7m-LgbsSe-MJoBVe,.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc:focus .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(255,255,255,.24)\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc:active .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(255,255,255,.32)\x7d.nsm7Bb-HzV7m-LgbsSe .n1UuX-DkfjY\x7b-webkit-border-radius:50%;border-radius:50%;display:-webkit-box;display:-webkit-flex;display:flex;height:20px;margin-left:-4px;margin-right:8px;min-width:20px;width:20px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7bfont-family:\x22Roboto\x22;font-size:12px;text-align:left\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .ssJRIf,.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff .fmcmS\x7boverflow:hidden;text-overflow:ellipsis\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff\x7bdisplay:-webkit-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;color:#5f6368;fill:#5f6368;font-size:11px;font-weight:400\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe.MFS4be-Ia7Qfc .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff\x7bcolor:#e8eaed;fill:#e8eaed\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff .Bz112c\x7bheight:18px;margin:-3px -3px -3px 2px;min-width:18px;width:18px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;margin-left:12px;margin-right:-10px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:18px;border-radius:18px\x7d.L5Fo6c-sM5MNb\x7bborder:0;display:block;left:0;position:relative;top:0\x7d.L5Fo6c-bF1uUb\x7b-webkit-border-radius:4px;border-radius:4px;bottom:0;cursor:pointer;left:0;position:absolute;right:0;top:0\x7d.L5Fo6c-bF1uUb:focus\x7bborder:none;outline:none\x7dsentinel\x7b\x7d"; const styleId = 'googleidentityservice_button_styles'; if (head && css && !document.getElementById(styleId)) {const style = document.createElement('style'); style.id = styleId; style.appendChild(document.createTextNode(css)); if (document.currentScript.nonce) style.setAttribute('nonce', document.currentScript.nonce); head.appendChild(style);}})(); \ No newline at end of file diff --git a/Chrome Extension/src/inject/inject.js b/Chrome Extension/src/inject/inject.js index 3d3f165..026e9ac 100644 --- a/Chrome Extension/src/inject/inject.js +++ b/Chrome Extension/src/inject/inject.js @@ -1,187 +1,215 @@ -chrome.extension.sendMessage({}, function(response) { - var readyStateCheckInterval = setInterval(function() { - if (document.readyState === 'complete') { - clearInterval(readyStateCheckInterval); - - // Specific location which allows the iframe embedded to be visible - function getEmbedLocation() { - return document.getElementsByClassName('punch-full-screen-element')[0]; - } - - // Extract slide number from the presentation - function getSlideNumber() { - var labelElement = - getSlideIframe().contentWindow.document.getElementsByClassName( - 'punch-viewer-svgpage-a11yelement')[0]; - if (!labelElement) return -1; - var label = labelElement.getAttribute('aria-label'); - return parseInt(label.match(/Slide (\d*)/)[1]); - } - - // Get the slide iframe - function getSlideIframe() { - return document.getElementsByClassName('punch-present-iframe')[0]; - } - - // Get the slide dimensions in svg values - function getSlideSvgViewDimensions() { - var svgContainer = - getSlideIframe().contentWindow.document.getElementsByClassName( - 'punch-viewer-svgpage-svgcontainer')[0]; - var svg = svgContainer.children[0]; - var viewBox = svg.getAttribute('viewBox').split(' '); - - return { - slideW: parseFloat(viewBox[2]), slideH: parseFloat(viewBox[3]) - } - } - - // Extract position and size of embedded image in SVG - // Needed for identifying exact location to embed the iframe - function extractPositionFromPath(path) { - var svgLinkPath = path.getAttribute('d'); - var pathRegexExp = - /M ([\S]*) ([\S]*) L ([\S]*) ([\S]*) ([\S]*) ([\S]*) ([\S]*) ([\S]*) Z/; - var matches = svgLinkPath.match(pathRegexExp); - var x1 = parseFloat(matches[1]); - var y1 = parseFloat(matches[2]); - var x2 = parseFloat(matches[3]); - var y3 = parseFloat(matches[6]); - var widthInSvg = x2 - x1; - var heightInSvg = y3 - y1; - return { - svgX: x1, svgY: y1, svgW: widthInSvg, svgH: heightInSvg - } - } - - // Get slide dimensions and offsets in pixels - function getSlideDimensions() { - var slideDiv = - getSlideIframe().contentWindow.document.getElementsByClassName( - 'punch-viewer-content')[0]; - var metadata = { - xOffsetPx: parseFloat(slideDiv.style.left), - yOffsetPx: parseFloat(slideDiv.style.top), - slideWidthPx: parseFloat(slideDiv.style.width), - slideHeightPx: parseFloat(slideDiv.style.height), - }; - return metadata; - } - - // Create circuitverse iframe from anchor tag - // Calculates exact position and places the iframe - function createEmbedIframe(anchorTag) { - var url = - anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); - var {svgX, svgY, svgW, svgH} = - extractPositionFromPath(anchorTag.children[0]); - var {slideW, slideH} = getSlideSvgViewDimensions(); - var {xOffsetPx, yOffsetPx, slideWidthPx, slideHeightPx} = - getSlideDimensions(); - - var svg2px = slideWidthPx / slideW; - - var absoluteXoffSetPx = xOffsetPx + svgX * svg2px; - var absoluteYoffSetPx = yOffsetPx + svgY * svg2px; - var widthPx = svgW * svg2px; - var heightPx = svgH * svg2px; - absoluteXoffSetPx = Math.round(absoluteXoffSetPx); - absoluteYoffSetPx = Math.round(absoluteYoffSetPx); - widthPx = Math.round(widthPx); - heightPx = Math.round(heightPx); - - var ifrm = document.createElement('iframe'); - ifrm.classList.add('circuitverse-iframe'); // assign a class - ifrm.setAttribute('style', `position:fixed;z-index:100; - width:${widthPx}px; - height:${heightPx}px; - top:${absoluteYoffSetPx}px; - left:${absoluteXoffSetPx}px`); - // assign url - ifrm.setAttribute('src', url); - - return ifrm; - } - - // Embeds iframe given link - function embed(anchorTag) { - var iframe = createEmbedIframe(anchorTag); - var url = - anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); - var location = getEmbedLocation(); - if (location == undefined) { - return; - } - location.appendChild(iframe); // to place at end of document - - iframe_embedded = true; - url_embedded = url; - } - - // Removes all embedded iframes - function removeEmbed() { - var iframes = document.getElementsByClassName('circuitverse-iframe'); - while (iframes[0]) { - iframes[0].parentNode.removeChild(iframes[0]); - } - } - - // Keeps track of current frame - - var slideNumber = -1; - - // Setting slideNumber = -1 will reset everything - function reset() { - slideNumber = -1; - } - - // Driver logic - function main() { - var iframeDocument = getSlideIframe(); - - if (!iframeDocument) { - slideNumber = -1; - removeEmbed(); - return; - } - - // Bring slide into focus - necessary for slide transitions to work! - if (slideNumber != -1) { - iframeDocument.contentWindow.document.body.focus(); - } - - if (slideNumber == getSlideNumber()) return; - - // New Slide - removeEmbed(); // remove previous iframes - slideNumber = getSlideNumber(); - - var anchorTags = - iframeDocument.contentWindow.document.getElementsByTagName('a'); - - var prevUrl = undefined; - for (var i = 0; i < anchorTags.length; i++) { - var url = anchorTags[i].getAttributeNS( - 'http://www.w3.org/1999/xlink', 'href'); - - // Google Slides has 2 anchor tags for every link for some reason; - // Hence ensuring no duplicate embeds! - if (url != prevUrl && - url.includes('circuitverse.org/simulator/embed')) { - prevUrl = url - embed(anchorTags[i]); - } - } - } - - // Call driver logic repeatedly - setInterval(main, 300); - - // Force reset after 3 seconds - needed for window resizing - // Also needed if first slide has circuit - window.addEventListener('resize', () => { - setTimeout(reset, 3000); - }); +//? Variables + +// Keeps track of current frame +let slideNumber = -1; + +//? Functions related to run the embedded CircuitVerse + +// Specific location which allows the iframe embedded to be visible +function getEmbedLocation() { + return document.getElementsByClassName('punch-full-screen-element')[0]; +} + +// Extract slide number from the presentation +function getSlideNumber() { + var labelElement = getSlideIframe().contentWindow.document.getElementsByClassName('punch-viewer-svgpage-a11yelement')[0]; + if (!labelElement) return -1; + var label = labelElement.getAttribute('aria-label'); + return parseInt(label.match(/Slide (\d*)/)[1]); +} + +// Get the slide iframe +function getSlideIframe() { + return document.getElementsByClassName('punch-present-iframe')[0]; +} + +// Get the slide dimensions in svg values +function getSlideSvgViewDimensions() { + var svgContainer = + getSlideIframe().contentWindow.document.getElementsByClassName('punch-viewer-svgpage-svgcontainer')[0]; + var svg = svgContainer.children[0]; + var viewBox = svg.getAttribute('viewBox').split(' '); + + return { + slideW: parseFloat(viewBox[2]), slideH: parseFloat(viewBox[3]) + } +} + +// Get slide dimensions and offsets in pixels +function getSlideDimensions() { + var slideDiv = getSlideIframe().contentWindow.document.getElementsByClassName('punch-viewer-content')[0]; + var metadata = { + xOffsetPx: parseFloat(slideDiv.style.left), + yOffsetPx: parseFloat(slideDiv.style.top), + slideWidthPx: parseFloat(slideDiv.style.width), + slideHeightPx: parseFloat(slideDiv.style.height), + }; + return metadata; +} + +// Extract position and size of embedded image in SVG +// Needed for identifying exact location to embed the iframe +function extractPositionFromPath(path) { + var svgLinkPath = path.getAttribute('d'); + var pathRegexExp = /M ([\S]*) ([\S]*) L ([\S]*) ([\S]*) ([\S]*) ([\S]*) ([\S]*) ([\S]*) Z/; + var matches = svgLinkPath.match(pathRegexExp); + var x1 = parseFloat(matches[1]); + var y1 = parseFloat(matches[2]); + var x2 = parseFloat(matches[3]); + var y3 = parseFloat(matches[6]); + var widthInSvg = x2 - x1; + var heightInSvg = y3 - y1; + return { + svgX: x1, svgY: y1, svgW: widthInSvg, svgH: heightInSvg + } +} + +// Create circuitverse iframe from anchor tag +// Calculates exact position and places the iframe +function createEmbedIframe(anchorTag) { + var url = + anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + var { svgX, svgY, svgW, svgH } = extractPositionFromPath(anchorTag.children[0]); + var { slideW, slideH } = getSlideSvgViewDimensions(); + var { xOffsetPx, yOffsetPx, slideWidthPx, slideHeightPx } = getSlideDimensions(); + + var svg2px = slideWidthPx / slideW; + var absoluteXoffSetPx = xOffsetPx + svgX * svg2px; + var absoluteYoffSetPx = yOffsetPx + svgY * svg2px; + var widthPx = svgW * svg2px; + var heightPx = svgH * svg2px; + absoluteXoffSetPx = Math.round(absoluteXoffSetPx); + absoluteYoffSetPx = Math.round(absoluteYoffSetPx); + widthPx = Math.round(widthPx); + heightPx = Math.round(heightPx); + + var ifrm = document.createElement('iframe'); + ifrm.classList.add('circuitverse-iframe'); // assign a class + ifrm.setAttribute('style', + `position:fixed;z-index:100; + width:${widthPx}px; + height:${heightPx}px; + top:${absoluteYoffSetPx}px; + left:${absoluteXoffSetPx}px` + ); + // assign url + ifrm.setAttribute('src', url); + return ifrm; +} + +// Embeds iframe given link +function embedCircuits(anchorTag) { + var iframe = createEmbedIframe(anchorTag); + var url = anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + var location = getEmbedLocation(); + if (location == undefined) { + return; + } + location.appendChild(iframe); // to place at end of document + iframe_embedded = true; + url_embedded = url; +} + +// Removes all embedded iframes +function removeEmbed() { + var iframes = document.getElementsByClassName('circuitverse-iframe'); + while(iframes[0]) { + iframes[0].parentNode.removeChild(iframes[0]); + } +} + +// Setting slideNumber = -1 will reset everything +function resetCircuitVerseEmbed() { + slideNumber = -1; +} + +// Driver logic +function initCircuitVerseIframeRunner() { + var iframeDocument = getSlideIframe(); + + if (!iframeDocument) { + slideNumber = -1; + removeEmbed(); + return; + } + + // Bring slide into focus - necessary for slide transitions to work! + if (slideNumber != -1) { + iframeDocument.contentWindow.document.body.focus(); + } + + if (slideNumber == getSlideNumber()) return; + + // New Slide + removeEmbed(); // remove previous iframes + slideNumber = getSlideNumber(); + + var anchorTags = iframeDocument.contentWindow.document.getElementsByTagName('a'); + + var prevUrl = undefined; + for (var i = 0; i < anchorTags.length; i++) { + var url = anchorTags[i].getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + + // Google Slides has 2 anchor tags for every link for some reason; + // Hence ensuring no duplicate embeds! + if (url != prevUrl && + url.includes('circuitverse.org/simulator/embed')) { + prevUrl = url + embedCircuits(anchorTags[i]); } - }, 10); -}); + } +} + + +//? Function realaed to `CircuitVerse Embed Tool` initialization +function injectCircuitVerseEmbedTool() { + // Inject embed tool css + fetch(chrome.runtime.getURL('/styles/embedTool.css')).then(r => r.text()).then(css => { + var style = document.createElement('style'); + style.innerHTML = css; + document.head.appendChild(style); + }).then(()=>{ + + // Inject embed tool html + fetch(chrome.runtime.getURL('/views/embedTool.html')).then(r => r.text()).then(html => { + var div = document.createElement('div'); + div.innerHTML = html; + document.body.appendChild(div); + }).then(()=>{ + + // Inject embed tool javscript + var embedToolScript = document.createElement('script'); + embedToolScript.src = chrome.runtime.getURL('/src/inject/embedTool.js'); + document.getElementsByTagName("body")[0].appendChild(embedToolScript); + + }) + + }) + + + // Inject an Span tag with extension id + var circuitverseExtensionIDTag = document.createElement('span'); + circuitverseExtensionIDTag.id = 'circuitverse-extension-id'; + circuitverseExtensionIDTag.style.display = 'none'; + circuitverseExtensionIDTag.innerText = chrome.runtime.id; + document.getElementsByTagName("body")[0].appendChild(circuitverseExtensionIDTag); +} + +document.onreadystatechange = function() { + if (document.readyState === 'complete') { + //? Initialization Code for `CircuitVerse Embed Runner` + // Call driver logic repeatedly + setInterval(initCircuitVerseIframeRunner, 300); + // Force reset after 3 seconds - needed for window resizing + // Also needed if first slide has circuit + window.addEventListener('resize', () => { + setTimeout(resetCircuitVerseEmbed, 3000); + }); + + //? Initialization Code for `CircuitVerse Embed Tool` + var gsi_script = document.createElement('script'); + gsi_script.src = chrome.runtime.getURL("/src/inject/gsi.client.js"); // Load gsi client library for OAuth + gsi_script.onload = injectCircuitVerseEmbedTool; // run injectCircuitVerseEmbedTool( after loading gsi client library + document.getElementsByTagName("body")[0].appendChild(gsi_script); + } +} \ No newline at end of file diff --git a/Chrome Extension/styles/embedTool.css b/Chrome Extension/styles/embedTool.css new file mode 100644 index 0000000..743a519 --- /dev/null +++ b/Chrome Extension/styles/embedTool.css @@ -0,0 +1,326 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap'); + +:root{ + --circuitverse-primary-color: #42B983; + --circuitverse-error-color: #F44336; +} + +/* CSS Spinner */ +.lds-ring { + display: inline-block; + position: relative; + width: 80px; + height: 80px; +} + +.lds-ring div { + box-sizing: border-box; + display: block; + position: absolute; + width: 64px; + height: 64px; + margin: 8px; + border: 8px solid var(--circuitverse-primary-color); + border-radius: 50%; + animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; + border-color: var(--circuitverse-primary-color) transparent transparent transparent; +} + +.lds-ring div:nth-child(1) { + animation-delay: -0.45s; +} + +.lds-ring div:nth-child(2) { + animation-delay: -0.3s; +} + +.lds-ring div:nth-child(3) { + animation-delay: -0.15s; +} + +@keyframes lds-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +/* Main */ +.circuitverse__embed_tool{ + width: fit-content; + height: fit-content; + position: absolute; + bottom: 50px; + right: 20px; + display: flex; + flex-direction: column; + align-items: flex-end; + row-gap: 20px; + z-index: 999; +} + +/* Show component class */ +.circuitverse__embed_tool .show{ + display: block!important; +} + +/* Hide component class */ +.circuitverse__embed_tool .hide{ + display: none!important; +} + +/* Visibility none */ +.circuitverse__embed_tool .invisible{ + visibility: hidden; +} + +/* Embed tool open button style */ +.circuitverse__embed_tool .circuitverse__embed_open_btn{ + height: 40px; + width: fit-content; + display: flex; + justify-content: center; + align-items: center; + padding: 8px; + padding-right: 18px; + border-radius: 50px; + + background-color: var(--circuitverse-primary-color); + color: white; + + font-family: 'Inter', sans-serif; + cursor: pointer; + +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn img{ + width: 38px; + height: 38px; +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn div{ + display: flex; + flex-direction: column; +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn .title{ + font-size: 16px; +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn .subtitle{ + font-size: 12px; +} + +/* Embed tool close button styl */ +.circuitverse__embed_tool .circuitverse__embed_close_btn{ + height: 40px; + width: 40px; + background-color: var(--circuitverse-primary-color); + color: white; + padding: 8px; + border-radius: 50%; + cursor: pointer; +} + +/* Container */ +.circuitverse__embed_tool .circuitverse__embed_tool_container{ + position: relative; + width: 330px; + min-height: 400px; + background-color: #fff; + border: 1px solid #D3D3D3; + border-radius: 16px; + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: space-between; + animation:fadeIn 0.3s linear; +} + +@keyframes fadeIn { + 0% { + opacity:0 + } + 100% { + opacity:1; + } +} + + +.circuitverse__embed_tool_container_header{ + height: 70px; + background-color: var(--circuitverse-primary-color); + border-radius: 16px 16px 0px 0px; + padding-left: 18px; + display: flex; + flex-direction: row; + justify-content: start; + align-items: center; +} + +.circuitverse__embed_tool_container_header img{ + width: 45px; + height: 45px; + margin-right: 12px; +} + +.circuitverse__embed_tool_container_header div{ + display: flex; + flex-direction: column; + font-family: 'Inter', sans-serif; + color: white; +} + +.circuitverse__embed_tool_container_header .title{ + font-size: 20px; + +} + +.circuitverse__embed_tool_container_header .subtitle{ + font-size: 14px; +} + +.circuitverse__embed_tool_container_body{ + padding: 18px; +} + +.circuitverse__embed_tool_container_footer{ + padding: 10px 15px; + background-color: #E8EEEB; + text-align: center; + font-family: 'Inter', sans-serif; +} + +/* loading_container */ +.loading_container .circuitverse__embed_tool_container_body{ + display: flex; + justify-content: center; + align-items: center; + flex: 1; +} + +.loading_container .circuitverse__embed_tool_container_body img{ + width: 100%; +} + +/* Authorize screen */ +.authorize_screen .circuitverse__embed_tool_container_body{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; +} + +.authorize_screen .circuitverse__embed_tool_container_body p{ + margin-right: 30px; + margin-left: 30px; + text-align: center; + font-size: 20px; + font-family: 'Inter', sans-serif; + margin-bottom: 40px; +} + +.authorize_screen .circuitverse__embed_tool_container_body button{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + background-color: #fff; + border: 0.2px solid #D3D3D3; + padding: 8px 15px; + border-radius: 6px; + cursor: pointer; +} + +.authorize_screen .circuitverse__embed_tool_container_body button img{ + width: 25px; + height: 25px; + margin-right: 10px; +} + +.authorize_screen .circuitverse__embed_tool_container_body button span{ + font-size: 16px; + font-family: 'Inter', sans-serif; +} + +.authorize_screen .circuitverse__embed_tool_container_footer{ + padding: 15px; + background-color: #fff; + text-align: justify; + font-size: 14px; +} + +/* Form screen */ +.form_screen .circuitverse__embed_tool_container_body label{ + font-family: 'Inter', sans-serif; + font-size: 18px; +} + +.form_screen .circuitverse__embed_tool_container_body input{ + height: 40px; + width: -webkit-fill-available; + border: 1.5px solid var(--circuitverse-primary-color); + border-radius: 6px; + padding: 8px; + font-size: 16px; + font-family: 'Inter', sans-serif; + margin-top: 10px; + margin-bottom: 14px; +} + +.form_screen .circuitverse__embed_tool_container_body button{ + height: 50px; + width: -webkit-fill-available; + border-radius: 6px; + font-size: 18px; + font-family: 'Inter', sans-serif; + border: none; + background-color: var(--circuitverse-primary-color); + color: #fff; + font-weight: 500; + cursor: pointer; +} + +.form_screen .circuitverse__embed_tool_container_body button:hover{ + /* translate the button up by 2px */ + transform: translateY(-2px); + /* add a slight shadow */ + box-shadow: 0 5px 10px rgba(0,0,0,0.2); + /* scale little bit */ + transform: scale(1.01); +} + +.form_screen .circuitverse__embed_tool_container_footer{ + font-family: 'Inter', sans-serif; + font-weight: 600; +} + +.form_screen .circuitverse__embed_tool_container_footer span{ + font-weight: normal; +} + +/* Message box */ +.circuitverse__embed_tool_container .msg_box{ + margin: 18px; + padding: 15px 20px; + border-radius: 6px; + font-family: 'Inter', sans-serif; + border: #D3D3D3 1px solid; + font-size: 14px; +} + +.circuitverse__embed_tool_container .msg_box.success{ + background-color: #f7f7f7; + color: var(--circuitverse-primary-color); + border-color: var(--circuitverse-primary-color); +} + +.circuitverse__embed_tool_container .msg_box.error{ + background-color: #f7f7f7; + color: var(--circuitverse-error-color); + border-color: var(--circuitverse-error-color); +} + diff --git a/Chrome Extension/views/embedTool.html b/Chrome Extension/views/embedTool.html new file mode 100644 index 0000000..be43b63 --- /dev/null +++ b/Chrome Extension/views/embedTool.html @@ -0,0 +1,83 @@ +
+
+ +
+ +
+ +
+ CircuitVerse + embed circuit in slides +
+
+ +
+

Authorize Yourself
To Insert Circuit In Slide

+ +
+ +
+ + +
+ +
+ +
+ CircuitVerse + embed circuit in slides +
+
+ +
+
+
+
+ + +
+ +
+ +
+ CircuitVerse + embed circuit in slides +
+
+ +
+ + + + +
+ + + +
+
+ + +
+ +   +
+ CircuitVerse + embed circuit +
+
+ + +
+ + + +
+
\ No newline at end of file diff --git a/Chrome Extension/views/browser_action.html b/Chrome Extension/views/popup.html similarity index 51% rename from Chrome Extension/views/browser_action.html rename to Chrome Extension/views/popup.html index caf6fb7..59091c6 100644 --- a/Chrome Extension/views/browser_action.html +++ b/Chrome Extension/views/popup.html @@ -17,6 +17,6 @@

CircuitVerse Live Circuit!

- This extension will now load live circuits in Google Slides. Make sure to install Google Slides Add-On as well. For more details, read the user documentation here. + This extension will now load live circuits in Google Slides. For more details, read the user documentation here.

\ No newline at end of file diff --git a/Firefox Extension/img/google-icon.png b/Firefox Extension/img/google-icon.png new file mode 100644 index 0000000..133eea3 Binary files /dev/null and b/Firefox Extension/img/google-icon.png differ diff --git a/Firefox Extension/img/logo_white.png b/Firefox Extension/img/logo_white.png new file mode 100644 index 0000000..363a0b5 Binary files /dev/null and b/Firefox Extension/img/logo_white.png differ diff --git a/Firefox Extension/manifest.json b/Firefox Extension/manifest.json index 2eeaa02..769d8a4 100644 --- a/Firefox Extension/manifest.json +++ b/Firefox Extension/manifest.json @@ -1,39 +1,53 @@ { - "name": "CircuitVerse", - "version": "0.0.1", - "manifest_version": 2, - "description": "CircuitVerse Firefox Extension", - "homepage_url": "https://circuitverse.org", - "icons": { - "16": "icons/icon16.png", - "19": "icons/icon19.png", - "32": "icons/icon32.png", - "48": "icons/icon48.png", - "128": "icons/icon128.png" - }, - "browser_action": { - "default_icon": "icons/icon32.png", - "default_popup": "views/browser_action.html", - "default_title": "Embed CircuitVerse Live Circuit" - }, - "default_locale": "en", - "background": { - "scripts": [ - "src/bg/background.js" - ], - "persistent": true - }, - "permissions": [ - "https://docs.google.com/*" - ], - "content_scripts": [ - { - "matches": [ - "https://docs.google.com/*" + "name": "CircuitVerse", + "version": "0.0.2", + "manifest_version": 2, + "description": "CircuitVerse Firefox Extension", + "homepage_url": "https://circuitverse.org", + "icons": { + "16": "icons/icon16.png", + "19": "icons/icon19.png", + "32": "icons/icon32.png", + "48": "icons/icon48.png", + "128": "icons/icon128.png" + }, + "browser_action": { + "default_icon": "icons/icon32.png", + "default_popup": "views/popup.html", + "default_title": "Embed CircuitVerse Live Circuit" + }, + "default_locale": "en", + "background": { + "scripts": [ + "src/bg/background.js" ], - "js": [ - "src/inject/inject.js" + "persistent": true + }, + "permissions": [ + "https://docs.google.com/*", + "https://circuitverse.org/*", + "https://www.googleapis.com/*", + "https://googleapis.com/*", + "https://slides.googleapis.com/*", + "storage", + "tabs" + ], + "content_scripts": [ + { + "matches": [ + "https://docs.google.com/*" + ], + "js": [ + "src/inject/inject.js" + ] + } + ], + "web_accessible_resources": [ + "views/embedTool.html", + "styles/embedTool.css", + "src/inject/embedTool.js", + "src/inject/gsi.client.js", + "img/google-icon.png", + "img/logo_white.png" ] - } - ] -} + } \ No newline at end of file diff --git a/Firefox Extension/src/bg/background.js b/Firefox Extension/src/bg/background.js index 65144c7..c7a9301 100644 --- a/Firefox Extension/src/bg/background.js +++ b/Firefox Extension/src/bg/background.js @@ -1,17 +1,308 @@ -// if you checked "fancy-settings" in extensionizr.com, uncomment this lines +// On install, open the CircuitVerse Docs in a new tab +chrome.runtime.onInstalled.addListener(function(object) { + chrome.tabs.create({url: 'https://docs.circuitverse.org/#/chapter2/2cvforeducators?id=embed-circuitverse-simulation-in-google-slides'}); +}); -// var settings = new Store("settings", { -// "sample_setting": "This is how you use Store.js to remember values" -// }); +function sendResponse(tabId, response, message) { + var msg = message; + msg["callback_id"] = response["callback_id"]; + msg["origin"] = response["origin"]; + chrome.tabs.sendMessage(tabId, msg); +} -// example of using a message handler from the inject scripts +// Handle messages from the injected Embed tool +chrome.runtime.onMessage.addListener(async function(request, sender) { + //? Handle new successful authentication callback + if (request.message_type === "USER_AUTHENTICATION_SUCCESSFUL") { + var access_token = request.access_token; + var expires_in = request.expires_in - 30; // as the internal process takes some time deduct 30 seconds + var expires_in_timestamp = Date.now() + expires_in * 1000; + var email; -// chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { -// chrome.pageAction.show(sender.tab.id); -// sendResponse(); -// }); + // Fetch user profile + var headers = new Headers(); + headers.append("Authorization", "Bearer " + access_token); -chrome.runtime.onInstalled.addListener(function(object) { - chrome.tabs.create({url: 'https://docs.circuitverse.org/#/embedding_circuits?id=embedding-in-google-slides'}); -}); + var requestOptions = { + method: 'GET', + headers: headers, + redirect: 'follow' + }; + + fetch("https://www.googleapis.com/oauth2/v1/userinfo?alt=json", requestOptions) + .then(response => response.json()) + .then(async(result) => { + email = result.email; + // Store the access token in the local session storage + // as we dont want to keep temporary tokens permerantly as they have max ttl of 1 hour + var payload_ = {} + payload_[email] = { + access_token: access_token, + expires_in: expires_in_timestamp, + }; + await browser.storage.local.set(payload_) + sendResponse(sender.tab.id, request, { + "message_type": "USER_AUTHENTICATION_SUCCESSFUL", + "email": email + }) + }) + .catch(error => { + sendResponse(sender.tab.id, request, { + "message_type": "USER_AUTHENTICATION_FAILED" + }) + }); + } + //? Used to check whether the email id is logged in and access_token is still valid + else if(request.message_type === "CHECK_LOGIN_STATUS"){ + var email = request.email; + var result = await browser.storage.local.get(email); + // If no record in storage, user is not logged in + if(result[email] === undefined || result[email] === null){ + sendResponse(sender.tab.id, request, { + "message_type": "USER_NOT_LOGGED_IN", + "email": email + }) + }else{ + // If record is present, check if access_token is still valid and expires_in is not expired + var access_token = result[email].access_token; + var expires_in = result[email].expires_in; + if(expires_in <= Date.now() || access_token === "" || access_token === null || access_token === undefined){ + await browser.storage.local.remove(email); + sendResponse(sender.tab.id, request, { + "message_type": "USER_NOT_LOGGED_IN", + "email": email + }) + }else{ + sendResponse(sender.tab.id, request, { + "message_type": "USER_LOGGED_IN", + "email": email + }) + } + } + } + //? Embed the circuit in slides + else if(request.message_type === "EMBED_CIRCUIT"){ + var email = request.email; + var link_of_page = request.link_of_page; // extract page id and presentation id + var circuitverse_link = request.circuitverse_link; + + // Parse the presentation id and slide id from the link + var tmp_ = parsePresentationLink(link_of_page); + var link_parse_status = tmp_[0]; + var presentation_id = tmp_[1]; + var slide_id = tmp_[2]; + if(link_parse_status === false){ + sendResponse(sender.tab.id, request, { + "message_type": "INVALID_PRESENTATION_LINK" + }) + return; + }else{ + // Fetch the access token from the local storage + var result = await browser.storage.local.get(email); + // If no record in storage, user is not logged in + if(result[email] === undefined || result[email] === null){ + sendResponse(sender.tab.id, request, { + "message_type": "USER_NOT_LOGGED_IN", + "email": email + }) + }else{ + // If record is present, check if access_token is still valid and expires_in is not expired + var access_token = result[email].access_token; + var expires_in = result[email].expires_in; + if(expires_in <= Date.now() || access_token === "" || access_token === null || access_token === undefined){ + browser.storage.local.remove([email]); // we need not to wait for this to complete + sendResponse(sender.tab.id, request, { + "message_type": "USER_LOGIN_SESSION_EXPIRED", + "email": email + }) + } + // If access_token is valid, embed the circuit in the slide + // Step 1: prepare the preview image link and hyperlink + var circuitverse_project_id = getProjectId(circuitverse_link); + var preview_image_link = await getCircuitPreviewImagePath(circuitverse_project_id); + var circuit_hyperlink = getCircuitEmbedPath(circuitverse_project_id); + // Step 2: fetch revison id of the slide + var revison_id_request = await fetchPresentationRevisionId(presentation_id, slide_id, access_token); + if(revison_id_request[0] === false) { + sendResponse(sender.tab.id, request, { + "message_type": "CIRCUIT_EMBEDDING_FAILED" + }) + return; + } + var presentation_revision_id = revison_id_request[1]; + // Step 3: insert image + var insert_image_request = await insertImageInSlide(presentation_id, slide_id, presentation_revision_id, preview_image_link, access_token); + if(insert_image_request[0] === false) { + sendResponse(sender.tab.id, request, { + "message_type": "CIRCUIT_EMBEDDING_FAILED" + }) + return; + } + // Step 4: insert hyperlink + var insert_hyperlink_request = await insertHyperlinkInImage(presentation_id, slide_id, insert_image_request[2], insert_image_request[1],circuit_hyperlink, access_token); + if(insert_hyperlink_request[0] === false) { + sendResponse(sender.tab.id, request, { + "message_type": "CIRCUIT_EMBEDDING_FAILED" + }) + return; + } + // TODO refetch revison id and give one retry + // Send success message + sendResponse(sender.tab.id, request, { + "message_type": "CIRCUIT_EMBEDDING_SUCCESSFUL" + }) + } + } + } +}) + +// Parse project id from url +function getProjectId(url) { + var re1= /https:\/\/circuitverse\.org\/users\/\d*\/projects\/(.*)/; + var re2 = /"https:\/\/circuitverse\.org\/simulator\/embed\/(.*?)"/; + var re3 = /https:\/\/circuitverse\.org\/simulator\/edit\/(.*)/; + var re4 = /https:\/\/circuitverse\.org\/simulator\/embed\/(.*)/; + var re5 = /https:\/\/circuitverse\.org\/simulator\/(.*)/; + + if(re1.test(url)) return url.match(re1)[1]; + if(re2.test(url)) return url.match(re2)[1]; + if(re3.test(url)) return url.match(re3)[1]; + if(re4.test(url)) return url.match(re4)[1]; + if(re5.test(url)) return url.match(re5)[1]; + return ""; +} + +// Get embed path of circuit from ID +function getCircuitEmbedPath(id) { + return `https://circuitverse.org/simulator/embed/${id}`; +} + +// Get circuit image path from ID +async function getCircuitPreviewImagePath(id) { + var queryUrl = `https://circuitverse.org/api/v1/projects/${id}/image_preview`; + var response = await fetch(queryUrl); + var data = await response.json(); + return data.project_preview; +} + +// Parse presentation id and slide id from url of page +function parsePresentationLink(url) { + // Check whether `link_of_page` is a valid google slides link and consists the slide_id + var re = /https:\/\/docs\.google\.com\/presentation\/d\/(.*)\/edit#slide=id\.(.*)/; + if(!re.test(url)){ + returrn [false, null, null]; + } + // Extract the slide_id and presentation_id from the link + var presentation_id = url.match(re)[1]; + var slide_id = url.match(re)[2]; + return [true, presentation_id, slide_id]; +} + +// Fetch Slides Revison Id +async function fetchPresentationRevisionId(presentation_id, slide_id, access_token) { + var queryUrl = `https://slides.googleapis.com/v1/presentations/${presentation_id}/pages/${slide_id}`; + var response = await fetch(queryUrl, { + headers: { + Authorization: `Bearer ${access_token}`, + } + }); + if(response.status !== 200) return [false, null]; + var data = await response.json(); + return [true, data.revisionId]; +} + +// Insert image in slide +async function insertImageInSlide(presentation_id, slide_id, revision_id, img_link, access_token) { + // Generate object id for image + var objectId = generateObjectId(); + // Prepare headers + var request_headers = new Headers(); + request_headers.append("Authorization", `Bearer ${access_token}`); + // Prepare body + var body = { + "requests": [ + { + "createImage": { + "objectId": objectId, + "elementProperties": { + "pageObjectId": slide_id, + "size": { + "width": { + "magnitude": 320, + "unit": "pt" + }, + "height": { + "magnitude": 240, + "unit": "pt" + } + } + }, + "url": img_link + } + } + ], + "writeControl": { + "requiredRevisionId": revision_id + } + }; + var request_options = { + method: 'POST', + headers: request_headers, + body: JSON.stringify(body), + redirect: 'follow' + }; + // Send request + var request = await fetch(`https://slides.googleapis.com/v1/presentations/${presentation_id}:batchUpdate`, request_options); + if(request.status !== 200) return [false, null, null]; + var data = await request.json(); + // return [status, image object id, revison id] + return [true, objectId, data.writeControl.requiredRevisionId]; +} + +// Insert hyperlink to image +async function insertHyperlinkInImage(presentation_id, slide_id, revision_id, object_id, hyperlink, access_token) { + // Prepare headers + var request_headers = new Headers(); + request_headers.append("Authorization", `Bearer ${access_token}`); + // body + var body = { + "requests": [ + { + "updateImageProperties": { + "objectId": object_id, + "fields": "link", + "imageProperties": { + "link": { + "url": hyperlink + } + } + } + } + ], + "writeControl": { + "requiredRevisionId": revision_id + } + } + var request_options = { + method: 'POST', + headers: request_headers, + body: JSON.stringify(body), + redirect: 'follow' + } + // Send request + var request = await fetch(`https://slides.googleapis.com/v1/presentations/${presentation_id}:batchUpdate`, request_options); + if(request.status !== 200) return false; + else return true; +} + +// Generate object id +function generateObjectId() { + var result = ''; + var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-:123456789'; + var charactersLength = Math.floor(Math.random()*(50-10+1)+10); // random number between 10 and 50 + for ( var i = 0; i < charactersLength; i++ ) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} \ No newline at end of file diff --git a/Firefox Extension/src/inject/embedTool.js b/Firefox Extension/src/inject/embedTool.js new file mode 100644 index 0000000..72b12bd --- /dev/null +++ b/Firefox Extension/src/inject/embedTool.js @@ -0,0 +1,251 @@ +// Get current page url +function getCurrentPageUrl() { + return window.location.href || document.location.href; +} +// Get the extension id +function fetchExtensionId() { + return document.getElementById('circuitverse-extension-id').innerText; +} + +// Get logged in user e-mail id -> returnn empty string if not found +function getLoggedInEmail() { + let email = null; + try { + email = gbar_.CONFIG[0][4]["ya"][5] + }catch(err) { + try { + email = IJ_values[32]; + } catch (error) { + email = null; + } + } + return (email === null || email === undefined) ? "unknown" : email +} + +function guidGenerator() { + var S4 = function() { + return (((1+Math.random())*0x10000)|0).toString(16).substring(1); + }; + return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4()); +} + +let callback_store = {}; + + + +// Send message to background +function sendMessageToBackground(message, callback) { + // chrome.runtime.sendMessage(fetchExtensionId(), message, callback); + let id = guidGenerator(); + callback_store[id] = callback; + message["callback_id"] = id; + window.postMessage(message, "*"); +} + +function processIncomingRequest(event){ + if (event.source == window && event.data && event.data.callback_id && event.data["for_content_script"] === true) { + let callback = callback_store[event.data.callback_id]; + if(callback){ + callback(event.data); + delete callback_store[event.data.callback_id]; + } + } +} + +// Listen to message +function listenMessageFromBackground() { + window.addEventListener("message", processIncomingRequest); +} + +// Authorize user +function authorizeUser() { + // TODO : update oauth token + const client = google.accounts.oauth2.initTokenClient({ + client_id: '707727329587-7t91s6ri6ob0j01ok04t4iddkectvs0r.apps.googleusercontent.com', + scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/presentations', + hint: getLoggedInEmail(), + callback: function(response){ + var access_token = response.access_token; + var expires_in = response.expires_in; + sendMessageToBackground({ + message_type: "USER_AUTHENTICATION_SUCCESSFUL", + access_token: access_token, + expires_in: expires_in + }, function(response) { + var type = response.message_type; + if(type === "USER_AUTHENTICATION_SUCCESSFUL"){ + var email = response.email; + updateLoggedinEmail(email); + showFormScreen(); + }else if(type === "USER_AUTHENTICATION_FAILED"){ + console.log("CircuitVerse : Failed User Authentication by Implicit OAuth 2.0") + } + }) + } + }); + client.requestAccessToken() +} + +// Check login status +function checkLoginStatus() { + sendMessageToBackground({ + message_type: "CHECK_LOGIN_STATUS", + email: getLoggedInEmail() + }, function(response) { + var type_ = response.message_type; + var email_ = response.email; + if(type_ === "USER_NOT_LOGGED_IN"){ + showAuthorizeScreen(); + }else if(type_ === "USER_LOGGED_IN"){ + updateLoggedinEmail(email_); + showFormScreen(); + } + }) +} + +// Insert Circuit Embed with link +function insertLink() { + const circuitVerseLink = document.getElementById('circuitverse__link_input').value; + if(circuitVerseLink === null || circuitVerseLink === undefined || circuitVerseLink === "") return; + showLoadingScreen(); + sendMessageToBackground({ + message_type: "EMBED_CIRCUIT", + link_of_page: getCurrentPageUrl(), + email: getLoggedInEmail(), + circuitverse_link: circuitVerseLink + }, function(response) { + showFormScreen(); + var type_ = response.message_type; + if(type_ === "INVALID_PRESENTATION_LINK"){ + showMessageOnScreen("Invalid presentation link", false, 5); + }else if(type_ === "USER_NOT_LOGGED_IN"){ + showMessageOnScreen("User not logged in", false, 5); + setTimeout(()=>showAuthorizeScreen(), 5000); + }else if(type_ === "USER_LOGIN_SESSION_EXPIRED"){ + showMessageOnScreen("Login session expired", false, 5); + setTimeout(()=>showAuthorizeScreen(), 5000); + }else if(type_ === "CIRCUIT_EMBEDDING_FAILED"){ + showMessageOnScreen("Circuit embedding failed", false, 5); + }else if(type_ === "CIRCUIT_EMBEDDING_SUCCESSFUL"){ + showMessageOnScreen("Successfully inserted circuit in slide", true, 5); + document.getElementById('circuitverse__link_input').value = ""; + } + showFormScreen(); + }); +} + +function getAbsoluteUrl(path) { + return "moz-extension://"+fetchExtensionId()+"/"+path +} + + +//? UI Related functions and variables +// Main window +let circuitverse_embed_tool_window = document.getElementById("circuitverse__embed_tool_window"); +// Screens +let circuitverse__embed_tool_window_authorize_screen = document.getElementsByClassName("authorize_screen")[0]; +let circuitverse__embed_tool_window_loading_screen = document.getElementsByClassName("loading_container")[0]; +let circuitverse__embed_tool_window_form_screen = document.getElementsByClassName("form_screen")[0]; +// Components +let circuitverse__msg_box = document.getElementsByClassName("msg_box")[0]; +let circuitverse__link_input = document.getElementById("circuitverse__link_input"); +let circuitverse__logged_in_email = document.getElementById("circuitverse__logged_in_email"); +// Buttons +let circuitverse__embed_tool_open_btn = document.getElementsByClassName("circuitverse__embed_open_btn")[0]; +let circuitverse__embed_tool_close_btn = document.getElementsByClassName("circuitverse__embed_close_btn")[0]; +let circuitverse__authorize_btn = document.getElementById("circuitverse__authorize_btn"); +let circuitverse__embed_btn = document.getElementById("circuitverse__embed_btn"); + + +function onclickOpenButton(){ + // Make sure to disable open button + circuitverse__embed_tool_open_btn.classList.add("hide"); + // Show close button + circuitverse__embed_tool_close_btn.classList.remove("hide"); + // Make circuitverse_embed_tool_window visible + circuitverse_embed_tool_window.classList.remove("hide"); +} + +function onclickCloseButton(){ + // Make sure to disable open button + circuitverse__embed_tool_open_btn.classList.remove("hide"); + // Show close button + circuitverse__embed_tool_close_btn.classList.add("hide"); + // Make circuitverse_embed_tool_window visible + circuitverse_embed_tool_window.classList.add("hide"); +} + +function showLoadingScreen(){ + circuitverse__embed_tool_window_authorize_screen.classList.add("hide"); + circuitverse__embed_tool_window_form_screen.classList.add("hide"); + circuitverse__embed_tool_window_loading_screen.classList.remove("hide"); +} + +function showAuthorizeScreen() { + circuitverse__embed_tool_window_form_screen.classList.add("hide"); + circuitverse__embed_tool_window_loading_screen.classList.add("hide"); + circuitverse__embed_tool_window_authorize_screen.classList.remove("hide"); +} + +function showFormScreen(){ + circuitverse__embed_tool_window_authorize_screen.classList.add("hide"); + circuitverse__embed_tool_window_loading_screen.classList.add("hide"); + circuitverse__embed_tool_window_form_screen.classList.remove("hide"); +} + +function showMessageOnScreen(message, successful, duration_seconds) { + if(successful){ + circuitverse__msg_box.classList.remove("error"); + circuitverse__msg_box.classList.add("success"); + }else{ + circuitverse__msg_box.classList.remove("success"); + circuitverse__msg_box.classList.add("error"); + } + circuitverse__msg_box.innerText = message; + circuitverse__msg_box.classList.remove("invisible"); + setTimeout(()=>{ + circuitverse__msg_box.classList.add("invisible"); + }, duration_seconds*1000); +} + +function updateLoggedinEmail(email) { + circuitverse__logged_in_email.innerText = email; +} + + +// Initialization function + +function initEmbedTool(){ + var interval = setInterval(function(){ + if(document.readyState === 'complete') { + clearInterval(interval); + // Start listening to message from bridge + listenMessageFromBackground(); + // Insert assets + let logo_white_url = getAbsoluteUrl("img/logo_white.png"); + document.getElementById("logo_white_1").src = logo_white_url; + document.getElementById("logo_white_2").src = logo_white_url; + document.getElementById("logo_white_3").src = logo_white_url; + document.getElementById("logo_white_4").src = logo_white_url; + + let google_icon_url = getAbsoluteUrl("img/google-icon.png"); + document.getElementById("google_icon").src = google_icon_url; + + // Initialize all event listeners + circuitverse__authorize_btn.addEventListener('click', authorizeUser); + circuitverse__embed_btn.addEventListener("click", insertLink); + circuitverse__embed_tool_open_btn.addEventListener("click", onclickOpenButton); + circuitverse__embed_tool_close_btn.addEventListener("click", onclickCloseButton); + + // Show loading screen by default + showLoadingScreen(); + + // Check for login status + checkLoginStatus(); + + } + }, 10); +} + + +initEmbedTool(); \ No newline at end of file diff --git a/Firefox Extension/src/inject/gsi.client.js b/Firefox Extension/src/inject/gsi.client.js new file mode 100644 index 0000000..08b9565 --- /dev/null +++ b/Firefox Extension/src/inject/gsi.client.js @@ -0,0 +1,384 @@ +"use strict";this.default_gsi=this.default_gsi||{};(function(_){var window=this; + try{ + var aa,ba,ca,da,q,ea,fa,ha,ja;aa=function(a){var b=0;return function(){return b>>0)+"_",d=0,e=function(f){if(this instanceof e)throw new TypeError("b");return new b(c+(f||"")+"_"+d++,f)};return e}); + q("Symbol.iterator",function(a){if(a)return a;a=Symbol("c");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c=f}}); + q("Array.prototype.find",function(a){return a?a:function(b,c){a:{var d=this;d instanceof String&&(d=String(d));for(var e=d.length,f=0;f=e}}); + var pa=function(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&cc&&(c=Math.max(0,e+c));if(null==d||d>e)d=e;d=Number(d);0>d&&(d=Math.max(0,e+d));for(c=Number(c||0);cc&&(c=Math.max(c+e,0));c=b};_.Ka=function(a){return a?"[GSI_LOGGER-"+a+"]: ":"[GSI_LOGGER]: "};_.x=function(a,b){try{_.Ja("debug")&&window.console&&window.console.log&&window.console.log(_.Ka(b)+a)}catch(c){}}; + _.y=function(a,b){try{_.Ja("warn")&&window.console&&window.console.warn&&window.console.warn(_.Ka(b)+a)}catch(c){}};_.A=function(a,b){try{_.Ja("error")&&window.console&&window.console.error&&window.console.error(_.Ka(b)+a)}catch(c){}};_.La=function(a,b,c){for(var d in a)b.call(c,a[d],d,a)};Na=function(a,b){for(var c,d,e=1;eb?1:0}; + _.Da=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;cparseFloat(gb)){fb=String(ib);break a}}fb=gb}_.kb=fb; + var Ga=new Map;Ga.set("debug",0);Ga.set("info",1);Ga.set("warn",2);Ga.set("error",3);_.Ha="warn"; + for(var lb=[],mb=0;63>mb;mb++)lb[mb]=0;_.nb=[].concat(128,lb); + var Ma="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "); + _.C=function(a,b){this.h=b===_.ob?a:""};_.C.prototype.toString=function(){return this.h.toString()};_.C.prototype.ha=!0;_.C.prototype.ea=function(){return this.h.toString()};_.pb=function(a){return a instanceof _.C&&a.constructor===_.C?a.h:"type_error:SafeUrl"};_.qb=/^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))/i;_.ob={};_.rb=new _.C("about:invalid#zClosurez",_.ob); + var vb;_.sb={};_.tb=function(a,b){this.h=b===_.sb?a:"";this.ha=!0};_.tb.prototype.ea=function(){return this.h.toString()};_.tb.prototype.toString=function(){return this.h.toString()};_.ub=function(a){return a instanceof _.tb&&a.constructor===_.tb?a.h:"type_error:SafeHtml"};vb=new _.tb(_.v.trustedTypes&&_.v.trustedTypes.emptyHTML||"",_.sb); + _.wb=function(a){var b=!1,c;return function(){b||(c=a(),b=!0);return c}}(function(){var a=document.createElement("div"),b=document.createElement("div");b.appendChild(document.createElement("div"));a.appendChild(b);b=a.firstChild.firstChild;a.innerHTML=_.ub(vb);return!b.parentElement}); + _.xb=String.prototype.repeat?function(a,b){return a.repeat(b)}:function(a,b){return Array(b+1).join(a)}; + _.yb=function(){this.o=this.o;this.m=this.m};_.yb.prototype.o=!1;_.yb.prototype.jc=function(){return this.o};_.yb.prototype.V=function(){this.o||(this.o=!0,this.aa())};_.yb.prototype.aa=function(){if(this.m)for(;this.m.length;)this.m.shift()()}; + _.zb=function(a,b){this.type=a;this.h=this.target=b;this.defaultPrevented=this.i=!1};_.zb.prototype.stopPropagation=function(){this.i=!0};_.zb.prototype.preventDefault=function(){this.defaultPrevented=!0}; + var Ab=function(){if(!_.v.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});try{_.v.addEventListener("test",function(){},b),_.v.removeEventListener("test",function(){},b)}catch(c){}return a}(); + var Cb=function(a,b){_.zb.call(this,a?a.type:"");this.relatedTarget=this.h=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=this.l=this.j=0;this.key="";this.charCode=this.keyCode=0;this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.state=null;this.pointerId=0;this.pointerType="";this.W=null;if(a){var c=this.type=a.type,d=a.changedTouches&&a.changedTouches.length?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.h=b;if(b=a.relatedTarget){if(_.db){a:{try{$a(b.nodeName); + var e=!0;break a}catch(f){}e=!1}e||(b=null)}}else"mouseover"==c?b=a.fromElement:"mouseout"==c&&(b=a.toElement);this.relatedTarget=b;d?(this.clientX=void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX||0,this.screenY=d.screenY||0):(this.j=_.eb||void 0!==a.offsetX?a.offsetX:a.layerX,this.l=_.eb||void 0!==a.offsetY?a.offsetY:a.layerY,this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX= + a.screenX||0,this.screenY=a.screenY||0);this.button=a.button;this.keyCode=a.keyCode||0;this.key=a.key||"";this.charCode=a.charCode||("keypress"==c?a.keyCode:0);this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=a.metaKey;this.pointerId=a.pointerId||0;this.pointerType="string"===typeof a.pointerType?a.pointerType:Bb[a.pointerType]||"";this.state=a.state;this.W=a;a.defaultPrevented&&Cb.ra.preventDefault.call(this)}};_.Sa(Cb,_.zb);var Bb={2:"touch",3:"pen",4:"mouse"}; + Cb.prototype.stopPropagation=function(){Cb.ra.stopPropagation.call(this);this.W.stopPropagation?this.W.stopPropagation():this.W.cancelBubble=!0};Cb.prototype.preventDefault=function(){Cb.ra.preventDefault.call(this);var a=this.W;a.preventDefault?a.preventDefault():a.returnValue=!1};Cb.prototype.Zc=function(){return this.W}; + var Db;Db="closure_listenable_"+(1E6*Math.random()|0);_.Eb=function(a){return!(!a||!a[Db])}; + var Fb=0; + var Gb=function(a,b,c,d,e){this.listener=a;this.proxy=null;this.src=b;this.type=c;this.capture=!!d;this.Ba=e;this.key=++Fb;this.Sa=this.ab=!1},Hb=function(a){a.Sa=!0;a.listener=null;a.proxy=null;a.src=null;a.Ba=null}; + var Ib=function(a){this.src=a;this.h={};this.i=0},Kb;Ib.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.h[f];a||(a=this.h[f]=[],this.i++);var g=Jb(a,b,d,e);-1>>0);_.Rb=function(a){if("function"===typeof a)return a;a[Zb]||(a[Zb]=function(b){return a.handleEvent(b)});return a[Zb]}; + _.$b=function(){_.yb.call(this);this.ba=new Ib(this);this.Ga=this;this.L=null};_.Sa(_.$b,_.yb);_.$b.prototype[Db]=!0;_.l=_.$b.prototype;_.l.addEventListener=function(a,b,c,d){_.D(this,a,b,c,d)};_.l.removeEventListener=function(a,b,c,d){Xb(this,a,b,c,d)}; + _.l.dispatchEvent=function(a){var b,c=this.L;if(c)for(b=[];c;c=c.L)b.push(c);c=this.Ga;var d=a.type||a;if("string"===typeof a)a=new _.zb(a,c);else if(a instanceof _.zb)a.target=a.target||c;else{var e=a;a=new _.zb(d,c);Na(a,e)}e=!0;if(b)for(var f=b.length-1;!a.i&&0<=f;f--){var g=a.h=b[f];e=ac(g,d,!0,a)&&e}a.i||(g=a.h=c,e=ac(g,d,!0,a)&&e,a.i||(e=ac(g,d,!1,a)&&e));if(b)for(f=0;!a.i&&fb)throw Error("v`"+b);a.v=b}else a.v=null};_.mc=function(a,b,c){b instanceof pc?(a.l=b,vc(a.l,a.m)):(c||(b=qc(b,wc)),a.l=new pc(b,a.m))};_.xc=function(a){return a instanceof _.ic?new _.ic(a):new _.ic(a)}; + oc=function(a,b){return a?b?decodeURI(a.replace(/%25/g,"%2525")):decodeURIComponent(a):""};qc=function(a,b,c){return"string"===typeof a?(a=encodeURI(a).replace(b,yc),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,"%$1")),a):null};yc=function(a){a=a.charCodeAt(0);return"%"+(a>>4&15).toString(16)+(a&15).toString(16)};rc=/[#\/\?@]/g;tc=/[#\?:]/g;sc=/[#\?]/g;wc=/[#\?@]/g;uc=/#/g;pc=function(a,b){this.i=this.h=null;this.j=a||null;this.l=!!b}; + zc=function(a){a.h||(a.h=new Map,a.i=0,a.j&&fc(a.j,function(b,c){a.add(decodeURIComponent(b.replace(/\+/g," ")),c)}))};_.Bc=function(a){var b=hc(a);if("undefined"==typeof b)throw Error("x");var c=new pc(null);a=gc(a);for(var d=0;dh?"":0==h?";expires="+(new Date(1970,1,1)).toUTCString():";expires="+(new Date(Date.now()+1E3*h)).toUTCString())+(d?";secure":"")+(null!=e?";samesite="+e:"")}; + _.Oc.prototype.get=function(a,b){for(var c=a+"=",d=(this.h.cookie||"").split(";"),e=0,f;e=a.h||d)return td(a)[b]=c,a;a.J[b+a.ya]=c;(c=a.Z)&&b in c&&delete c[b];return a};wd=function(a){var b=_.H(a);if(b&2)return a;a=_.Xa(a,vd);fd(b,a);Object.freeze(a);return a}; + zd=function(a,b,c){c=void 0===c?fd:c;if(null!=a){if(Wc&&a instanceof Uint8Array)return a.length?new _.nd(new Uint8Array(a),_.xd):_.yd();if(Array.isArray(a)){var d=_.H(a);if(d&2)return a;if(b&&!(d&32)&&(d&16||0===d))return _.ad(a,d|2),a;a=_.pd(a,zd,c,!0);b=_.H(a);b&4&&b&2&&Object.freeze(a);return a}return a.fb===_.kd?vd(a):a}};vd=function(a){if(_.cd(a.J))return a;a=Ad(a,!0);_.Zc(a.J,2);return a}; + Ad=function(a,b){var c=a.J,d=_.dd([]),e=a.constructor.h;e&&d.push(e);e=a.Z;if(e){d.length=c.length;d.fill(void 0,d.length,c.length);var f={};d[d.length-1]=f}0!==(_.H(c)&128)&&hd(d);b=b||a.ia()?fd:_.ed;d=jd(a.constructor,d);a.Da&&(d.Da=a.Da.slice());for(var g=!!(_.H(c)&16),h=e?c.length-1:c.length,k=0;k/g;le=/"/g;me=/'/g;ne=/\x00/g;oe=/[\x00&<>"']/;pe=function(){this.blockSize=-1}; + se=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909, + 275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];te=function(a,b){this.blockSize=-1;this.blockSize=64;this.j=_.v.Uint8Array?new Uint8Array(this.blockSize):Array(this.blockSize);this.l=this.i=0;this.h=[];this.o=a;this.m=b;this.s=_.v.Int32Array?new Int32Array(64):Array(64);void 0===qe&&(_.v.Int32Array?qe=new Int32Array(se):qe=se);this.reset()};_.Sa(te,pe); + te.prototype.reset=function(){this.l=this.i=0;this.h=_.v.Int32Array?new Int32Array(this.m):_.Fa(this.m)}; + var ue=function(a){for(var b=a.j,c=a.s,d=0,e=0;eb;b++){e=c[b-15]|0;d=c[b-2]|0;var f=(c[b-16]|0)+((e>>>7|e<<25)^(e>>>18|e<<14)^e>>>3)|0,g=(c[b-7]|0)+((d>>>17|d<<15)^(d>>>19|d<<13)^d>>>10)|0;c[b]=f+g|0}d=a.h[0]|0;e=a.h[1]|0;var h=a.h[2]|0,k=a.h[3]|0,m=a.h[4]|0,n=a.h[5]|0,p=a.h[6]|0;f=a.h[7]|0;for(b=0;64>b;b++){var t=((d>>>2|d<<30)^(d>>>13|d<<19)^(d>>>22|d<<10))+(d&e^d&h^e&h)|0;g=m&n^~m&p;f=f+((m>>>6|m<<26)^(m>>>11|m<<21)^(m>>> + 25|m<<7))|0;g=g+(qe[b]|0)|0;g=f+(g+(c[b]|0)|0)|0;f=p;p=n;n=m;m=k+g|0;k=h;h=e;e=d;d=g+t|0}a.h[0]=a.h[0]+d|0;a.h[1]=a.h[1]+e|0;a.h[2]=a.h[2]+h|0;a.h[3]=a.h[3]+k|0;a.h[4]=a.h[4]+m|0;a.h[5]=a.h[5]+n|0;a.h[6]=a.h[6]+p|0;a.h[7]=a.h[7]+f|0}; + te.prototype.update=function(a,b){void 0===b&&(b=a.length);var c=0,d=this.i;if("string"===typeof a)for(;c=e&&e==(e|0)))throw Error("m");this.j[d++]=e;d==this.blockSize&&(ue(this),d=0)}else throw Error("n");this.i=d;this.l+=b}; + te.prototype.digest=function(){var a=[],b=8*this.l;56>this.i?this.update(_.nb,56-this.i):this.update(_.nb,this.blockSize-(this.i-56));for(var c=63;56<=c;c--)this.j[c]=b&255,b/=256;ue(this);for(c=b=0;c>d&255;return a};var ve=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],Tc=function(){te.call(this,8,ve)};_.Sa(Tc,te);xe={};_.ye=function(a,b){this.h=b===xe?a:""}; + _.ye.prototype.toString=function(){return this.h+""};_.ye.prototype.ha=!0;_.ye.prototype.ea=function(){return this.h.toString()};_.ze=function(a){return a instanceof _.ye&&a.constructor===_.ye?a.h:"type_error:TrustedResourceUrl"}; + Jd=function(a){if(void 0===we){var b=null;var c=_.v.trustedTypes;if(c&&c.createPolicy){try{b=c.createPolicy("goog#html",{createHTML:he,createScript:he,createScriptURL:he})}catch(d){_.v.console&&_.v.console.error(d.message)}we=b}else we=b}a=(b=we)?b.createHTML(a):a;return new _.tb(a,_.sb)}; + Kd=function(a){a instanceof _.tb||(a="object"==typeof a&&a.ha?a.ea():String(a),oe.test(a)&&(-1!=a.indexOf("&")&&(a=a.replace(ie,"&")),-1!=a.indexOf("<")&&(a=a.replace(je,"<")),-1!=a.indexOf(">")&&(a=a.replace(ke,">")),-1!=a.indexOf('"')&&(a=a.replace(le,""")),-1!=a.indexOf("'")&&(a=a.replace(me,"'")),-1!=a.indexOf("\x00")&&(a=a.replace(ne,"�"))),a=Jd(a));return a}; + Ae=function(a,b,c){var d;a=c||a;if(a.querySelectorAll&&a.querySelector&&b)return a.querySelectorAll(b?"."+b:"");if(b&&a.getElementsByClassName){var e=a.getElementsByClassName(b);return e}e=a.getElementsByTagName("*");if(b){var f={};for(c=d=0;a=e[c];c++){var g=a.className,h;if(h="function"==typeof g.split)h=0<=(0,_.Da)(g.split(/\s+/),b);h&&(f[d++]=a)}f.length=d;return f}return e}; + _.Be=function(a,b){var c=b||document;return c.querySelectorAll&&c.querySelector?c.querySelectorAll("."+a):Ae(document,a,b)};_.Ce=function(a,b){var c=b||document;if(c.getElementsByClassName)a=c.getElementsByClassName(a)[0];else{c=document;var d=b||c;a=d.querySelectorAll&&d.querySelector&&a?d.querySelector(a?"."+a:""):Ae(c,a,b)[0]||null}return a||null};_.De=function(a){for(var b;b=a.firstChild;)a.removeChild(b)};_.Ee=function(a){return a&&a.parentNode?a.parentNode.removeChild(a):null}; + _.Fe=function(a,b){if(a)if(_.Eb(a))a.ba&&_.Mb(a.ba,b);else if(a=_.Tb(a)){var c=0;b=b&&b.toString();for(var d in a.h)if(!b||d==b)for(var e=a.h[d].concat(),f=0;f>2];g=b[(g&3)<<4|h>>4];h=b[(h&15)<<2|k>>6];k=b[k&63];c[f++]=m+g+h+k}m=0;k=d;switch(a.length-e){case 2:m=a[e+1],k=b[(m&15)<<2]||d;case 1:a=a[e],c[f]=b[a>>2]+b[(a&3)<<4|m>>4]+k+d}return c.join("")}; + _.Me=function(){if(!_.Le){_.Le={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),b=["+/=","+/","-_=","-_.","-_"],c=0;5>c;c++){var d=a.concat(b[c].split(""));Ke[c]=d;for(var e=0;e=a.h?a.Z?a.Z[b]:void 0:c&&a.Z&&(c=a.Z[b],null!=c)?c:a.J[b+a.ya]};_.I=function(a,b,c,d){_.Re(a);return _.ud(a,b,c,d)};_.Te=function(a,b,c){return void 0!==Se(a,b,c,!1)};_.L=function(a,b){a=_.F(a,b);return null==a?a:!!a};Se=function(a,b,c,d){var e=_.F(a,c,d);b=_.ld(e,b);b!==e&&null!=b&&(_.ud(a,c,b,d),_.Zc(b.J,_.H(a.J)&18));return b}; + _.M=function(a,b,c,d){d=void 0===d?!1:d;b=Se(a,b,c,d);if(null==b)return b;if(!_.cd(a.J)){var e=_.Ue(b);e!==b&&(b=e,_.ud(a,c,b,d))}return b};_.Bd=function(a,b,c,d){_.Re(a);if(null!=c){var e=_.bd([]);for(var f=!1,g=0;g":">","`":"`","\u0085":"…","\u00a0":" ","\u2028":"
","\u2029":"
"};tf=function(a){return Ef[a]}; + Ff={"\x00":"%00","\u0001":"%01","\u0002":"%02","\u0003":"%03","\u0004":"%04","\u0005":"%05","\u0006":"%06","\u0007":"%07","\b":"%08","\t":"%09","\n":"%0A","\v":"%0B","\f":"%0C","\r":"%0D","\u000e":"%0E","\u000f":"%0F","\u0010":"%10","\u0011":"%11","\u0012":"%12","\u0013":"%13","\u0014":"%14","\u0015":"%15","\u0016":"%16","\u0017":"%17","\u0018":"%18","\u0019":"%19","\u001a":"%1A","\u001b":"%1B","\u001c":"%1C","\u001d":"%1D","\u001e":"%1E","\u001f":"%1F"," ":"%20",'"':"%22","'":"%27","(":"%28",")":"%29", + "<":"%3C",">":"%3E","\\":"%5C","{":"%7B","}":"%7D","\u007f":"%7F","\u0085":"%C2%85","\u00a0":"%C2%A0","\u2028":"%E2%80%A8","\u2029":"%E2%80%A9","\uff01":"%EF%BC%81","\uff03":"%EF%BC%83","\uff04":"%EF%BC%84","\uff06":"%EF%BC%86","\uff07":"%EF%BC%87","\uff08":"%EF%BC%88","\uff09":"%EF%BC%89","\uff0a":"%EF%BC%8A","\uff0b":"%EF%BC%8B","\uff0c":"%EF%BC%8C","\uff0f":"%EF%BC%8F","\uff1a":"%EF%BC%9A","\uff1b":"%EF%BC%9B","\uff1d":"%EF%BC%9D","\uff1f":"%EF%BC%9F","\uff20":"%EF%BC%A0","\uff3b":"%EF%BC%BB", + "\uff3d":"%EF%BC%BD"};_.Cf=function(a){return Ff[a]};sf=/[\x00\x22\x26\x27\x3c\x3e]/g;Gf=/[\x00\x22\x27\x3c\x3e]/g;_.Bf=/[\x00- \x22\x27-\x29\x3c\x3e\\\x7b\x7d\x7f\x85\xa0\u2028\u2029\uff01\uff03\uff04\uff06-\uff0c\uff0f\uff1a\uff1b\uff1d\uff1f\uff20\uff3b\uff3d]/g;Af=/^[^&:\/?#]*(?:[\/?#]|$)|^https?:|^ftp:|^data:image\/[a-z0-9+]+;base64,[a-z0-9+\/]+=*$|^blob:/i;_.yf=function(a){return String(a).replace(Gf,tf)};_.zf=function(a){return String(a).replace(_.Bf,_.Cf)};wf=/<(?:!|\/?([a-zA-Z][a-zA-Z0-9:\-]*))(?:[^>'"]|"[^"]*"|'[^']*')*>/g; + xf=/':'')}; + + _.gf("cancelable_auto_select"); + + _.gf("enable_clearcut_logs"); + + _.gf("enable_intermediate_iframe"); + + _.gf("enable_revoke_without_credentials"); + + }catch(e){_._DumpException(e)} + try{ + var ki,ni,oi;_.li=function(a,b,c){c=void 0===c?!0:c;if(b&&2===_.F(b,7)){var d={};b&&(d={kc:_.F(b,6),shape:_.F(b,3),size:_.F(b,1),text:_.F(b,5),theme:_.F(b,2),width:_.F(b,4),Oa:void 0===c?!0:c});_.Ld(a,ii,d)}else b&&2===_.F(b,10)&&!_.hf("disable_personalized_button")?(c=void 0===c?!0:c,b&&_.Te(b,_.bf,8)?(d={},b&&(d={shape:_.F(b,3),text:_.F(b,5),theme:_.F(b,2),width:_.F(b,4),md:_.Md(_.M(b,_.bf,8)),nd:_.F(b,9),Oa:c}),_.Ld(a,ji,d)):ki(a,b,c)):ki(a,b,c)}; + ki=function(a,b,c){var d={};b&&(d={kc:_.F(b,6),shape:_.F(b,3),size:_.F(b,1),text:_.F(b,5),theme:_.F(b,2),width:_.F(b,4),Oa:void 0===c?!0:c});_.Ld(a,mi,d)};ni={};oi=function(a,b){this.h=b===ni?a:"";this.ha=!0};oi.prototype.ea=function(){return this.h};oi.prototype.toString=function(){return this.h.toString()};var pi=function(a){return a instanceof oi&&a.constructor===oi?a.h:"type_error:SafeStyle"},qi={},ri=function(a,b){this.h=b===qi?a:"";this.ha=!0};ri.prototype.toString=function(){return this.h.toString()}; + ri.prototype.ea=function(){return this.h}; + var si=function(a){return a instanceof ri&&a.constructor===ri?a.h:"type_error:SafeStyleSheet"},ti={},ui=function(a,b){return a&&b&&a.bd&&b.bd?a.za!==b.za?!1:a.toString()===b.toString():a instanceof _.Hd&&b instanceof _.Hd?a.za!=b.za?!1:a.toString()==b.toString():a==b},vi=function(a){return a.replace(/<\//g,"<\\/").replace(/\]\]>/g,"]]\\>")},wi=/^(?!-*(?:expression|(?:moz-)?binding))(?:(?:[.#]?-?(?:[_a-z0-9-]+)(?:-[_a-z0-9-]+)*-?|(?:rgb|rgba|hsl|hsla|calc|max|min|cubic-bezier)\([-\u0020\t,+.!#%_0-9a-zA-Z]+\)|[-+]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:e-?[0-9]+)?(?:[a-z]{1,4}|%)?|!important)(?:\s*[,\u0020]\s*|$))*$/i,xi= + function(a){_.qf(a,ti)?a=vi(a.Ka):null==a?a="":a instanceof oi?a=vi(pi(a)):a instanceof oi?a=vi(pi(a)):a instanceof ri?a=vi(si(a)):a instanceof ri?a=vi(si(a)):(a=String(a),a=wi.test(a)?a:"zSoyz");return a},yi=function(){return(0,_.P)('')}; + _.zi=function(a){_.N.call(this,a)};_.K(_.zi,_.N);_.l=_.zi.prototype;_.l.zc=function(){return _.Ve(this,1)};_.l.Bc=function(){return _.Ve(this,2)};_.l.yc=function(){return _.Ve(this,3)};_.l.Dc=function(){return _.Ve(this,4)};_.l.Ac=function(){return _.Ve(this,5)};_.l.wc=function(){return _.Ve(this,6)};_.l.Cc=function(){return _.Ve(this,7)};_.l.xc=function(){return _.Ve(this,9)}; + var Ei=function(a,b,c,d,e,f,g,h){var k=void 0===g?!0:g;h=void 0===h?!1:h;g=e&&1!=e?_.Q(Ai(e)):_.Q(Ai(2));var m=_.P;k="
'+Di(ui(c,2)||ui(c,3))+(h?"":''+_.Q(Ai(e))+"")+''+g+"
")},Bi=function(a){var b="";switch(a){case 2:b+="MFS4be-v3pZbf-Ia7Qfc MFS4be-Ia7Qfc";break;case 3:b+="MFS4be-JaPV2b-Ia7Qfc MFS4be-Ia7Qfc";break;default:b+="i5vt6e-Ia7Qfc"}return b}, + Ci=function(a){var b="";switch(a){case 2:b+="JGcpL-RbRzK";break;case 4:b+="JGcpL-RbRzK";break;default:b+="uaxL4e-RbRzK"}return b},Ai=function(a){var b="";switch(a){case 1:b+="Sign in";break;case 3:b+="Sign up with Google";break;case 4:b+="Continue with Google";break;default:b+="Sign in with Google"}return b},Di=function(a){return(0,_.P)((void 0===a?0:a)?'
'+yi()+"
":'
'+yi()+"
")}; + var mi=function(a){a=a||{};var b=a.Oa;return(0,_.P)(Ei(a.kc,a.size,a.theme,a.shape,a.text,a.width,void 0===b?!0:b))},ii=function(a){a=a||{};var b=a.Oa;return(0,_.P)(Ei(void 0,a.size,a.theme,a.shape,a.text,void 0,void 0===b?!0:b,!0))},ji=function(a){var b=a.Oa,c=a.md,d=a.nd,e=a.shape,f=a.text,g=a.theme,h=a.width;a=_.P;var k=void 0===b?!0:b;b=c.ic?c.ic:c.displayName;e="
';c.pa?(e+='',h=_.R(b?b:c.id)+'):e+=_.Kf();h='
';k="";if(b)switch(f){case 4:k+="Continue as "+ + b;break;default:k+="Sign in as "+b}else k+=Ai(f);e+=h+_.Q(k)+'
'+_.Q(c.id)+"
"+(1'):"")+"
"+Di(ui(g,2)||ui(g,3))+"
";c=(0,_.P)(e);return a(c)}; + + }catch(e){_._DumpException(e)} + try{ + _.Oi=function(){var a=_.ra();if(_.ua())return _.za(a);a=_.sa(a);var b=_.ya(a);return _.ta()?b(["Version","Opera"]):_.w("Edge")?b(["Edge"]):_.w("Edg/")?b(["Edg"]):_.w("Silk")?b(["Silk"]):_.wa()?b(["Chrome","CriOS","HeadlessChrome"]):(a=a[2])&&a[1]||""};_.Ri=function(){return![_.wa()&&!_.Pi()&&!_.Qi(),_.wa()&&_.w("Android"),_.w("Edge")].some(function(a){return a})}; + _.Si=function(){return _.xa()||(_.w("iPad")||_.w("iPhone"))&&!_.xa()&&!_.wa()&&!_.w("Coast")&&!_.va()&&_.w("AppleWebKit")||_.Ba()&&0<=_.Va(_.Ca(),"14.4")||_.va()&&0<=_.Va(_.Oi(),"100")}; + _.Pi=function(){return!_.Qi()&&(_.w("iPod")||_.w("iPhone")||_.w("Android")||_.w("IEMobile"))};_.Qi=function(){return _.w("iPad")||_.w("Android")&&!_.w("Mobile")||_.w("Silk")}; + var Ti;Ti={}; + _.Ui=(Ti.enable_fedcm="28250620661-550h2e8djhee3ri2nma0u294i6ks921r.apps.googleusercontent.com 28250620661-jplop9r4d3uj679blu2nechmlm3h89gk.apps.googleusercontent.com 721418733929-55iv503445sqh9rospct8lthb3n46f3k.apps.googleusercontent.com 538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com 780994550302-0b687p4i9l66nunnvkvlje5bjfdm4tb3.apps.googleusercontent.com 817667923408-mm67cha4vukqtq6aj0faaibfofl1memo.apps.googleusercontent.com 916232382604-225e0sa3bdsq7k0ekpoh9sl1nne7okf8.apps.googleusercontent.com 488525074229-5rqhf4jaqmqpiosqevcmbclbo5nmsdh4.apps.googleusercontent.com 687088973437-38pnelafhrqnth469mvgm2ma64aev0il.apps.googleusercontent.com 402150438060-mvb4nhmp3o8rh83452qqlqq8bch09bnt.apps.googleusercontent.com 58828047352-u541mjj0fguhe0v26j4f2lm6q647anvh.apps.googleusercontent.com 965288796332-0h7v07k49r7ggo08nggbg2sdop6eop7d.apps.googleusercontent.com 834141296178-3itknsh2mneibsovevaoltkhrcadp6vv.apps.googleusercontent.com 624372386952-1kbovj4d6ejmlib859olmuq89qlonqbh.apps.googleusercontent.com 731494682028-3n7jsq8ladl31e4s02ehpbvvdh0ee613.apps.googleusercontent.com 918187601222-03rud06q74l0dc8ni8vmv10s7jrfo29e.apps.googleusercontent.com 269789103163-vupssne2p7gtgs30ms2ta2sd0ujlgf6s.apps.googleusercontent.com 34426703102-s53835smi0gfuba2u3f5d5trhdj15p5p.apps.googleusercontent.com 629251271814-hbnj6o76ofknqot961urbdqeoaujvvkh.apps.googleusercontent.com 289442006438-040a42cbidr6v5d178f3iqi9q95821r3.apps.googleusercontent.com 690222127349-t1i7h5njnm024hlum1df998qopl24l1o.apps.googleusercontent.com".split(" "),Ti); + + }catch(e){_._DumpException(e)} + try{ + _.wk=function(a){if(a instanceof _.C)a=_.pb(a);else{b:if(_.lf){try{var b=new URL(a)}catch(c){b="https:";break b}b=b.protocol}else c:{b=document.createElement("a");try{b.href=a}catch(c){b=void 0;break c}b=b.protocol;b=":"===b||""===b?"https:":b}a="javascript:"!==b?a:void 0}return a};_.xk=function(a){var b=void 0===b?_.mf:b;a:{b=void 0===b?_.mf:b;for(var c=0;cf.length&&(f=g));var h=jn(d.j,a);0h.length&&h.length!=g.length&& + (a=a.substr(h.length+1),h+="."+a.split(".")[0],h.length>f.length&&(f=h));var k=f.split("").reverse().join("");if(2>c.indexOf("."+k))return _.A("Invalid origin pattern. Patterns cannot be composed of a wildcard and a top level domain."),!1}catch(m){return!1}return!0}; + cn=function(){kn||(kn=_.D(window,"message",function(a){a=a.W;if(a.data){var b=a.data;"onetap_google"===b.sentinel&&"parent_frame_ready"===b.command&&(_.x("Message received: "+JSON.stringify(b)),window.parent&&window.parent===a.source?$m?b.nonce!==$m?_.y("Message ignored due to invalid nonce."):(ln(a.origin)?(_.Ym=a.origin,_.mn=b.parentMode||"amp_client",dn&&dn()):(_.y("Origin verification failed. Invalid origin - "+a.origin+"."),en&&en()),en=dn=$m=void 0,kn&&(_.Yb(kn),kn=void 0)):_.y("Message ignored. Origin verifier is not ready, or already done."): + _.y("Message ignored due to invalid source."))}}))};ln=function(a){return"string"===typeof bn?nn(bn,a):Array.isArray(bn)?bn.some(function(b){return nn(b,a)}):!1};nn=function(a,b){a=_.xc(a);b=_.xc(b);if(a.i!==b.i)return!1;a=a.h;b=b.h;return a.startsWith("*.")?b.endsWith(a.substr(1))||b===a.substr(2):a===b};_.on=function(a){_.Ym?_.Zm({command:"intermediate_iframe_resize",height:a}):_.y("Resize command was not sent due to missing verified parent origin.")}; + _.pn=function(){_.Ym?_.Zm({command:"intermediate_iframe_close"}):_.y("Close command was not sent due to missing verified parent origin.")};_.qn=function(a){_.Ym?_.Zm({command:"set_tap_outside_mode",cancel:a}):_.y("Set tap outside mode command was not sent due to missing verified parent origin.")}; + var rn=function(){this.S=void 0;this.h={}};rn.prototype.set=function(a,b){sn(this,a,b,!1)};rn.prototype.add=function(a,b){sn(this,a,b,!0)};var sn=function(a,b,c,d){for(var e=0;ec&&(c=d);return b.substr(0,c+1)},vn=function(a){var b=new rn;wn(0,"",a,b);return b},wn=function(a,b,c,d){for(var e="\x00";a=(void 0===b?100:b)||(b=new _.ic(Pn),_.mc(b,_.Bc({client_id:Qn,as:Rn,event:a.toString()})),_.Ie(b.toString(),void 0,"POST",void 0,void 0,void 0,"https://accounts.google.com/gsi/log"!==Pn))},Wn=function(a){var b=new (Function.prototype.bind.apply(Tn,[null,"onetap",a,"prompt"].concat(Un(Vn.apply(1,arguments)))));Sn(b)}, + Xn=function(){var a=new (Function.prototype.bind.apply(Tn,[null,"onetap",void 0,"closed"].concat(Un(Vn.apply(0,arguments)))));Sn(a)},Yn=function(){var a=new (Function.prototype.bind.apply(Tn,[null,"id",void 0,"init"].concat(Un(Vn.apply(0,arguments)))));Sn(a)},eo=function(){var a=_.E("g_id_onload");if(a){var b=_.Tm(a);a=_.Pm(b,Zn);void 0===a.auto_prompt&&(a.auto_prompt=!0);a.auto_prompt&&a.skip_prompt_cookie&&_.Qc.get(a.skip_prompt_cookie)&&(a.auto_prompt=!1);delete a.skip_prompt_cookie;var c={},d; + for(d in b)b.hasOwnProperty(d)&&0>$n.indexOf(d.toLowerCase())&&(c[d]=b[d]);a.state&&(c.state=a.state);if(d=a.login_uri){b=_.xc(d);b.h||(_.jc(b,location.protocol),b.h=location.hostname,_.lc(b,location.port),Yn("relativeLoginUri",d),_.y("Relative login_uri was provided. Use absolute url instead. Relative login_uri may be considered invalid in the future."));if("https"!==b.i&&"localhost"!==b.h)throw Yn("unsecuredLoginUri",d),new ao("Unsecured login_uri provided.");d=b.toString();a.login_uri=d}d&&!a.callback&& + (a.callback=bo(d,c));"redirect"!==a.ux_mode||d||_.A("Missing required login_uri parameter for the redirect flow.");d=a.native_login_uri;delete a.native_login_uri;d&&a.native_callback?_.A("Cannot set both data-native_login_uri and data-native_callback."):d&&(a.native_callback=co(d,c,a.native_id_param||"email",a.native_password_param||"password"));return a}},bo=function(a,b){return function(c){c&&c.credential?(b.credential=c.credential,b.g_csrf_token=En(),_.nl(a,b)):Z("No credential found in the response.")}}, + co=function(a,b,c,d){return function(e){e&&"password"===e.type?(b[c]=e.id,b[d]=e.password,_.nl(a,b)):Z("No password credential returned.")}},go=function(a){a=_.Tm(a);return _.Pm(a,fo)},ko=function(a){a=new ho(a);io.__G_ID_CLIENT__=a;Hn(a.Nc);jo(a);return a},lo=function(a,b,c){var d=io.__G_ID_CLIENT__;d||(ko(),d=io.__G_ID_CLIENT__);d.T(a,b,c)},no=function(a,b,c){if(a&&b){var d=io.__G_ID_CLIENT__;d?mo(d,a,b,c):_.y("Failed to render button before calling initialize().")}else _.y("Failed to render button because there is no parent or options set.")}, + po=function(){var a=io.__G_ID_CLIENT__;a||(ko(),a=io.__G_ID_CLIENT__);oo(a.s)},qo=function(){var a=void 0===a?document.readyState:a;for(var b=_.Be("g_id_signout"),c=0;c=c?c:0};d=b[a.h+"p"];void 0!==d&&(c.disable_auto_prompt=d);a=b[a.h+"t"];void 0!==a&&(c.disable_auto_select_to=a);return c},Uo=function(a,b){var c=a.h+"p",d=a.h+"t",e=a.h+"l",f=So(a);void 0=== + b.disable_auto_prompt?delete f[c]:f[c]=b.disable_auto_prompt;void 0===b.disable_auto_select_to?delete f[d]:f[d]=b.disable_auto_select_to;f[e]=b.prompt_suppress_level;b=JSON.stringify(f);c=_.w("Android")&&_.wa()&&0<=_.Va(_.Oi(),"67");_.Qc.set(a.i,b,{lc:15552E3,path:"/",domain:a.j||void 0,Lb:c?!0:void 0,Kb:c?"none":void 0})},Vo=function(a){a=To(a).disable_auto_prompt;return void 0!==a&&a>(new Date).getTime()},oo=function(a){var b=To(a);b.disable_auto_select_to=Date.now()+864E5;Uo(a,b)},Wo=function(a){var b= + To(a);delete b.disable_auto_select_to;Uo(a,b)}; + var Xo=RegExp("^((?!\\s)[a-zA-Z0-9\u0080-\u3001\u3003-\uff0d\uff0f-\uff60\uff62-\uffffFF-]+[\\.\\uFF0E\\u3002\\uFF61])+(?!\\s)[a-zA-Z0-9\u0080-\u3001\u3003-\uff0d\uff0f-\uff60\uff62-\uffffFF-]{2,63}$"); + var Yo=function(){};Yo.prototype.next=function(){return Zo};var Zo={done:!0,value:void 0};Yo.prototype.Ia=function(){return this}; + var cp=function(a){if(a instanceof $o||a instanceof ap||a instanceof bp)return a;if("function"==typeof a.next)return new $o(function(){return a});if("function"==typeof a[Symbol.iterator])return new $o(function(){return a[Symbol.iterator]()});if("function"==typeof a.Ia)return new $o(function(){return a.Ia()});throw Error("za");},$o=function(a){this.h=a};$o.prototype.Ia=function(){return new ap(this.h())};$o.prototype[Symbol.iterator]=function(){return new bp(this.h())};$o.prototype.i=function(){return new bp(this.h())}; + var ap=function(a){this.h=a};_.K(ap,Yo);ap.prototype.next=function(){return this.h.next()};ap.prototype[Symbol.iterator]=function(){return new bp(this.h)};ap.prototype.i=function(){return new bp(this.h)};var bp=function(a){$o.call(this,function(){return a});this.j=a};_.K(bp,$o);bp.prototype.next=function(){return this.j.next()}; + var dp=function(){}; + var ep=function(){};_.Sa(ep,dp);ep.prototype[Symbol.iterator]=function(){return cp(this.Ia(!0)).i()}; + var fp=function(a){this.h=a};_.Sa(fp,ep);_.l=fp.prototype;_.l.set=function(a,b){try{this.h.setItem(a,b)}catch(c){if(0==this.h.length)throw"Storage mechanism: Storage disabled";throw"Storage mechanism: Quota exceeded";}};_.l.get=function(a){a=this.h.getItem(a);if("string"!==typeof a&&null!==a)throw"Storage mechanism: Invalid value was encountered";return a};_.l.tb=function(a){this.h.removeItem(a)}; + _.l.Ia=function(a){var b=0,c=this.h,d=new Yo;d.next=function(){if(b>=c.length)return Zo;var e=c.key(b++);if(a)return{value:e,done:!1};e=c.getItem(e);if("string"!==typeof e)throw"Storage mechanism: Invalid value was encountered";return{value:e,done:!1}};return d};_.l.key=function(a){return this.h.key(a)}; + var gp=function(){var a=null;try{a=window.sessionStorage||null}catch(b){}this.h=a};_.Sa(gp,fp); + var hp=function(a,b){this.i=a;this.h=b+"::"};_.Sa(hp,ep);hp.prototype.set=function(a,b){this.i.set(this.h+a,b)};hp.prototype.get=function(a){return this.i.get(this.h+a)};hp.prototype.tb=function(a){this.i.tb(this.h+a)};hp.prototype.Ia=function(a){var b=this.i[Symbol.iterator](),c=this,d=new Yo;d.next=function(){var e=b.next();if(e.done)return e;for(e=e.value;e.slice(0,c.h.length)!=c.h;){e=b.next();if(e.done)return e;e=e.value}return{value:a?e.slice(c.h.length):c.i.get(e),done:!1}};return d}; + var ip=new _.Ll("g_credential_picker"),kp=function(a,b){b=void 0===b?"i_":b;var c=new gp;if(c.h)try{c.h.setItem("__sak","1");c.h.removeItem("__sak");var d=!0}catch(e){d=!1}else d=!1;this.G=d?new hp(c,"g_state_id_"):null;this.Rc=b;this.j=a=Object.assign({},a);this.Fa=!1;this.B=!0;this.Y=null;b=new Uint8Array(16);(window.crypto||_.Fc.msCrypto).getRandomValues(b);this.D=btoa(String.fromCharCode.apply(String,Un(b))).replace(/=+$/,"");this.H=new Map;this.wa=this.xa=!1;jp(this,a)};_.K(kp,_.cf); + var jp=function(a,b){var c=a.G?a.G.get("ll")||void 0:void 0;if(c)lp(a,c);else{if(c=void 0!==b.log_level)c=b.log_level,c=void 0===c||0<=(0,_.Da)(Co,c);c&&lp(a,b.log_level)}a.Lc=b.button_url||"https://accounts.google.com/gsi/button";a.Wa=b.picker_url||"https://accounts.google.com/gsi/select";a.Wc=b.prompt_url||"https://accounts.google.com/gsi/iframe/select";a.cc=b.status_url||"https://accounts.google.com/gsi/status";a.O=_.Rm(a.cc);a.Nc=b.container_css_url||"https://accounts.google.com/gsi/style";a.Yc= + b.revoke_url||"https://accounts.google.com/gsi/revoke";c=a.O;var d=b.client_id,e=a.D;Pn=c?c+"/gsi/log":"https://accounts.google.com/gsi/log";Qn=d;Rn=e;a.callback=b.callback;a.ta="redirect"===b.ux_mode?"redirect":"popup";c=b.ui_mode;void 0!==c&&Object.values(Eo).includes(c)||(c=_.Pi()&&!_.Qi()?"bottom_sheet":"card");a.uiMode=c;a.u=(b.prompt_parent_id?document.getElementById(b.prompt_parent_id):null)||document.body;a.Vc=9E4;a.la=!1!==b.cancel_on_tap_outside;a.xa=!1!==b.itp_support;a.dc=void 0===b.use_fedcm_for_prompt? + void 0:!!b.use_fedcm_for_prompt;c=b.state_cookie_domain;!c||null!=c&&Xo.test(c)||(c=void 0);a.s=new Ro(c,a.Rc,b.state_cookie_name);a.Va(b);c={};void 0!==b.client_id&&(c.client_id=b.client_id);void 0!==b.origin&&(c.origin=b.origin);void 0!==b.auto_select&&(c.auto_select=b.auto_select);c.ux_mode=a.ta;"redirect"===c.ux_mode&&b.login_uri&&(c.login_uri=b.login_uri);c.ui_mode=a.uiMode;void 0!==b.context&&Object.values(Do).includes(b.context)&&(c.context=b.context);void 0!==b.hint&&(c.hint=b.hint);void 0!== + b.hosted_domain&&(c.hosted_domain=b.hosted_domain);void 0!==b.existing&&(c.existing=b.existing);void 0!==b.special_accounts&&(c.special_accounts=b.special_accounts);void 0!==b.nonce&&(c.nonce=b.nonce);void 0!==b.channel_id&&(c.channel_id=b.channel_id);void 0!==b.state&&(c.state=b.state);"warn"!==_.Ha&&(c.log_level=_.Ha);void 0!==b.hl&&(c.hl=b.hl);void 0!==b.disable_auto_focus&&(c.disable_auto_focus=b.disable_auto_focus);c.as=a.D;_.hf("rp_cancelable_auto_select")&&(c.feature="cancelableAutoSelect"); + a.Ha(c);a.h=c};kp.prototype.Va=function(){};kp.prototype.Ha=function(){}; + var jo=function(a){a.Fa||(a.Fa=!0,_.D(window,"message",function(b){mp(a,b.W)},!1),a.Y=_.D(document,"click",function(){a.la&&np(a,!1)&&(op(a,"tap_outside"),Xn("tapOutside"))}))},pp=function(){var a=window;return"IdentityCredential"in window||"FederatedCredential"in window&&a.FederatedCredential.prototype.login},rp=function(a){a.v=new AbortController;var b={url:"https://accounts.google.com/gsi/",configURL:"https://accounts.google.com/gsi/fedcm.json",clientId:a.h.client_id};a.h.nonce&&(b.nonce=a.h.nonce); + b={providers:[b],mode:"mediated",preferAutoSignIn:!!a.h.auto_select};navigator.credentials.get({ed:"optional",signal:a.v.signal,federated:b,identity:b}).then(function(c){var d={signal:a.v.signal};a.h.nonce&&(d.nonce=a.h.nonce);a.wa=!0;var e=function(f){a.callback&&(f={credential:f&&(f.idToken||f.token),select_by:"fedcm"},qp({data:{announcement:_.Jf({})}}),a.callback.call(a,f),_.x("FedCM response :"+JSON.stringify(f)))};"login"in c?c.login(d).then(e,function(f){_.A("FedCM login() rejects with "+f)}): + e(c)},function(c){_.A("FedCM get() rejects with "+c)})}; + kp.prototype.T=function(a,b,c){var d=this;np(this,!0)&&(sp(this,"flow_restarted"),Xn("flowRestarted"));this.m=a;this.ma=c;a=Object.assign({},this.j,b);jp(this,a);a="bottom_sheet"===this.h.ui_mode?"bottomSheet":"card";this.h.client_id?_.hf("unsupported_browser")?(Z("One Tap is not supported in this User Agent."),this.l("browser_not_supported"),_.ef(this,"prompt_display_failed",{cause:"Unsupported user agent for one tap."}),Wn(a,"browserNotSupported")):Vo(this.s)?(Z("User has closed One Tap before. Still in the cool down period."), + this.l("suppressed_by_user"),_.ef(this,"prompt_display_failed",{cause:"Prompt disabled by the user."}),Wn(a,"cooldown",(To(this.s).prompt_suppress_level||0).toString())):pp()&&(this.dc||void 0===this.dc&&_.Ui.enable_fedcm.includes(this.h.client_id)&&_.hf("enable_fedcm_via_userid"))?rp(this):tp(this,function(e){e&&_.L(e,3)?(up(d),vp(d),wp(d,!0)):e&&_.Te(e,_.O,2)?(_.Sc(_.M(e,_.O,2)),e=_.M(e,_.O,2),e=_.F(e,1),d.l(2===e?"opt_out_or_no_session":7===e?"secure_http_required":5===e?"unregistered_origin": + 3===e||4===e?"invalid_client":9===e?"browser_not_supported":12===e?"web_view_not_supported":"unknown_reason"),_.ef(d,"prompt_display_failed",{cause:"Error while checking for the credential status."})):e&&!_.L(e,3)&&_.Si()&&d.xa?(d.h.is_itp=!0,up(d),vp(d),wp(d,!0),delete d.h.is_itp):e&&!_.L(e,3)?(_.x("No sessions found in the browser."),d.l("opt_out_or_no_session"),_.ef(d,"prompt_display_failed",{cause:"No signed in Google accounts available."})):(_.x("Invalid response from check credential status."), + d.l("unknown_reason"),_.ef(d,"prompt_display_failed",{cause:"A network error was encountered while checking for the credential status."}))}):(_.A("Missing required parameter: client_id."),this.l("missing_client_id"),_.ef(this,"prompt_display_failed",{cause:"Missing required parameter: client_id."}),Wn(a,"noClientId"))}; + var mo=function(a,b,c,d){_.De(b);_.Fe(b);var e="gsi_"+Date.now()%1E6+"_"+Math.floor(1E6*Math.random()),f=new _.ic(a.Lc),g=Object.assign({},c),h=_.Hc(document,"div");h.classList.add("S9gUrf-YoZ4jf");h.style.position="relative";b.appendChild(h);b=xp(a,h,c,e);a.H.set(e,{iframeId:e,Ba:d,fc:c.click_listener,Cb:b,data:{nonce:g.nonce||a.j.nonce,state:g.state||a.j.state}});delete g.nonce;delete g.state;c=_.Bc(g);c.add("client_id",a.j.client_id);c.add("iframe_id",e);c.add("as",a.D);g.locale&&(c.add("hl",g.locale), + _.Dc(c,"locale"));"warn"!==_.Ha&&c.add("log_level",_.Ha);a.j.hint&&c.add("hint",a.j.hint);a.j.hosted_domain&&c.add("hosted_domain",a.j.hosted_domain);_.mc(f,c);g=_.Ri();f=Kn(h,f.toString(),e,g);g&&Dn(f,function(k){k.preventDefault();k.stopPropagation();yp(a,e)})},xp=function(a,b,c,d){var e=_.Hc(document,"div");b.appendChild(e);b=new No(e,c,function(){yp(a,d)});Oo(b);return b},zp=function(a,b){var c=a.H.get(b);if(c&&c.Cb){var d=c.Cb;requestAnimationFrame(function(){requestAnimationFrame(function(){d.V(); + c.Cb=void 0;a:{if(performance&&performance.getEntriesByType){var e=performance.getEntriesByType("navigation");if(0=d.disable_auto_select_to&&(Wo(c),d=To(c));c=!(d.disable_auto_select_to&&Date.now() {const head = document.head; const css = ".qJTHM\x7b-webkit-user-select:none;color:#202124;direction:ltr;-webkit-touch-callout:none;font-family:\x22Roboto-Regular\x22,arial,sans-serif;-webkit-font-smoothing:antialiased;font-weight:400;margin:0;overflow:hidden;-webkit-text-size-adjust:100%\x7d.ynRLnc\x7bleft:-9999px;position:absolute;top:-9999px\x7d.L6cTce\x7bdisplay:none\x7d.bltWBb\x7bword-break:break-all\x7d.hSRGPd\x7bcolor:#1a73e8;cursor:pointer;font-weight:500;text-decoration:none\x7d.Bz112c-W3lGp\x7bheight:16px;width:16px\x7d.Bz112c-E3DyYd\x7bheight:20px;width:20px\x7d.Bz112c-r9oPif\x7bheight:24px;width:24px\x7d.Bz112c-uaxL4e\x7b-webkit-border-radius:10px;border-radius:10px\x7d.LgbsSe-Bz112c\x7bdisplay:block\x7d.S9gUrf-YoZ4jf,.S9gUrf-YoZ4jf *\x7bborder:none;margin:0;padding:0\x7d.fFW7wc-ibnC6b\x3e.aZ2wEe\x3ediv\x7bborder-color:#4285f4\x7d.P1ekSe-ZMv3u\x3ediv:nth-child(1)\x7bbackground-color:#1a73e8!important\x7d.P1ekSe-ZMv3u\x3ediv:nth-child(2),.P1ekSe-ZMv3u\x3ediv:nth-child(3)\x7bbackground-image:linear-gradient(to right,rgba(255,255,255,.7),rgba(255,255,255,.7)),linear-gradient(to right,#1a73e8,#1a73e8)!important\x7d.haAclf\x7bdisplay:inline-block\x7d.nsm7Bb-HzV7m-LgbsSe\x7b-webkit-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:background-color .218s,border-color .218s;transition:background-color .218s,border-color .218s;-webkit-user-select:none;-webkit-appearance:none;background-color:#fff;background-image:none;border:1px solid #dadce0;color:#3c4043;cursor:pointer;font-family:\x22Google Sans\x22,arial,sans-serif;font-size:14px;height:40px;letter-spacing:0.25px;outline:none;overflow:hidden;padding:0 12px;position:relative;text-align:center;vertical-align:middle;white-space:nowrap;width:auto\x7d@media screen and (-ms-high-contrast:active)\x7b.nsm7Bb-HzV7m-LgbsSe\x7bborder:2px solid windowText;color:windowText\x7d\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe\x7bfont-size:14px;height:32px;letter-spacing:0.25px;padding:0 10px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe\x7bfont-size:11px;height:20px;letter-spacing:0.3px;padding:0 8px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe\x7bpadding:0;width:40px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.pSzOP-SxQuSe\x7bwidth:32px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.purZT-SxQuSe\x7bwidth:20px\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK\x7b-webkit-border-radius:20px;border-radius:20px\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK.pSzOP-SxQuSe\x7b-webkit-border-radius:16px;border-radius:16px\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK.purZT-SxQuSe\x7b-webkit-border-radius:10px;border-radius:10px\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc\x7bborder:none;color:#fff\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-v3pZbf-Ia7Qfc\x7bbackground-color:#1a73e8\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-JaPV2b-Ia7Qfc\x7bbackground-color:#202124;color:#e8eaed\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bheight:18px;margin-right:8px;min-width:18px;width:18px\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bheight:14px;min-width:14px;width:14px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bheight:10px;min-width:10px;width:10px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bmargin-left:8px;margin-right:-4px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bmargin:0;padding:10px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.pSzOP-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bpadding:8px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bpadding:4px\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;display:-webkit-box;display:-webkit-flex;display:flex;justify-content:center;-webkit-align-items:center;align-items:center;background-color:#fff;height:36px;margin-left:-10px;margin-right:12px;min-width:36px;width:36px\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf .nsm7Bb-HzV7m-LgbsSe-Bz112c,.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf .nsm7Bb-HzV7m-LgbsSe-Bz112c\x7bmargin:0;padding:0\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7bheight:28px;margin-left:-8px;margin-right:10px;min-width:28px;width:28px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7bheight:16px;margin-left:-6px;margin-right:8px;min-width:16px;width:16px\x7d.nsm7Bb-HzV7m-LgbsSe.Bz112c-LgbsSe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:3px;border-radius:3px;margin-left:2px;margin-right:0;padding:0\x7d.nsm7Bb-HzV7m-LgbsSe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:18px;border-radius:18px\x7d.nsm7Bb-HzV7m-LgbsSe.pSzOP-SxQuSe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:14px;border-radius:14px\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:8px;border-radius:8px\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-bN97Pc-sM5MNb\x7bdisplay:-webkit-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;-webkit-flex-direction:row;flex-direction:row;justify-content:space-between;-webkit-flex-wrap:nowrap;flex-wrap:nowrap;height:100%;position:relative;width:100%\x7d.nsm7Bb-HzV7m-LgbsSe .oXtfBe-l4eHX\x7bjustify-content:center\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7b-webkit-flex-grow:1;flex-grow:1;font-family:\x22Google Sans\x22,arial,sans-serif;font-weight:500;overflow:hidden;text-overflow:ellipsis;vertical-align:top\x7d.nsm7Bb-HzV7m-LgbsSe.purZT-SxQuSe .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7bfont-weight:300\x7d.nsm7Bb-HzV7m-LgbsSe .oXtfBe-l4eHX .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7b-webkit-flex-grow:0;flex-grow:0\x7d.nsm7Bb-HzV7m-LgbsSe .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7b-webkit-transition:background-color .218s;transition:background-color .218s;bottom:0;left:0;position:absolute;right:0;top:0\x7d.nsm7Bb-HzV7m-LgbsSe:hover,.nsm7Bb-HzV7m-LgbsSe:focus\x7b-webkit-box-shadow:none;box-shadow:none;border-color:#d2e3fc;outline:none\x7d.nsm7Bb-HzV7m-LgbsSe:hover .nsm7Bb-HzV7m-LgbsSe-MJoBVe,.nsm7Bb-HzV7m-LgbsSe:focus .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(66,133,244,.04)\x7d.nsm7Bb-HzV7m-LgbsSe:active .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(66,133,244,.1)\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc:hover .nsm7Bb-HzV7m-LgbsSe-MJoBVe,.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc:focus .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(255,255,255,.24)\x7d.nsm7Bb-HzV7m-LgbsSe.MFS4be-Ia7Qfc:active .nsm7Bb-HzV7m-LgbsSe-MJoBVe\x7bbackground:rgba(255,255,255,.32)\x7d.nsm7Bb-HzV7m-LgbsSe .n1UuX-DkfjY\x7b-webkit-border-radius:50%;border-radius:50%;display:-webkit-box;display:-webkit-flex;display:flex;height:20px;margin-left:-4px;margin-right:8px;min-width:20px;width:20px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId\x7bfont-family:\x22Roboto\x22;font-size:12px;text-align:left\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .ssJRIf,.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff .fmcmS\x7boverflow:hidden;text-overflow:ellipsis\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff\x7bdisplay:-webkit-box;display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;color:#5f6368;fill:#5f6368;font-size:11px;font-weight:400\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe.MFS4be-Ia7Qfc .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff\x7bcolor:#e8eaed;fill:#e8eaed\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-BPrWId .K4efff .Bz112c\x7bheight:18px;margin:-3px -3px -3px 2px;min-width:18px;width:18px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;margin-left:12px;margin-right:-10px\x7d.nsm7Bb-HzV7m-LgbsSe.jVeSEe.JGcpL-RbRzK .nsm7Bb-HzV7m-LgbsSe-Bz112c-haAclf\x7b-webkit-border-radius:18px;border-radius:18px\x7d.L5Fo6c-sM5MNb\x7bborder:0;display:block;left:0;position:relative;top:0\x7d.L5Fo6c-bF1uUb\x7b-webkit-border-radius:4px;border-radius:4px;bottom:0;cursor:pointer;left:0;position:absolute;right:0;top:0\x7d.L5Fo6c-bF1uUb:focus\x7bborder:none;outline:none\x7dsentinel\x7b\x7d"; const styleId = 'googleidentityservice_button_styles'; if (head && css && !document.getElementById(styleId)) {const style = document.createElement('style'); style.id = styleId; style.appendChild(document.createTextNode(css)); if (document.currentScript.nonce) style.setAttribute('nonce', document.currentScript.nonce); head.appendChild(style);}})(); \ No newline at end of file diff --git a/Firefox Extension/src/inject/inject.js b/Firefox Extension/src/inject/inject.js index 86c0675..8d7c860 100644 --- a/Firefox Extension/src/inject/inject.js +++ b/Firefox Extension/src/inject/inject.js @@ -1,195 +1,252 @@ -chrome.runtime.sendMessage({}, function(response) { - var readyStateCheckInterval = setInterval(function() { - if (document.readyState === 'complete') { - clearInterval(readyStateCheckInterval); - - // Specific location which allows the iframe embedded to be visible - function getEmbedLocation() { - return document.getElementsByClassName('punch-viewer-container')[0]; - } - - // Extract slide number from the presentation - function getSlideNumber() { - var labelElement = document.getElementsByClassName( - 'punch-viewer-svgpage-a11yelement')[0]; - if (!labelElement) return -1; - var label = labelElement.getAttribute('aria-label'); - return parseInt(label.match(/Slide (\d*)/)[1]); - } - - // Get the slide dimensions in svg values - function getSlideSvgViewDimensions() { - var svgContainer = document.getElementsByClassName( - 'punch-viewer-svgpage-svgcontainer')[0]; - var svg = svgContainer.children[0]; - var viewBox = svg.getAttribute('viewBox').split(' '); - - return { - slideW: parseFloat(viewBox[2]), slideH: parseFloat(viewBox[3]) - } - } - - // Extract position and size of embedded image in SVG - // Needed for identifying exact location to embed the iframe - function extractPositionFromPath(path) { - var svgLinkPath = path.getAttribute('d'); - - var pathRegexExp = - /m([\S]*) ([\S]*)l([\S]*) ([\S]*)l([\S]*) ([\S]*)l([\S]*) ([\S]*)z/; - var matches = svgLinkPath.match(pathRegexExp); - - var x1 = parseFloat(matches[1]); - var y1 = parseFloat(matches[2]); - var x2 = x1 + parseFloat(matches[3]); - var y2 = y1 + parseFloat(matches[4]); - var x3 = x2 + parseFloat(matches[5]); - var y3 = y2 + parseFloat(matches[6]); - var svgX = Math.min(x1, x2, x3); - var svgY = Math.min(y1, y2, y3); - var svgW = Math.max(x1, x2, x3) - svgX; - var svgH = Math.max(y1, y2, y3) - svgY; - return { - svgX, svgY, svgW, svgH - } - } - - // Get slide dimensions and offsets in pixels - function getSlideDimensions() { - var slideDiv = - document.getElementsByClassName('punch-viewer-content')[0]; - var metadata = { - xOffsetPx: parseFloat(slideDiv.style.left), - yOffsetPx: parseFloat(slideDiv.style.top), - slideWidthPx: parseFloat(slideDiv.style.width), - slideHeightPx: parseFloat(slideDiv.style.height), - }; - return metadata; - } - - - // Url in anchor tag in firefox is as follows - // https://www.google.com/url?q=https://circuitverse.org/simulator/embed/247&sa=D&ust=1601725669371000&usg=AFQjCNHjRBTGCOn7qQbamqK5YYcQ9AXgmA - // Helper function to extract actual circuitverse url only - function cleanUrl(url) { - var re = /q=([^&]*)\&/; - // if (re.test(url)) - // return url.match()[1]; - // else - return url; - } - - // Create circuitverse iframe from anchor tag - // Calculates exact position and places the iframe - function createEmbedIframe(anchorTag) { - var url = - anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); - - var {svgX, svgY, svgW, svgH} = - extractPositionFromPath(anchorTag.children[0]); - - - var {slideW, slideH} = getSlideSvgViewDimensions(); - - var {xOffsetPx, yOffsetPx, slideWidthPx, slideHeightPx} = - getSlideDimensions(); - - - var svg2px = slideWidthPx / slideW; - - - var absoluteXoffSetPx = xOffsetPx + svgX * svg2px; - var absoluteYoffSetPx = yOffsetPx + svgY * svg2px; - var widthPx = svgW * svg2px; - var heightPx = svgH * svg2px; - absoluteXoffSetPx = Math.round(absoluteXoffSetPx); - absoluteYoffSetPx = Math.round(absoluteYoffSetPx); - widthPx = Math.round(widthPx); - heightPx = Math.round(heightPx); - - - var ifrm = document.createElement('iframe'); - ifrm.classList.add('circuitverse-iframe'); // assign a class - ifrm.setAttribute('style', `position:fixed;z-index:100; - width:${widthPx}px; - height:${heightPx}px; - top:${absoluteYoffSetPx}px; - left:${absoluteXoffSetPx}px`); - // assign url - ifrm.setAttribute('src', cleanUrl(url)); - return ifrm; - } - - // Embeds iframe given link - function embed(anchorTag) { - var iframe = createEmbedIframe(anchorTag); - - var url = - anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); - - var location = getEmbedLocation(); - if (location == undefined) { - return; - } - - location.appendChild(iframe); // to place at end of document - - iframe_embedded = true; - url_embedded = url; - } - - // Removes all embedded iframes - function removeEmbed() { - var iframes = document.getElementsByClassName('circuitverse-iframe'); - while (iframes[0]) { - iframes[0].parentNode.removeChild(iframes[0]); - } - } - - // Keeps track of current frame - - var slideNumber = -1; - - // Setting slideNumber = -1 will reset everything - function reset() { - slideNumber = -1; - } - - // Driver logic - function main() { - // Bring slide into focus - necessary for slide transitions to work! - if (slideNumber != -1) { - document.body.focus(); - } - - if (slideNumber == getSlideNumber()) return; - - // New Slide - removeEmbed(); // remove previous iframes - slideNumber = getSlideNumber(); - - var anchorTags = document.getElementsByTagName('a'); - - var prevUrl = undefined; - for (var i = 0; i < anchorTags.length; i++) { - var url = anchorTags[i].getAttributeNS( - 'http://www.w3.org/1999/xlink', 'href'); - // Google Slides has 2 anchor tags for every link for some reason; - // Hence ensuring no duplicate embeds! - if (url != prevUrl && - url.includes('circuitverse.org/simulator/embed')) { - prevUrl = url - embed(anchorTags[i]); - } - } - } - // Call driver logic repeatedly - setInterval(main, 300); - - // Force reset after 3 seconds - needed for window resizing - // Also needed if first slide has circuit - window.addEventListener('resize', () => { - setTimeout(reset, 3000); - }); +//? Variables + +// Keeps track of current frame +let slideNumber = -1; + +//? Functions related to run the embedded CircuitVerse + +// Specific location which allows the iframe embedded to be visible +function getEmbedLocation() { + return document.getElementsByClassName('punch-full-screen-element')[0]; +} + +// Extract slide number from the presentation +function getSlideNumber() { + var labelElement = getSlideIframe().contentWindow.document.getElementsByClassName('punch-viewer-svgpage-a11yelement')[0]; + if (!labelElement) return -1; + var label = labelElement.getAttribute('aria-label'); + return parseInt(label.match(/Slide (\d*)/)[1]); +} + +// Get the slide iframe +function getSlideIframe() { + return document.getElementsByClassName('punch-present-iframe')[0]; +} + +// Get the slide dimensions in svg values +function getSlideSvgViewDimensions() { + var svgContainer = + getSlideIframe().contentWindow.document.getElementsByClassName('punch-viewer-svgpage-svgcontainer')[0]; + var svg = svgContainer.children[0]; + var viewBox = svg.getAttribute('viewBox').split(' '); + + return { + slideW: parseFloat(viewBox[2]), slideH: parseFloat(viewBox[3]) + } +} + +// Get slide dimensions and offsets in pixels +function getSlideDimensions() { + var slideDiv = getSlideIframe().contentWindow.document.getElementsByClassName('punch-viewer-content')[0]; + var metadata = { + xOffsetPx: parseFloat(slideDiv.style.left), + yOffsetPx: parseFloat(slideDiv.style.top), + slideWidthPx: parseFloat(slideDiv.style.width), + slideHeightPx: parseFloat(slideDiv.style.height), + }; + return metadata; +} + +// Extract position and size of embedded image in SVG +// Needed for identifying exact location to embed the iframe +function extractPositionFromPath(path) { + var svgLinkPath = path.getAttribute('d'); + var pathRegexExp = /M ([\S]*) ([\S]*) L ([\S]*) ([\S]*) ([\S]*) ([\S]*) ([\S]*) ([\S]*) Z/; + var matches = svgLinkPath.match(pathRegexExp); + var x1 = parseFloat(matches[1]); + var y1 = parseFloat(matches[2]); + var x2 = parseFloat(matches[3]); + var y3 = parseFloat(matches[6]); + var widthInSvg = x2 - x1; + var heightInSvg = y3 - y1; + return { + svgX: x1, svgY: y1, svgW: widthInSvg, svgH: heightInSvg + } +} + +// Create circuitverse iframe from anchor tag +// Calculates exact position and places the iframe +function createEmbedIframe(anchorTag) { + var url = + anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + var { svgX, svgY, svgW, svgH } = extractPositionFromPath(anchorTag.children[0]); + var { slideW, slideH } = getSlideSvgViewDimensions(); + var { xOffsetPx, yOffsetPx, slideWidthPx, slideHeightPx } = getSlideDimensions(); + + var svg2px = slideWidthPx / slideW; + var absoluteXoffSetPx = xOffsetPx + svgX * svg2px; + var absoluteYoffSetPx = yOffsetPx + svgY * svg2px; + var widthPx = svgW * svg2px; + var heightPx = svgH * svg2px; + absoluteXoffSetPx = Math.round(absoluteXoffSetPx); + absoluteYoffSetPx = Math.round(absoluteYoffSetPx); + widthPx = Math.round(widthPx); + heightPx = Math.round(heightPx); + + var ifrm = document.createElement('iframe'); + ifrm.classList.add('circuitverse-iframe'); // assign a class + ifrm.setAttribute('style', + `position:fixed;z-index:100; + width:${widthPx}px; + height:${heightPx}px; + top:${absoluteYoffSetPx}px; + left:${absoluteXoffSetPx}px` + ); + // assign url + ifrm.setAttribute('src', url); + return ifrm; +} + +// Embeds iframe given link +function embedCircuits(anchorTag) { + var iframe = createEmbedIframe(anchorTag); + var url = anchorTag.getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + var location = getEmbedLocation(); + if (location == undefined) { + return; + } + location.appendChild(iframe); // to place at end of document + iframe_embedded = true; + url_embedded = url; +} + +// Removes all embedded iframes +function removeEmbed() { + var iframes = document.getElementsByClassName('circuitverse-iframe'); + while(iframes[0]) { + iframes[0].parentNode.removeChild(iframes[0]); + } +} + +// Setting slideNumber = -1 will reset everything +function resetCircuitVerseEmbed() { + slideNumber = -1; +} + +// Driver logic +function initCircuitVerseIframeRunner() { + var iframeDocument = getSlideIframe(); + + if (!iframeDocument) { + slideNumber = -1; + removeEmbed(); + return; + } + + // Bring slide into focus - necessary for slide transitions to work! + if (slideNumber != -1) { + iframeDocument.contentWindow.document.body.focus(); + } + + if (slideNumber == getSlideNumber()) return; + + // New Slide + removeEmbed(); // remove previous iframes + slideNumber = getSlideNumber(); + + var anchorTags = iframeDocument.contentWindow.document.getElementsByTagName('a'); + + var prevUrl = undefined; + for (var i = 0; i < anchorTags.length; i++) { + var url = anchorTags[i].getAttributeNS('http://www.w3.org/1999/xlink', 'href'); + + // Google Slides has 2 anchor tags for every link for some reason; + // Hence ensuring no duplicate embeds! + if (url != prevUrl && + url.includes('circuitverse.org/simulator/embed')) { + prevUrl = url + embedCircuits(anchorTags[i]); } - }, 10); -}); + } +} + + +//? Function realaed to `CircuitVerse Embed Tool` initialization +function injectCircuitVerseEmbedTool() { + // Inject embed tool css + fetch(chrome.runtime.getURL('/styles/embedTool.css')).then(r => r.text()).then(css => { + var style = document.createElement('style'); + style.innerHTML = css; + document.head.appendChild(style); + }).then(()=>{ + + // Inject embed tool html + fetch(chrome.runtime.getURL('/views/embedTool.html')).then(r => r.text()).then(html => { + var div = document.createElement('div'); + div.innerHTML = html; + document.body.appendChild(div); + }).then(()=>{ + + // Inject embed tool javscript + var embedToolScript = document.createElement('script'); + embedToolScript.src = chrome.runtime.getURL('/src/inject/embedTool.js'); + document.getElementsByTagName("body")[0].appendChild(embedToolScript); + + }) + + }) + + + // Inject an Span tag with extension id + var circuitverseExtensionIDTag = document.createElement('span'); + circuitverseExtensionIDTag.id = 'circuitverse-extension-id'; + circuitverseExtensionIDTag.style.display = 'none'; + circuitverseExtensionIDTag.innerText = chrome.i18n.getMessage("@@extension_id") ; // Update for Firefox + document.getElementsByTagName("body")[0].appendChild(circuitverseExtensionIDTag); +} + +//? Bridge between Content-script and background-script +// Woraround for FireFox as chrome.runtime.sendMessageExternal not available +function startCommuniationBridge(){ + // Listen for messages from the content script + window.addEventListener("message", (event) => { + if (event.source != window) return; + if (event.data["for_content_script"]) return; + if (event.data) { + // Send message to background script + var data = event.data; + data["callback_id"] = event.data.callback_id; + data["origin"] = event.data.origin; + chrome.runtime.sendMessage(data); + } + }, false); +} + +function startListenerForBG() { + chrome.runtime.onMessage.addListener((response, sender) => { + // Send response back to content script + var res = response; + res["for_content_script"] = true; + window.postMessage(res, res.origin); + }) +} + + +// Run on document ready +document.onreadystatechange = function() { + +} + +var checkStatusInterval = setInterval(function() { + if (document.readyState === 'complete') { + //? Initialization Code for `CircuitVerse Embed Runner` + clearInterval(checkStatusInterval); + // Call driver logic repeatedly + setInterval(initCircuitVerseIframeRunner, 300); + // Force reset after 3 seconds - needed for window resizing + // Also needed if first slide has circuit + window.addEventListener('resize', () => { + setTimeout(resetCircuitVerseEmbed, 3000); + }); + + //? Start communication bridge between inject.js <---> content script to establish communication between background script <---> content script + startCommuniationBridge(); + startListenerForBG(); + + //? Initialization Code for `CircuitVerse Embed Tool` + var gsi_script = document.createElement('script'); + gsi_script.src = chrome.runtime.getURL("/src/inject/gsi.client.js"); // Load gsi client library for OAuth + gsi_script.onload = injectCircuitVerseEmbedTool; // run injectCircuitVerseEmbedTool( after loading gsi client library + document.getElementsByTagName("body")[0].appendChild(gsi_script); + } +}, 1000); \ No newline at end of file diff --git a/Firefox Extension/styles/embedTool.css b/Firefox Extension/styles/embedTool.css new file mode 100644 index 0000000..2b0bed6 --- /dev/null +++ b/Firefox Extension/styles/embedTool.css @@ -0,0 +1,326 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap'); + +:root{ + --circuitverse-primary-color: #42B983; + --circuitverse-error-color: #F44336; +} + +/* CSS Spinner */ +.lds-ring { + display: inline-block; + position: relative; + width: 80px; + height: 80px; +} + +.lds-ring div { + box-sizing: border-box; + display: block; + position: absolute; + width: 64px; + height: 64px; + margin: 8px; + border: 8px solid var(--circuitverse-primary-color); + border-radius: 50%; + animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; + border-color: var(--circuitverse-primary-color) transparent transparent transparent; +} + +.lds-ring div:nth-child(1) { + animation-delay: -0.45s; +} + +.lds-ring div:nth-child(2) { + animation-delay: -0.3s; +} + +.lds-ring div:nth-child(3) { + animation-delay: -0.15s; +} + +@keyframes lds-ring { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} + +/* Main */ +.circuitverse__embed_tool{ + width: fit-content; + height: fit-content; + position: absolute; + bottom: 50px; + right: 20px; + display: flex; + flex-direction: column; + align-items: flex-end; + row-gap: 20px; + z-index: 999; +} + +/* Show component class */ +.circuitverse__embed_tool .show{ + display: block!important; +} + +/* Hide component class */ +.circuitverse__embed_tool .hide{ + display: none!important; +} + +/* Visibility none */ +.circuitverse__embed_tool .invisible{ + visibility: hidden; +} + +/* Embed tool open button style */ +.circuitverse__embed_tool .circuitverse__embed_open_btn{ + height: 40px; + width: fit-content; + display: flex; + justify-content: center; + align-items: center; + padding: 8px; + padding-right: 18px; + border-radius: 50px; + + background-color: var(--circuitverse-primary-color); + color: white; + + font-family: 'Inter', sans-serif; + cursor: pointer; + +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn img{ + width: 38px; + height: 38px; +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn div{ + display: flex; + flex-direction: column; +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn .title{ + font-size: 16px; +} + +.circuitverse__embed_tool .circuitverse__embed_open_btn .subtitle{ + font-size: 12px; +} + +/* Embed tool close button styl */ +.circuitverse__embed_tool .circuitverse__embed_close_btn{ + height: 40px; + width: 40px; + background-color: var(--circuitverse-primary-color); + color: white; + padding: 8px; + border-radius: 50%; + cursor: pointer; +} + +/* Container */ +.circuitverse__embed_tool .circuitverse__embed_tool_container{ + position: relative; + width: 330px; + min-height: 400px; + background-color: #fff; + border: 1px solid #D3D3D3; + border-radius: 16px; + overflow: hidden; + display: flex; + flex-direction: column; + justify-content: space-between; + animation:fadeIn 0.3s linear; +} + +@keyframes fadeIn { + 0% { + opacity:0 + } + 100% { + opacity:1; + } +} + + +.circuitverse__embed_tool_container_header{ + height: 70px; + background-color: var(--circuitverse-primary-color); + border-radius: 16px 16px 0px 0px; + padding-left: 18px; + display: flex; + flex-direction: row; + justify-content: start; + align-items: center; +} + +.circuitverse__embed_tool_container_header img{ + width: 45px; + height: 45px; + margin-right: 12px; +} + +.circuitverse__embed_tool_container_header div{ + display: flex; + flex-direction: column; + font-family: 'Inter', sans-serif; + color: white; +} + +.circuitverse__embed_tool_container_header .title{ + font-size: 20px; + +} + +.circuitverse__embed_tool_container_header .subtitle{ + font-size: 14px; +} + +.circuitverse__embed_tool_container_body{ + padding: 18px; +} + +.circuitverse__embed_tool_container_footer{ + padding: 10px 15px; + background-color: #E8EEEB; + text-align: center; + font-family: 'Inter', sans-serif; +} + +/* loading_container */ +.loading_container .circuitverse__embed_tool_container_body{ + display: flex; + justify-content: center; + align-items: center; + flex: 1; +} + +.loading_container .circuitverse__embed_tool_container_body img{ + width: 100%; +} + +/* Authorize screen */ +.authorize_screen .circuitverse__embed_tool_container_body{ + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; +} + +.authorize_screen .circuitverse__embed_tool_container_body p{ + margin-right: 30px; + margin-left: 30px; + text-align: center; + font-size: 20px; + font-family: 'Inter', sans-serif; + margin-bottom: 40px; +} + +.authorize_screen .circuitverse__embed_tool_container_body button{ + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + background-color: #fff; + border: 0.2px solid #D3D3D3; + padding: 8px 15px; + border-radius: 6px; + cursor: pointer; +} + +.authorize_screen .circuitverse__embed_tool_container_body button img{ + width: 25px; + height: 25px; + margin-right: 10px; +} + +.authorize_screen .circuitverse__embed_tool_container_body button span{ + font-size: 16px; + font-family: 'Inter', sans-serif; +} + +.authorize_screen .circuitverse__embed_tool_container_footer{ + padding: 15px; + background-color: #fff; + text-align: justify; + font-size: 14px; +} + +/* Form screen */ +.form_screen .circuitverse__embed_tool_container_body label{ + font-family: 'Inter', sans-serif; + font-size: 18px; +} + +.form_screen .circuitverse__embed_tool_container_body input{ + height: 40px; + width: -moz-available; + border: 1.5px solid var(--circuitverse-primary-color); + border-radius: 6px; + padding: 8px; + font-size: 16px; + font-family: 'Inter', sans-serif; + margin-top: 10px; + margin-bottom: 14px; +} + +.form_screen .circuitverse__embed_tool_container_body button{ + height: 50px; + width: -moz-available; + border-radius: 6px; + font-size: 18px; + font-family: 'Inter', sans-serif; + border: none; + background-color: var(--circuitverse-primary-color); + color: #fff; + font-weight: 500; + cursor: pointer; +} + +.form_screen .circuitverse__embed_tool_container_body button:hover{ + /* translate the button up by 2px */ + transform: translateY(-2px); + /* add a slight shadow */ + box-shadow: 0 5px 10px rgba(0,0,0,0.2); + /* scale little bit */ + transform: scale(1.01); +} + +.form_screen .circuitverse__embed_tool_container_footer{ + font-family: 'Inter', sans-serif; + font-weight: 600; +} + +.form_screen .circuitverse__embed_tool_container_footer span{ + font-weight: normal; +} + +/* Message box */ +.circuitverse__embed_tool_container .msg_box{ + margin: 18px; + padding: 15px 20px; + border-radius: 6px; + font-family: 'Inter', sans-serif; + border: #D3D3D3 1px solid; + font-size: 14px; +} + +.circuitverse__embed_tool_container .msg_box.success{ + background-color: #f7f7f7; + color: var(--circuitverse-primary-color); + border-color: var(--circuitverse-primary-color); +} + +.circuitverse__embed_tool_container .msg_box.error{ + background-color: #f7f7f7; + color: var(--circuitverse-error-color); + border-color: var(--circuitverse-error-color); +} + diff --git a/Firefox Extension/views/browser_action.html b/Firefox Extension/views/browser_action.html deleted file mode 100644 index 8de5c45..0000000 --- a/Firefox Extension/views/browser_action.html +++ /dev/null @@ -1,22 +0,0 @@ - - - -
-

CircuitVerse Live Circuit!

-

- This extension will now load live circuits in Google Slides. Make sure to install Google Slides Add-On as well. For more details, read the user documentation here. -

-
\ No newline at end of file diff --git a/Firefox Extension/views/embedTool.html b/Firefox Extension/views/embedTool.html new file mode 100644 index 0000000..be43b63 --- /dev/null +++ b/Firefox Extension/views/embedTool.html @@ -0,0 +1,83 @@ +
+
+ +
+ +
+ +
+ CircuitVerse + embed circuit in slides +
+
+ +
+

Authorize Yourself
To Insert Circuit In Slide

+ +
+ +
+ + +
+ +
+ +
+ CircuitVerse + embed circuit in slides +
+
+ +
+
+
+
+ + +
+ +
+ +
+ CircuitVerse + embed circuit in slides +
+
+ +
+ + + + +
+ + + +
+
+ + +
+ +   +
+ CircuitVerse + embed circuit +
+
+ + +
+ + + +
+
\ No newline at end of file diff --git a/Firefox Extension/views/popup.html b/Firefox Extension/views/popup.html new file mode 100644 index 0000000..59091c6 --- /dev/null +++ b/Firefox Extension/views/popup.html @@ -0,0 +1,22 @@ + + + +
+

CircuitVerse Live Circuit!

+

+ This extension will now load live circuits in Google Slides. For more details, read the user documentation here. +

+
\ No newline at end of file