-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.js
2 lines (2 loc) · 25.8 KB
/
content.js
1
2
(()=>{"use strict";var t;!function(t){t.MANUAL="manual",t.TIMEOUT="timeout"}(t||(t={}));const e="timer_alert_time",i="timer_position",s=10,n=500,o=10,r={X_OFFSET:150,Y_OFFSET:10},a=1e4,l=18e5,c=1e3;var d=function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{l(s.next(t))}catch(t){o(t)}}function a(t){try{l(s.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,a)}l((s=s.apply(t,e||[])).next())}))};class u{static getSubmissionIdFromUrl(){const t=window.location.pathname.match(/\/submissions\/(\d+)/);return t?t[1]:null}static waitForSubmissionResult(){return d(this,arguments,void 0,(function*(t=3e4){const e=Date.now(),i=this.getSubmissionIdFromUrl();return i&&i!==this.lastSubmissionId?(this.lastSubmissionId=i,new Promise((e=>{this.checkSubmissionResult(e,t)}))):new Promise((i=>{const s=()=>{const n=this.getSubmissionIdFromUrl();n&&n!==this.lastSubmissionId?(this.lastSubmissionId=n,this.checkSubmissionResult(i,t-(Date.now()-e))):Date.now()-e<t?setTimeout(s,100):i({status:"Timeout - Result Unknown",details:""})};s()}))}))}static checkSubmissionResult(t,e){const i=Date.now(),s=()=>{var n,o;for(const e of this.RESULT_SELECTORS){const i=document.querySelectorAll(e);for(const e of i){const i=((null===(n=e.textContent)||void 0===n?void 0:n.trim())||"").match(/(Accepted|Runtime Error|Time Limit Exceeded|Compile Error|Wrong Answer)/i);if(i){const s=i[0];let n="";if("Wrong Answer"===s){const t=e.closest('div[class*="space-y-4"]');if(t){const e=t.querySelectorAll('div[class*="space-y-4"] > div:not(:first-child)');n=Array.from(e).map((t=>{var e;return null===(e=t.textContent)||void 0===e?void 0:e.trim()})).filter(Boolean).join(" | ")}}else{const t=e.nextElementSibling;t&&(n=(null===(o=t.textContent)||void 0===o?void 0:o.trim())||"")}return void t({status:s,details:n})}}}Date.now()-i<e?setTimeout(s,100):t({status:"Timeout - Result Unknown",details:""})};s()}static parseSubmissionDetails(t){const e=t.match(/(\d+)\s*ms/),i=t.match(/(\d+\.?\d*)\s*MB/);return{runtime:e?parseInt(e[1]):void 0,memory:i?1024*parseFloat(i[1]):void 0}}}u.RESULT_SELECTORS=['div[class*="flex items-center"] > div > span','div[class*="flex items-center justify-between"] > div > h3','div[class*="space-y-4"] > div[class*="flex items-center"] > div > span','[data-e2e-locator="submission-result"]','div[class*="space-y-4"] > div[class*="flex items-center"] > div','div[class*="space-y-4"] > div[class*="flex items-center justify-between gap-4"] > div > h3 > div[class*="sd-sm:block hidden"] > div'],u.lastSubmissionId=null;var h,m,g=function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{l(s.next(t))}catch(t){o(t)}}function a(t){try{l(s.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,a)}l((s=s.apply(t,e||[])).next())}))};class v{static getSubmissionIdFromUrl(){const t=window.location.pathname.match(/\/submissions\/(\d+)/);return t?t[1]:null}static waitForSubmissionResult(){return g(this,arguments,void 0,(function*(t=3e4){const e=Date.now(),i=this.getSubmissionIdFromUrl();return i&&i!==this.lastSubmissionId?(this.lastSubmissionId=i,new Promise((e=>{this.checkSubmissionResult(e,t)}))):new Promise((i=>{const s=()=>{const n=this.getSubmissionIdFromUrl();n&&n!==this.lastSubmissionId?(this.lastSubmissionId=n,this.checkSubmissionResult(i,t-(Date.now()-e))):Date.now()-e<t?setTimeout(s,100):i({status:"Timeout - Result Unknown",details:""})};s()}))}))}static checkSubmissionResult(t,e){const i=Date.now(),s=()=>{var n,o;for(const e of this.RESULT_SELECTORS){const i=document.querySelectorAll(e);for(const e of i){const i=(null===(n=e.textContent)||void 0===n?void 0:n.trim())||"",s=i.match(/(通过|解答错误|执行出错|超出时间限制|编译出错)/);if(s){const n={通过:"Accepted",解答错误:"Wrong Answer",执行出错:"Runtime Error",超出时间限制:"Time Limit Exceeded",编译出错:"Compile Error"}[s[0]];let r="";if("Accepted"===n){const t=i.match(/运行时间\s*(\d+)\s*ms/),e=i.match(/内存消耗\s*(\d+\.?\d*)\s*MB/);(t||e)&&(r=`Runtime: ${(null==t?void 0:t[1])||"0"}ms, Memory: ${(null==e?void 0:e[1])||"0"}MB`)}else if("Wrong Answer"===n){const t=e.closest('div[class*="space-y-4"]');if(t){const e=t.querySelectorAll('div[class*="space-y-4"] > div:not(:first-child)');r=Array.from(e).map((t=>{var e;return null===(e=t.textContent)||void 0===e?void 0:e.trim()})).filter(Boolean).join(" | ")}}else{const t=e.nextElementSibling;t&&(r=(null===(o=t.textContent)||void 0===o?void 0:o.trim())||"")}return void t({status:n,details:r})}}}Date.now()-i<e?setTimeout(s,100):t({status:"Timeout - Result Unknown",details:""})};s()}static parseSubmissionDetails(t){const e=t.match(/(?:Runtime|运行时间):\s*(\d+)ms/)||t.match(/(\d+)\s*ms/),i=t.match(/(?:Memory|内存消耗):\s*(\d+\.?\d*)MB/)||t.match(/(\d+\.?\d*)\s*MB/);return{runtime:e?parseInt(e[1]):void 0,memory:i?1024*parseFloat(i[1]):void 0}}}v.RESULT_SELECTORS=['div[class*="flex w-full items-center justify-between gap-4"] > div:first-child > span','div[class*="flex w-full items-center justify-between gap-4"] > div:first-child','div[class*="flex items-center"] > div > span','div[class*="flex items-center justify-between"] > div > h3'],v.lastSubmissionId=null;class S{constructor(t){this.logLevel="info",this.logCounter=0,this.lastResetTime=Date.now(),this.prefix=t}setLogLevel(t){this.logLevel=t}log(t,...e){this.logMessage("info",console.log,t,...e)}error(t,e){if(this.shouldLog("error")){let t;if(null==e)t="<no error details>";else if(e instanceof Error)t=`${e.message}\n${e.stack}`;else try{t=JSON.stringify(e)}catch(i){t=String(e)}}}debug(t,...e){this.logMessage("debug",console.debug,t,...e)}shouldLog(t){return S.LOG_LEVELS.indexOf(this.logLevel)<=S.LOG_LEVELS.indexOf(t)}warn(t,...e){this.logMessage("info",console.warn,t,...e)}info(t,...e){this.logMessage("info",console.info,t,...e)}logMessage(t,e,i,...s){this.shouldLog(t)&&!this.shouldThrottle()&&e(`${this.prefix} [${(new Date).toLocaleString()}]: ${i}`,...s)}shouldThrottle(){const t=Date.now();return t-this.lastResetTime>=S.THROTTLE_INTERVAL?(this.logCounter=0,this.lastResetTime=t,!1):(this.logCounter++,this.logCounter>S.MAX_LOGS_PER_INTERVAL)}}S.LOG_LEVELS=["debug","info","error"],S.THROTTLE_INTERVAL=1e3,S.MAX_LOGS_PER_INTERVAL=100;class f{constructor(){this.loggers=new Map,this.defaultPrefix="BBBunny",this.SEPARATOR=":"}static getInstance(){return f.instance||(f.instance=new f),f.instance}setDefaultPrefix(t){this.defaultPrefix=t}getLogger(t){const e=(Array.isArray(t)?t:[t]).join(this.SEPARATOR),i=`${this.defaultPrefix}${this.SEPARATOR}${e}`;return this.loggers.has(e)||this.loggers.set(e,new S(i)),this.loggers.get(e)}setGlobalLogLevel(t){this.loggers.forEach((e=>e.setLogLevel(t)))}}!function(t){t.SESSION_START="session:start",t.SESSION_END="session:end",t.SESSION_UPDATE="session:update",t.SESSION_LEAVE="session:leave",t.SESSION_RETURN="session:return",t.SESSION_UPDATE_ACTIVITY="session:update_activity",t.SUBMISSION_ADD="session:submission_add",t.DATA_PROBLEM_UPDATE="data:problem_update",t.DATA_CLEAR_ALL="data:clear_all",t.DATA_EXPORT="data:export",t.DATA_IMPORT="data:import",t.DATA_GET_STATS="data:get_stats",t.DATA_GET_SESSIONS="data:get_sessions",t.DATA_GET_PROBLEMS="data:get_problems",t.DATA_GET_SETTINGS="data:get_settings",t.DATA_UPDATE_SETTINGS="data:update_settings"}(h||(h={})),function(t){t.SESSION_INITIALIZE_ERROR="session:initialize_error",t.SESSION_LEAVE_ERROR="session:leave_error",t.SESSION_RETURN_ERROR="session:return_error",t.SESSION_UPDATE_ERROR="session:update_error",t.SESSION_CLOSE_ERROR="session:close_error",t.SESSION_NOT_FOUND="session:not_found",t.SUBMISSION_ADD_ERROR="submission:add_error",t.DATA_CLEAR_ERROR="data:clear_error",t.DATA_EXPORT_ERROR="data:export_error",t.DATA_IMPORT_ERROR="data:import_error",t.DATA_PROBLEM_UPDATE_ERROR="data:problem_update_error",t.DATA_SETTINGS_UPDATE_ERROR="data:settings_update_error",t.DATA_STATS_ERROR="data:stats_error",t.UNKNOWN_ERROR="error:unknown"}(m||(m={}));var T=function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{l(s.next(t))}catch(t){o(t)}}function a(t){try{l(s.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,a)}l((s=s.apply(t,e||[])).next())}))};class E{static wrap(t){return T(this,arguments,void 0,(function*(t,e=m.UNKNOWN_ERROR){try{const e=yield t();return this.response.success(e)}catch(t){return this.response.error(e,t instanceof Error?t.message:"Operation failed")}}))}}E.session={start:(t,e)=>({action:h.SESSION_START,payload:{problem:t,currentTime:e}}),end:(t,e,i)=>({action:h.SESSION_END,payload:{sessionId:t,endTime:e,endReason:i}}),update:(t,e)=>({action:h.SESSION_UPDATE,payload:{sessionId:t,updates:e}}),leave:(t,e)=>({action:h.SESSION_LEAVE,payload:{sessionId:t,leaveTime:e}}),return:(t,e)=>({action:h.SESSION_RETURN,payload:{sessionId:t,returnTime:e}}),updateActivity:(t,e)=>({action:h.SESSION_UPDATE_ACTIVITY,payload:{sessionId:t,activityTime:e}}),addSubmission:(t,e,i,s,n,o)=>({action:h.SUBMISSION_ADD,payload:{sessionId:t,code:e,language:i,status:s,runtime:n,errorMessage:o}})},E.data={export:(t,e)=>({action:h.DATA_EXPORT,payload:{reason:t,details:Object.assign({source:e.source,timestamp:Date.now()},e)}}),import:(t,e)=>({action:h.DATA_IMPORT,payload:{data:t,options:e}}),getStats:()=>({action:h.DATA_GET_STATS,payload:void 0}),getSessions:()=>({action:h.DATA_GET_SESSIONS,payload:void 0}),getProblems:t=>({action:h.DATA_GET_PROBLEMS,payload:{problemIds:t}}),updateProblem:t=>({action:h.DATA_PROBLEM_UPDATE,payload:{problem:t}})},E.settings={get:()=>({action:h.DATA_GET_SETTINGS,payload:void 0}),update:t=>({action:h.DATA_UPDATE_SETTINGS,payload:t})},E.response={success:t=>({success:!0,data:t}),error:(t,e)=>({success:!1,error:{code:t,message:e}}),unknown(t){return this.error(m.UNKNOWN_ERROR,t instanceof Error?t.message:"Unknown error occurred")}};var p=function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{l(s.next(t))}catch(t){o(t)}}function a(t){try{l(s.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,a)}l((s=s.apply(t,e||[])).next())}))};class y{constructor(){this.currentSessionId=null,this.problemInfo=null,this.activityTimer=null,this.activityStartTime=null,this.lastActivityTime=null,this.logger=f.getInstance().getLogger("SessionManager")}startTracking(t){return p(this,void 0,void 0,(function*(){this.problemInfo=t,yield this.initialize(),this.setupActivityTracking()}))}setupActivityTracking(){document.addEventListener("visibilitychange",(()=>{document.hidden?this.handlePageLeave():this.handlePageReturn()})),window.addEventListener("beforeunload",(()=>{this.closeSession(t.MANUAL)})),setInterval((()=>{this.currentSessionId&&null!==this.lastActivityTime&&Date.now()-this.lastActivityTime>l&&this.closeSession(t.TIMEOUT)}),c),this.startActivityTracking()}startActivityTracking(){null!==this.activityTimer&&window.clearInterval(this.activityTimer),this.activityTimer=window.setInterval((()=>{document.hidden||null!==this.activityStartTime||(this.activityStartTime=Date.now())}),c)}handlePageLeave(){return p(this,void 0,void 0,(function*(){if(this.logger.log("Page visibility changed: page leave detected"),null!==this.activityStartTime){if(yield this.updateSessionActivity(),this.currentSessionId)try{this.logger.log("Recording session leave for session:",this.currentSessionId);const t=E.session.leave(this.currentSessionId,Date.now());yield chrome.runtime.sendMessage(t)}catch(t){this.logger.error("Failed to record session leave:",t)}this.activityStartTime=null}}))}handlePageReturn(){return p(this,void 0,void 0,(function*(){if(this.logger.log("Page visibility changed: page return detected"),this.activityStartTime=Date.now(),this.currentSessionId)try{this.logger.log("Recording session return for session:",this.currentSessionId);const t=E.session.return(this.currentSessionId,Date.now());yield chrome.runtime.sendMessage(t)}catch(t){this.logger.error("Failed to record session return:",t)}}))}updateSessionActivity(){return p(this,void 0,void 0,(function*(){if(this.currentSessionId)try{const t=Date.now(),e=E.session.updateActivity(this.currentSessionId,t);this.logger.log("Updating session activity:",e),yield chrome.runtime.sendMessage(e),this.lastActivityTime=t}catch(t){this.logger.error("Failed to update session activity:",t)}}))}initialize(){return p(this,void 0,void 0,(function*(){try{if(!this.problemInfo)return void this.logger.error("No problem info available for session initialization",null);const t=E.session.start(this.problemInfo,Date.now());this.logger.log("Sending session initialize message",t);const e=yield chrome.runtime.sendMessage(t);e.success?(this.currentSessionId=e.data.sessionId,this.activityStartTime=Date.now(),this.lastActivityTime=Date.now(),this.logger.log(e.data.isNewSession?"Started new session:":"Resumed existing session:",this.currentSessionId)):this.logger.error("Failed to initialize session:",e.error)}catch(t){this.logger.error("Failed to initialize session:",t)}}))}getSubmissionHandler(){return"leetcode.cn"===window.location.hostname?v:u}handleSubmission(){return p(this,void 0,void 0,(function*(){if(this.currentSessionId)try{yield this.updateSessionActivity(),this.logger.log("Handling submission...");const t=this.getSubmissionHandler(),e=yield t.waitForSubmissionResult();this.logger.log("Submission result:",e);const i=E.session.addSubmission(this.currentSessionId,"123","unknown","Accepted"===e.status?"success":"failed","Accepted"===e.status&&e.details?t.parseSubmissionDetails(e.details).runtime:void 0,"Accepted"!==e.status?e.details:void 0);this.logger.log("Sending submission message:",i);const s=yield chrome.runtime.sendMessage(i);this.logger.log("Submission create response:",s)}catch(t){this.logger.error("Failed to handle submission:",t)}else this.logger.warn("No active session for submission")}))}closeSession(){return p(this,arguments,void 0,(function*(e=t.MANUAL){if(this.currentSessionId)try{const t=E.session.end(this.currentSessionId,Date.now(),e);yield chrome.runtime.sendMessage(t),this.currentSessionId=null,this.activityStartTime=null,null!==this.activityTimer&&(window.clearInterval(this.activityTimer),this.activityTimer=null)}catch(t){this.logger.error("Failed to close session:",t)}}))}}var A=function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{l(s.next(t))}catch(t){o(t)}}function a(t){try{l(s.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,a)}l((s=s.apply(t,e||[])).next())}))};class I{static normalizeDifficulty(t){return"简单"===t?"Easy":"中等"===t?"Medium":"困难"===t?"Hard":t}static getProblemInfo(){return A(this,void 0,void 0,(function*(){var t,e;this.logger.log("Attempting to extract problem info...");const i=document.querySelector(this.TITLE_SELECTOR),s=document.querySelector(this.DIFFICULTY_SELECTOR),n=window.location.pathname.split("/")[2];if(i&&s&&n){const o=(null===(t=i.textContent)||void 0===t?void 0:t.trim())||"",r=(null===(e=s.textContent)||void 0===e?void 0:e.trim())||"",a={id:n,title:o,difficulty:this.normalizeDifficulty(r)};return this.logger.log("Successfully extracted problem info:",a),a}return this.logger.log("Failed to extract problem info"),null}))}static retryGetProblemInfo(){return A(this,arguments,void 0,(function*(t=5,e=1e3){return new Promise(((i,s)=>{let n=0;const o=()=>A(this,void 0,void 0,(function*(){this.logger.log(`Attempt ${n+1}/${t} to get problem info`);const r=yield this.getProblemInfo();r?i(r):(n++,n<t?(this.logger.log(`Retrying in ${e}ms...`),setTimeout(o,e)):(this.logger.error("Max retries reached",new Error("Failed to retrieve problem info")),s(new Error("Failed to retrieve problem info"))))}));o()}))}))}}I.TITLE_SELECTOR='div[class*="flex items-start justify-between"] div[class*="flex items-start"] a',I.DIFFICULTY_SELECTOR='div[class*="bg-fill-secondary"][class*="text-difficulty"]',I.logger=f.getInstance().getLogger(["ContentScript","ProblemExtractor"]);var b=function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{l(s.next(t))}catch(t){o(t)}}function a(t){try{l(s.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,a)}l((s=s.apply(t,e||[])).next())}))};class _{static hasInstance(){return null!==_.instance}static getInstance(){return _.instance||(_.instance=new _),_.instance}constructor(){this.element=null,this.intervalId=null,this.isDragging=!1,this.currentX=0,this.currentY=0,this.initialX=0,this.initialY=0,this.STORAGE_KEY=i,this.ALERT_TIME_KEY=e,this.alertTimeInSeconds=null,this.hasAlerted=!1,this.logger=f.getInstance().getLogger(["ContentScript","Timer"]),this.handleDragStart=t=>{this.element&&(this.isDragging=!0,this.currentX=parseInt(this.element.style.left)||0,this.currentY=parseInt(this.element.style.top)||0,t instanceof MouseEvent?(this.initialX=t.clientX-this.currentX,this.initialY=t.clientY-this.currentY):(this.initialX=t.touches[0].clientX-this.currentX,this.initialY=t.touches[0].clientY-this.currentY),t.target===this.element&&(this.element.style.cursor="grabbing"))},this.handleDrag=t=>{var e,i;if(!this.isDragging)return;t.preventDefault(),t instanceof MouseEvent?(this.currentX=t.clientX-this.initialX,this.currentY=t.clientY-this.initialY):(this.currentX=t.touches[0].clientX-this.initialX,this.currentY=t.touches[0].clientY-this.initialY);const s=window.innerWidth-((null===(e=this.element)||void 0===e?void 0:e.offsetWidth)||0),n=window.innerHeight-((null===(i=this.element)||void 0===i?void 0:i.offsetHeight)||0);this.currentX=Math.min(Math.max(0,this.currentX),s),this.currentY=Math.min(Math.max(0,this.currentY),n),this.updatePosition()},this.handleDragEnd=()=>{this.isDragging=!1,this.element&&(this.element.style.cursor="move",this.savePosition())},this.logger.log("Timer instance created"),this.startTime=Date.now(),this.loadPosition(),this.loadAlertTime(),this.createTimerElement(),this.initDragEvents(),this.initWindowResizeHandler(),chrome.storage.onChanged.addListener(((t,e)=>{if("sync"===e&&t[this.ALERT_TIME_KEY]){const e=t[this.ALERT_TIME_KEY].newValue;this.alertTimeInSeconds=60*e,this.hasAlerted=!1}}))}loadPosition(){const t=localStorage.getItem(this.STORAGE_KEY);if(t){const{x:e,y:i}=JSON.parse(t);this.currentX=Math.min(e,window.innerWidth-150),this.currentY=Math.min(i,window.innerHeight-50)}else this.setDefaultPosition()}setDefaultPosition(){this.currentX=Math.max(window.innerWidth-r.X_OFFSET,0),this.currentY=r.Y_OFFSET}initWindowResizeHandler(){window.addEventListener("resize",(()=>{var t,e;const i=window.innerWidth-((null===(t=this.element)||void 0===t?void 0:t.offsetWidth)||0),s=window.innerHeight-((null===(e=this.element)||void 0===e?void 0:e.offsetHeight)||0);(this.currentX>i||this.currentY>s)&&(this.currentX=Math.min(this.currentX,i),this.currentY=Math.min(this.currentY,s),this.updatePosition(),this.savePosition())}))}savePosition(){localStorage.setItem(this.STORAGE_KEY,JSON.stringify({x:this.currentX,y:this.currentY}))}createTimerElement(){this.element=document.createElement("div"),this.element.textContent="00:00:00",this.element.style.cssText=`\n position: fixed;\n left: ${this.currentX}px;\n top: ${this.currentY}px;\n background-color: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 8px 12px;\n border-radius: 4px;\n font-family: monospace;\n font-size: 14px;\n z-index: 10000;\n cursor: move;\n user-select: none;\n touch-action: none;\n visibility: hidden;\n `,document.body.appendChild(this.element),requestAnimationFrame((()=>{this.element&&(this.element.style.visibility="visible")}))}initDragEvents(){this.element&&(this.element.addEventListener("mousedown",this.handleDragStart),document.addEventListener("mousemove",this.handleDrag),document.addEventListener("mouseup",this.handleDragEnd),this.element.addEventListener("touchstart",this.handleDragStart),document.addEventListener("touchmove",this.handleDrag),document.addEventListener("touchend",this.handleDragEnd))}updatePosition(){this.element&&(this.element.style.left=`${this.currentX}px`,this.element.style.top=`${this.currentY}px`)}start(){this.logger.log("Timer started"),this.startTime=Date.now(),this.intervalId=window.setInterval((()=>this.update()),1e3)}loadAlertTime(){return b(this,void 0,void 0,(function*(){const t=yield chrome.storage.sync.get(this.ALERT_TIME_KEY);t[this.ALERT_TIME_KEY]?(this.alertTimeInSeconds=60*t[this.ALERT_TIME_KEY],this.hasAlerted=!1):this.alertTimeInSeconds=60*s}))}setAlertTime(t){this.logger.log(`Setting alert time to ${t} seconds`),this.alertTimeInSeconds=t,this.hasAlerted=!1,chrome.storage.sync.set({[this.ALERT_TIME_KEY]:Math.floor(t/60)})}removeAlert(){this.alertTimeInSeconds=null,this.hasAlerted=!1,localStorage.removeItem(this.ALERT_TIME_KEY)}checkAndAlert(t){this.alertTimeInSeconds&&t>=this.alertTimeInSeconds&&!this.hasAlerted&&(this.showAlert(),this.hasAlerted=!0)}showAlert(){if(this.element){const t=this.element.style.backgroundColor,e=()=>{this.element&&(this.element.style.backgroundColor="rgba(255, 0, 0, 0.8)"===this.element.style.backgroundColor?t:"rgba(255, 0, 0, 0.8)")};let i=0;const s=setInterval((()=>{e(),i++,i>=o&&(clearInterval(s),this.element&&(this.element.style.backgroundColor=t))}),n)}}update(){if(!this.element)return;const t=Date.now()-this.startTime,e=Math.floor(t/1e3%60),i=Math.floor(t/6e4%60),s=Math.floor(t/36e5);this.element.textContent=`${s.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}:${e.toString().padStart(2,"0")}`;const n=e+60*i+3600*s;this.checkAndAlert(n)}destroy(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=null),this.element&&(this.element.removeEventListener("mousedown",this.handleDragStart),this.element.removeEventListener("touchstart",this.handleDragStart),document.removeEventListener("mousemove",this.handleDrag),document.removeEventListener("touchmove",this.handleDrag),document.removeEventListener("mouseup",this.handleDragEnd),document.removeEventListener("touchend",this.handleDragEnd),window.removeEventListener("resize",this.initWindowResizeHandler),this.element.parentNode&&this.element.parentNode.removeChild(this.element)),this.element=null,_.instance=null}}_.instance=null;const w={logger:{level:"info",defaultPrefix:"BBBunny"}};var R=function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{l(s.next(t))}catch(t){o(t)}}function a(t){try{l(s.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,a)}l((s=s.apply(t,e||[])).next())}))};class D{constructor(){this.sessionManager=null,this.initialized=!1,this.OBSERVER_TIMEOUT=a,this.observer=null,this.logger=f.getInstance().getLogger("ContentScript")}static getInstance(){return D.instance||(D.instance=new D),D.instance}start(){this.logger.log("Starting content script..."),this.initializeObserver()}checkAndInitialize(){this.initialized?this.logger.log("Already initialized, skipping..."):(this.logger.log("Starting initialization..."),this.initializeCore())}initializeCore(){return R(this,void 0,void 0,(function*(){try{yield this.waitForPageLoad();const t=yield this.extractProblemBrief();this.logger.log("Problem brief:",t);const e=yield this.extractProblemDetail(t);this.logger.log("Problem detail:",e),yield this.sendProblemToBackground(e),yield this.setupSessionManager(t),yield this.setupTimer(),this.setupSubmitButtonListener(),this.initialized=!0,this.logger.log("Initialization complete")}catch(t){this.logger.error("Failed to initialize content script",t)}}))}waitForPageLoad(){return R(this,void 0,void 0,(function*(){"complete"!==document.readyState&&(this.logger.log("Waiting for page to load..."),yield new Promise((t=>window.addEventListener("load",t))))}))}sendProblemToBackground(t){return R(this,void 0,void 0,(function*(){this.logger.debug("Sending problem to background...",t);try{yield chrome.runtime.sendMessage(E.data.updateProblem(t)),this.logger.debug("Problem sent successfully")}catch(t){throw this.logger.error("Failed to send problem to background:",t),t}}))}extractProblemBrief(){return R(this,void 0,void 0,(function*(){return this.logger.debug("Extracting basic problem info..."),yield I.retryGetProblemInfo()}))}setupSessionManager(t){return R(this,void 0,void 0,(function*(){this.logger.log("Setting up session manager..."),this.sessionManager=new y,yield this.sessionManager.startTracking(t),this.logger.log("SessionManager setup complete")}))}setupTimer(){return R(this,void 0,void 0,(function*(){if(this.logger.log("Setting up timer..."),_.hasInstance())this.logger.log("Timer already exists, skipping timer setup");else try{const t=_.getInstance();t.start();const i=(yield chrome.storage.sync.get(e))[e]||10;t.setAlertTime(60*i),this.logger.log("Timer setup complete")}catch(t){this.logger.error("Failed to initialize timer",t)}}))}setupSubmitButtonListener(){this.logger.log("Setting up submit button listener..."),document.addEventListener("click",(t=>R(this,void 0,void 0,(function*(){var e;const i=t.target;this.isSubmitButton(i)&&(this.logger.log("Submit button clicked"),yield null===(e=this.sessionManager)||void 0===e?void 0:e.handleSubmission())}))))}isSubmitButton(t){return["Submit","提交"].includes(t.textContent||"")}initializeObserver(){this.observer=new MutationObserver(((t,e)=>{document.querySelector('div[class*="flex items-start justify-between"]')&&(this.logger.log("Problem content detected"),e.disconnect(),this.checkAndInitialize())})),this.observer.observe(document.body,{childList:!0,subtree:!0})}extractProblemDetail(t){return R(this,void 0,void 0,(function*(){this.logger.debug("Extracting detailed problem info...");document.documentElement.lang;const e=this.containsChineseCharacters(t.title);return{id:t.id,titleEN:e?"":t.title,titleZH:e?t.title:"",difficulty:t.difficulty,lastUpdated:Date.now()}}))}containsChineseCharacters(t){return/[\u4e00-\u9fff\u3400-\u4dbf]/.test(t)}}f.getInstance().setGlobalLogLevel(w.logger.level),f.getInstance().setDefaultPrefix(w.logger.defaultPrefix);D.getInstance().start()})();
//# sourceMappingURL=content.js.map