diff --git a/.gitignore b/.gitignore index 2289371..df3226e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules/ /.vscode/ +/build/ package-lock.json \ No newline at end of file diff --git a/README.md b/README.md index ebc8c1b..e660f45 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,33 @@ -# README +# Vanita -> :warning: **NEVER DOWNLOAD OR RUN CODE THAT COMES FROM SOMEWHERE ELSE EVEN IF SOMETHING OR SOMEONE ARE CLAIMING THAT IT'S FROM THIS REPOSITORY. ONLY RUN THE CODE FROM THIS REPOSITORY, OR EVEN BETTER, BUILD IT YOURSELF. RUNNING CODE THAT YOU DO NOT UNDERSTAND ALWAYS COMES WITH RISK OF ACCOUNT THEFT AND OTHER MALICIOUS ACTIONS, BE CAREFUL!** +![extension method showcase gif](/extension/logo.png) -## About :placard: +## About -RWP stands for Roblox web panel, it's a code snippet that you can run via developer console or through the provided browser extension to try out early Roblox site features and get extended functionality without any programming experience. +Enhances the Roblox website experience with extra functionality. -## Usage :customs: +What are the main features? -Both methods work well, however, installing browser extension will be better on the long run. +- Save beyond the 50 outfits limit with outfits tab. -### Extension Method :electric_plug: +Why choose this over other Roblox extensions? -![extension method showcase gif](/examples/extension-method.gif) +- Open-source (MIT license). +- Roblox site stays vanilla by default, some features may allow you to modify certain parts of the site when enabled. +- No data collection. +- Free, but donations are appreciated. -1. Download this GitHub repository onto your computer. - -2. Extract the zip file. - -3. Go to [`chrome://extensions`](chrome://extensions). - -4. Enable "Developer mode" toggle. - -5. Click "Load unpacked" button. - -6. Select the [`extension`](extension) folder and click "Select Folder". - -7. Go to and click on the extension icon. - -8. Check "Injection Enabled" checkbox and refresh the page. - -### Console Method :computer: - -![extension method showcase gif](/examples/console-method.gif) - -1. Go to [`dist/release.js`](dist/release.js) - -2. Click "Raw". - -3. Select the entire page (Ctrl+A). - -4. Copy to clipboard (Ctrl+C). - -5. Go to . - -6. Open developer console either by pressing (F12) or by the opening context menu (Right Click) and clicking "Inspect". - -7. Click on the "Console" tab. - -8. Paste from clipboard (Ctrl+V) into the console and press (Enter). - -## Building :hammer: +## Building -If you don't trust the [`dist/release.js`](dist/release.js) file *(I dont blame you if you do)*, you can build it yourself. +If you don't trust the [`extension/embedded.js`](extension/embedded.js) file *(I dont blame you if you do)*, you can build it yourself. -### Requirements :passport_control: +### Requirements 1. Installed NodeJS runtime environment. 2. Installed NPM package manager. -### Instructions :notebook: +### Instructions 1. Download this GitHub repository onto your computer. @@ -70,8 +37,8 @@ If you don't trust the [`dist/release.js`](dist/release.js) file *(I dont blame 4. Run `npm install` to install dependencies that the project relies on and wait until it's done. -5. Run `npm run build` to build the [`dist/release.js`](dist/release.js) file and wait until it's done. +5. Run `npm run build` to build the [`extension/embedded.js`](extension/embedded.js) file and wait until it's done. -## Credits :medal_sports: +## Credits [@Julli4n](https://github.com/Julli4n) - [For discovering the API endpoint and documenting it](https://gist.github.com/Julli4n/13016b11e80109ba643ab9e90b431e02). diff --git a/dist/release.js b/dist/release.js deleted file mode 100644 index b82e178..0000000 --- a/dist/release.js +++ /dev/null @@ -1,8 +0,0 @@ -const container=document.createElement("div"),style=(container.id="app",document.body.appendChild(container),document.createElement("style"));style.textContent='@import"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200";.page.a1.a1{display:flex;flex-direction:column;gap:8px;padding:8px}.page.a1 .link.a1{color:#5e7af7}.page.a1 .link.a1:hover{text-decoration:underline}svg.a3{stroke:currentColor;fill:currentColor;stroke-width:0;width:100%;height:auto;max-height:100%}.info.a2.a2{padding:8px 8px 0;font-size:.9rem}.controls.a2.a2{display:flex;flex-direction:row;gap:8px;padding:8px}.controls.a2 .textfield.a2{padding:8px;background-color:#111212;color:#bdbebe;border:1px solid #414142;border-radius:8px;outline:none;font-size:1rem}.controls.a2 .textfield.a2:focus{border-color:#bdbebe}.controls.a2 .textfield.a2::placeholder{color:#919191}.controls.a2 .button.a2{padding:6px 12px;background-color:transparent;color:#bdbebe;border:1px solid #bdbebe;border-radius:8px;font-size:1rem}.controls.a2 .button.a2:hover{border-color:#e4e4e4;color:#e4e4e4}.outfits.a2.a2{overflow-y:auto;padding:8px;display:flex;flex-direction:row;flex-wrap:wrap;align-items:flex-start;flex-grow:1;gap:8px}.outfits.a2 .outfit.a2{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px}.outfits.a2 .outfit .preview.a2{position:relative}.outfits.a2 .outfit .preview .icon.a2{width:126px;height:126px;background-color:#2f3133;border-radius:8px;cursor:pointer;transition:background .3s linear}.outfits.a2 .outfit .preview .icon.a2:hover{background:radial-gradient(transparent,rgba(0,0,0,.2))}.outfits.a2 .outfit .preview .options.a2{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:5px;background-color:#000000bf;border-radius:8px}.outfits.a2 .outfit .preview .options .option.a2{padding:3px;border:1px solid transparent;border-radius:8px;width:100%;font-size:.8rem;cursor:pointer}.outfits.a2 .outfit .preview .options .option.a2:hover{border-color:#fff}.outfits.a2 .outfit .caption.a2{display:flex;flex-direction:row;align-items:center;gap:5px;width:100%}.outfits.a2 .outfit .caption .name.a2{font-size:1rem;flex-grow:1}.outfits.a2 .outfit .caption .edit.a2{width:18px;height:18px;color:#fff;cursor:pointer}.header.a0.a0{display:flex;flex-direction:row;align-items:center;background-color:#191b1d;border-bottom:1px solid #111214;border-top-left-radius:5px;border-top-right-radius:5px;font-size:1rem}.header.a0 .title.a0{padding:8px}.header.a0 .drag.a0{padding:8px;flex-grow:1;height:100%}.tabs.a0.a0{display:flex;flex-direction:row;align-items:center;background-color:#393b3d}.tabs.a0 .tab.a0{text-align:center;padding:6px 12px;font-size:1rem;cursor:pointer}.tabs.a0 .tab.a0:hover{background-color:#5e6165}#app *{box-sizing:border-box;font-family:HCo Gotham SSm,Helvetica Neue,Helvetica,Arial,Lucida Grande,"sans-serif"}#app{position:fixed;top:0;left:0;z-index:9999;display:flex;flex-direction:column;width:700px;height:500px;background:#232527;color:#fff;border:1px solid #111214;border-radius:5px}#app .material-symbols-outlined{font-variation-settings:"FILL" 0,"wght" 400,"GRAD" 0,"opsz" 48}',document.head.appendChild(style);(()=>{var Nt=Object.defineProperty,Dt=(t,e,n)=>e in t?Nt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,B=(t,e,n)=>(Dt(t,"symbol"!=typeof e?e+"":e,n),n);function R(){}function et(t,e){for(const n in e)t[n]=e[n];return t}function bt(t){return t()}function ut(){return Object.create(null)}function N(t){t.forEach(bt)}function kt(t){return"function"==typeof t}function J(t,e){return t!=t?e==e:t!==e||t&&"object"==typeof t||"function"==typeof t}!function(){var t=document.createElement("link").relList;if(!(t&&t.supports&&t.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))o(e);new MutationObserver(t=>{for(const e of t)if("childList"===e.type)for(const n of e.addedNodes)"LINK"===n.tagName&&"modulepreload"===n.rel&&o(n)}).observe(document,{childList:!0,subtree:!0})}function o(t){var e,n;t.ep||(t.ep=!0,n={},(e=t).integrity&&(n.integrity=e.integrity),e.referrerpolicy&&(n.referrerPolicy=e.referrerpolicy),"use-credentials"===e.crossorigin?n.credentials="include":"anonymous"===e.crossorigin?n.credentials="omit":n.credentials="same-origin",fetch(t.href,n))}}();let F;function ft(t,e){return(F=F||document.createElement("a")).href=e,t===F.href}function zt(t){return 0===Object.keys(t).length}function Rt(t,e,n,o){if(t)return e=$t(t,e,n,o),t[0](e)}function $t(t,e,n,o){return t[1]&&o?et(n.ctx.slice(),t[1](o(e))):n.ctx}function It(t,e,n,o){if(t[2]&&o){var r=t[2](o(n));if(void 0===e.dirty)return r;if("object"!=typeof r)return e.dirty|r;var a=[],i=Math.max(e.dirty.length,r.length);for(let t=0;tt.removeEventListener(e,n,o)}function b(t,e,n){null==n?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Gt(t){return Array.from(t.childNodes)}function At(t,e){t.wholeText!==(e=""+e)&&(t.data=e)}function pt(t,e){t.value=e??""}let q;function H(t){q=t}function qt(){if(q)return q;throw new Error("Function called outside component initialization")}function Ot(t){qt().$$.on_mount.push(t)}const Y=[],ht=[],V=[],mt=[],Jt=Promise.resolve();let it=!1;function Xt(){it||(it=!0,Jt.then(Ut))}function st(t){V.push(t)}const rt=new Set;let P=0;function Ut(){if(0===P){var t=q;do{try{for(;P{tt.delete(t),o&&(n&&t.d(1),o())}),t.o(e)):o&&o()}function Kt(t,e){var n={},o={},r={$$scope:1};let a=t.length;for(;a--;){var i=t[a],s=e[a];if(s){for(const c in i)c in s||(o[c]=1);for(const u in s)r[u]||(n[u]=s[u],r[u]=1);t[a]=s}else for(const l in i)r[l]=1}for(const f in o)f in n||(n[f]=void 0);return n}function Wt(t){return"object"==typeof t&&null!==t?t:{}}function ot(t){t&&t.c()}function X(e,t,n,o){var{fragment:r,after_update:a}=e.$$;r&&r.m(t,n),o||st(()=>{var t=e.$$.on_mount.map(bt).filter(kt);e.$$.on_destroy?e.$$.on_destroy.push(...t):N(t),e.$$.on_mount=[]}),a.forEach(st)}function Z(t,e){t=t.$$;null!==t.fragment&&(N(t.on_destroy),t.fragment&&t.fragment.d(e),t.on_destroy=t.fragment=null,t.ctx=[])}function Ft(t,e){-1===t.$$.dirty[0]&&(Y.push(t),Xt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{n=n.length?n[0]:e;return u.ctx&&r(u.ctx[t],u.ctx[t]=n)&&(!u.skip_bound&&u.bound[t]&&u.bound[t](n),l)&&Ft(o,t),e}):[],u.update(),l=!0,N(u.before_update),u.fragment=!!n&&n(u.ctx),t.target&&(t.hydrate?(a=Gt(t.target),u.fragment&&u.fragment.l(a),a.forEach(U)):u.fragment&&u.fragment.c(),t.intro&&M(o.$$.fragment),X(o,t.target,t.anchor,t.customElement),Ut()),H(c)}class W{$destroy(){Z(this,1),this.$destroy=R}$on(t,e){if(!kt(e))return R;const n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{var t=n.indexOf(e);-1!==t&&n.splice(t,1)}}$set(t){this.$$set&&!zt(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}class Qt{constructor(t){B(this,"pos1",0),B(this,"pos2",0),B(this,"pos3",0),B(this,"pos4",0),B(this,"target"),this.target=t}drag(t){this.dragMouseDown(t)}dragMouseDown(t){t.preventDefault();const e=this;this.pos3=t.clientX,this.pos4=t.clientY,document.onmouseup=()=>e.closeDragElement(),document.onmousemove=t=>{e.elementDrag(t)}}elementDrag(t){t.preventDefault(),this.pos1=this.pos3-t.clientX,this.pos2=this.pos4-t.clientY,this.pos3=t.clientX,this.pos4=t.clientY,this.target.style.top=this.target.offsetTop-this.pos2+"px",this.target.style.left=this.target.offsetLeft-this.pos1+"px"}closeDragElement(){document.onmouseup=null,document.onmousemove=null}}function Vt(t){let n;return{c(){(n=A("div")).innerHTML=`
Made with ❤️ by Daw588. - Available on GitHub - for free.
-
If you would like to support me, - you can donate - to keep me motivated! Donations go - towards improving this product by - putting food on my table :D
`,b(n,"class","page a1")},m(t,e){S(t,n,e)},p:R,i:R,o:R,d(t){t&&U(n)}}}class te extends W{constructor(t){super(),K(this,t,null,Vt,J,{})}}async function Bt(){return(await fetch("https://avatar.roblox.com/v1/avatar/thumbnail-customization",{method:"POST",headers:new Headers({"Content-Type":"application/json"}),credentials:"include"})).headers.get("x-csrf-token")}async function Q(t,e){return fetch(t,{method:"POST",headers:new Headers({"Content-Type":"application/json","x-csrf-token":await Bt()}),credentials:"include",body:e?JSON.stringify(e):null})}async function G(t){return fetch(t,{method:"GET",headers:new Headers({"Content-Type":"application/json","x-csrf-token":await Bt()}),credentials:"include"})}class lt{constructor(){B(this,"id"),B(this,"name"),B(this,"displayName")}static async getCurrentUser(){var t=await(await G("https://users.roblox.com/v1/users/authenticated")).json(),e=new lt;return e.id=t.id,e.name=t.name,e.displayName=t.displayName,e}}class j{constructor(){B(this,"id"),B(this,"thumbnailUrl"),B(this,"data"),B(this,"menuOpen",!1)}async wear(){this.id||console.error("Cannot wear an outfit without an outfit id!"),await Q(`https://avatar.roblox.com/v1/outfits/${this.id}/wear`)}async update(){this.id||console.error("Cannot update outfit without an outfit id!"),this.data||console.error("Cannot update outfit without data!"),await Q(`https://avatar.roblox.com/v1/outfits/${this.id}/update`,this.data)}async create(){this.data||console.error("Cannot create an outfit without data!"),await Q("https://avatar.roblox.com/v1/outfits/create",this.data)}async delete(){this.id||console.error("Cannot delete outfit without an outfit id!"),await Q(`https://avatar.roblox.com/v1/outfits/${this.id}/delete`),this.data=null}static async getOutfitsList(t){t=await(await G(`https://avatar.roblox.com/v1/users/${t}/outfits?page=1&itemsPerPage=100&isEditable=true`)).json();return console.log(t),t.data}static async getOutfitByName(t,e){var t=await j.getOutfitsList(t),t=(console.log(t),t.find(t=>t.name===e)),n=new j;return n.id=t.id,n}static async getOutfit(t){var t=(await G(`https://avatar.roblox.com/v1/outfits/${t}/details`)).json(),e=new j;return e.id=t.id,e.data={assetIds:t.assets.map(t=>t.id),bodyColors:t.bodyColors,name:t.name,outfitType:t.outfitType,playerAvatarType:t.playerAvatarType,scale:t.scale},e}static async getOutfitFromAvatar(){var t=await(await G("https://avatar.roblox.com/v1/avatar")).json(),e=new j;return e.data={name:"TEMPLATE",bodyColors:t.bodyColors,assetIds:t.assets.map(t=>t.id),scale:t.scales,playerAvatarType:t.playerAvatarType,outfitType:"Avatar"},e}}class _t{constructor(){}static async getAvatarBodyShot(t){return(await(await G("https://thumbnails.roblox.com/v1/users/avatar?"+new URLSearchParams({userIds:t.userId.toString(),size:t.size,format:t.format,isCircular:t.isCircular?"true":"false"}).toString())).json()).data[0].imageUrl}}var yt=function(){var g=String.fromCharCode,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",r={};function a(t,e){if(!r[t]){r[t]={};for(var n=0;n>>8,n[2*o+1]=a%256}return n},decompressFromUint8Array:function(t){if(null==t)return i.decompress(t);for(var e=new Array(t.length/2),n=0,o=e.length;n>=1}else{for(r=1,o=0;o>=1}0==--l&&(l=Math.pow(2,d),d++),delete c[u]}else for(r=s[u],o=0;o>=1;0==--l&&(l=Math.pow(2,d),d++),s[i]=f++,u=String(a)}if(""!==u){if(Object.prototype.hasOwnProperty.call(c,u)){if(u.charCodeAt(0)<256){for(o=0;o>=1}else{for(r=1,o=0;o>=1}0==--l&&(l=Math.pow(2,d),d++),delete c[u]}else for(r=s[u],o=0;o>=1;0==--l&&(l=Math.pow(2,d),d++)}for(r=2,o=0;o>=1;for(;;){if(h<<=1,m==e-1){p.push(n(h));break}m++}return p.join("")},decompress:function(e){return null==e?"":""==e?null:i._decompress(e.length,32768,function(t){return e.charCodeAt(t)})},_decompress:function(t,e,n){for(var o,r,a,i,s,c,u=[],l=4,f=4,d=3,p="",h=[],m={val:n(0),position:e,index:1},v=0;v<3;v+=1)u[v]=v;for(r=0,i=Math.pow(2,2),s=1;s!=i;)a=m.val&m.position,m.position>>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0{"title"in t&&n(0,a=t.title),"viewBox"in t&&n(1,i=t.viewBox),"$$scope"in t&&n(2,r=t.$$scope)},[a,i,r,o]}class oe extends W{constructor(t){super(),K(this,t,ne,ee,J,{title:0,viewBox:1})}}function re(t){let n;return{c(){b(n=at("path"),"d","M14 8.77v-1.6l-1.94-.64-.45-1.09.88-1.84-1.13-1.13-1.81.91-1.09-.45-.69-1.92h-1.6l-.63 1.94-1.11.45-1.84-.88-1.13 1.13.91 1.81-.45 1.09L0 7.23v1.59l1.94.64.45 1.09-.88 1.84 1.13 1.13 1.81-.91 1.09.45.69 1.92h1.59l.63-1.94 1.11-.45 1.84.88 1.13-1.13-.92-1.81.47-1.09L14 8.75v.02zM7 11c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z")},m(t,e){S(t,n,e)},p:R,d(t){t&&U(n)}}}function ie(t){let o,n;const r=[{viewBox:"0 0 14 16"},t[0]];let e={$$slots:{default:[re]},$$scope:{ctx:t}};for(let t=0;t{n(0,e=et(et({},e),dt(t)))},[e=dt(e)]}class ae extends W{constructor(t){super(),K(this,t,se,ie,J,{})}}function vt(t,e,n){t=t.slice();return t[18]=e[n],t}function gt(n){let o,r,a,i,s,c,u,l,f,d,p,h,m,v,g,w,y=(n[18].data?n[18].data.name:"Unknown")+"",x,k,C,B,_,j,T,P;function R(){return n[8](n[18])}function z(){return n[9](n[18])}function F(){return n[10](n[18])}function I(){return n[11](n[18])}function D(){return n[12](n[18])}return B=new ae({}),{c(){o=A("div"),r=A("div"),a=A("img"),c=E(),u=A("div"),(l=A("div")).textContent="Update",f=E(),(d=A("div")).textContent="Delete",p=E(),(h=A("div")).textContent="Cancel",v=E(),g=A("div"),w=A("div"),x=nt(y),k=E(),C=A("div"),ot(B.$$.fragment),_=E(),b(a,"class","icon a2"),b(a,"alt",i="Bodyshot of "+(n[18].data?n[18].data.name:"Unknown")),ft(a.src,s=n[18].thumbnailUrl||"#")||b(a,"src",s),b(l,"class","option a2"),b(d,"class","option a2"),b(h,"class","option a2"),b(u,"class","options a2"),b(u,"style",m=`display: ${n[18].menuOpen?"flex":"none"};`),b(r,"class","preview a2"),b(w,"class","name a2"),b(C,"class","edit a2"),b(g,"class","caption a2"),b(o,"class","outfit a2")},m(t,e){S(t,o,e),$(o,r),$(r,a),$(r,c),$(r,u),$(u,l),$(u,f),$(u,d),$(u,p),$(u,h),$(o,v),$(o,g),$(g,w),$(w,x),$(g,k),$(g,C),X(B,C,null),$(o,_),j=!0,T||(P=[O(a,"click",R),O(a,"keydown",ce),O(l,"click",z),O(l,"keydown",ue),O(d,"click",F),O(d,"keydown",fe),O(h,"click",I),O(h,"keydown",de),O(C,"click",D),O(C,"keydown",pe)],T=!0)},p(t,e){n=t,(!j||1&e&&i!==(i="Bodyshot of "+(n[18].data?n[18].data.name:"Unknown")))&&b(a,"alt",i),(!j||1&e&&!ft(a.src,s=n[18].thumbnailUrl||"#"))&&b(a,"src",s),(!j||1&e&&m!==(m=`display: ${n[18].menuOpen?"flex":"none"};`))&&b(u,"style",m),(!j||1&e)&&y!==(y=(n[18].data?n[18].data.name:"Unknown")+"")&&At(x,y)},i(t){j||(M(B.$$.fragment,t),j=!0)},o(t){L(B.$$.fragment,t),j=!1},d(t){t&&U(o),Z(B),T=!1,N(P)}}}function le(n){let o,r,a,i,s,c,u,l,f,d,p,h=n[0],m=[];for(let t=0;tL(m[t],1,1,()=>{m[t]=null}))(t);Tt()}},i(t){if(!f){for(let t=0;t{},ue=()=>{},fe=()=>{},de=()=>{},pe=()=>{};function he(e,t,o){let r=[],n="",a,i=!1;async function s(t){var e=t.data.name,n=(t.data.name="TEMPORARY",await t.create(),await j.getOutfitByName(a.id,"TEMPORARY"));await n.wear(),await n.delete(),t.data.name=e,window.location.reload()}function c(t){t.menuOpen=!t.menuOpen,o(0,r)}function u(t){c(t);t=r.indexOf(t);-1!==t&&(r.splice(t,1),o(0,r))}async function l(t){c(t);var e=await j.getOutfitFromAvatar(),n=(e.thumbnailUrl=await _t.getAvatarBodyShot({format:"Png",isCircular:!1,size:"100x100",userId:a.id}),t.data.name);t.thumbnailUrl=e.thumbnailUrl,t.data=e.data,t.data.name=n,o(0,r)}Ot(async()=>{var t;a=await lt.getCurrentUser(),t=localStorage.getItem("rwp-outfits"),i=(t&&(t=yt.decompress(t),t=JSON.parse(t),o(0,r=t.map(t=>{var e=new j;return e.thumbnailUrl=t.thumbnailUrl,e.data=t.data,e}))),!0)});return e.$$.update=()=>{var t;1&e.$$.dirty&&r&&i&&(t=r.map(t=>({data:t.data,thumbnailUrl:t.thumbnailUrl})),t=JSON.stringify(t),t=yt.compress(t),localStorage.setItem("rwp-outfits",t))},[r,n,async function(){var t=await j.getOutfitFromAvatar();t.data.name=""===n.trim()?"New outfit":n,o(1,n=""),t.thumbnailUrl=await _t.getAvatarBodyShot({format:"Png",isCircular:!1,size:"100x100",userId:a.id}),r.push(t),o(0,r)},s,c,u,l,function(){n=this.value,o(1,n)},t=>s(t),t=>l(t),t=>u(t),t=>c(t),t=>c(t)]}class me extends W{constructor(t){super(),K(this,t,he,le,J,{})}}function _e(t){let n,o;return n=new te({}),{c(){ot(n.$$.fragment)},m(t,e){X(n,t,e),o=!0},i(t){o||(M(n.$$.fragment,t),o=!0)},o(t){L(n.$$.fragment,t),o=!1},d(t){Z(n,t)}}}function ye(t){let n,o;return n=new me({}),{c(){ot(n.$$.fragment)},m(t,e){X(n,t,e),o=!0},i(t){o||(M(n.$$.fragment,t),o=!0)},o(t){L(n.$$.fragment,t),o=!1},d(t){Z(n,t)}}}function we(n){let o,r,a,i,s,c,u,l,f,d,p,h,m,v,g,w;const y=[ye,_e],x=[];function k(t){return"outfits"===t[1]?0:"about"===t[1]?1:-1}return~(p=k(n))&&(h=x[p]=y[p](n)),{c(){o=A("div"),(r=A("div")).textContent="RWP - Vanilla Roblox with extended functionality",a=E(),i=A("div"),s=E(),c=A("div"),(u=A("div")).textContent="Outfits",l=E(),(f=A("div")).textContent="About",d=E(),h&&h.c(),m=xt(),b(r,"class","title a0"),b(i,"class","drag a0"),b(o,"class","header a0"),b(u,"class","tab a0"),b(f,"class","tab a0"),b(c,"class","tabs a0")},m(t,e){S(t,o,e),$(o,r),$(o,a),$(o,i),S(t,s,e),S(t,c,e),$(c,u),$(c,l),$(c,f),S(t,d,e),~p&&x[p].m(t,e),S(t,m,e),v=!0,g||(w=[O(i,"mousedown",n[2]),O(u,"click",n[3]),O(u,"keydown",ve),O(f,"click",n[4]),O(f,"keydown",ge)],g=!0)},p(t,[]){let e=p;(p=k(t))!==e&&(h&&(St(),L(x[e],1,1,()=>{x[e]=null}),Tt()),~p?((h=x[p])||(h=x[p]=y[p](t)).c(),M(h,1),h.m(m.parentNode,m)):h=null)},i(t){v||(M(h),v=!0)},o(t){L(h),v=!1},d(t){t&&U(o),t&&U(s),t&&U(c),t&&U(d),~p&&x[p].d(t),t&&U(m),g=!1,N(w)}}}const ve=()=>{},ge=()=>{};function be(t,e,n){let o,r="outfits";return Ot(()=>{var t=document.getElementById("app");n(0,o=new Qt(t))}),[o,r,t=>o.drag(t),()=>n(1,r="outfits"),()=>n(1,r="about")]}class ke extends W{constructor(t){super(),K(this,t,be,we,J,{})}}new ke({target:document.getElementById("app")});})() \ No newline at end of file diff --git a/examples/console-method.gif b/examples/console-method.gif deleted file mode 100644 index 104d856..0000000 Binary files a/examples/console-method.gif and /dev/null differ diff --git a/examples/extension-method.gif b/examples/extension-method.gif deleted file mode 100644 index a6583c6..0000000 Binary files a/examples/extension-method.gif and /dev/null differ diff --git a/extension/background.js b/extension/background.js deleted file mode 100644 index 8c0a8b5..0000000 --- a/extension/background.js +++ /dev/null @@ -1,21 +0,0 @@ -chrome.tabs.onUpdated.addListener(async (tabId, info) => { - if (info.status !== "complete") { - return; - } - - const tab = await chrome.tabs.get(tabId); - if (!tab.url.includes("roblox.com")) { - return; - } - - chrome.storage.sync.get(["injectionEnabled"], data => { - if (data.injectionEnabled) { - chrome.scripting.executeScript({ - target: { - tabId: tab.id - }, - files: ["embedded.js"] - }); - } - }); -}); \ No newline at end of file diff --git a/extension/embedded.js b/extension/embedded.js index b82e178..c55f59d 100644 --- a/extension/embedded.js +++ b/extension/embedded.js @@ -1,8 +1,8 @@ -const container=document.createElement("div"),style=(container.id="app",document.body.appendChild(container),document.createElement("style"));style.textContent='@import"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200";.page.a1.a1{display:flex;flex-direction:column;gap:8px;padding:8px}.page.a1 .link.a1{color:#5e7af7}.page.a1 .link.a1:hover{text-decoration:underline}svg.a3{stroke:currentColor;fill:currentColor;stroke-width:0;width:100%;height:auto;max-height:100%}.info.a2.a2{padding:8px 8px 0;font-size:.9rem}.controls.a2.a2{display:flex;flex-direction:row;gap:8px;padding:8px}.controls.a2 .textfield.a2{padding:8px;background-color:#111212;color:#bdbebe;border:1px solid #414142;border-radius:8px;outline:none;font-size:1rem}.controls.a2 .textfield.a2:focus{border-color:#bdbebe}.controls.a2 .textfield.a2::placeholder{color:#919191}.controls.a2 .button.a2{padding:6px 12px;background-color:transparent;color:#bdbebe;border:1px solid #bdbebe;border-radius:8px;font-size:1rem}.controls.a2 .button.a2:hover{border-color:#e4e4e4;color:#e4e4e4}.outfits.a2.a2{overflow-y:auto;padding:8px;display:flex;flex-direction:row;flex-wrap:wrap;align-items:flex-start;flex-grow:1;gap:8px}.outfits.a2 .outfit.a2{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px}.outfits.a2 .outfit .preview.a2{position:relative}.outfits.a2 .outfit .preview .icon.a2{width:126px;height:126px;background-color:#2f3133;border-radius:8px;cursor:pointer;transition:background .3s linear}.outfits.a2 .outfit .preview .icon.a2:hover{background:radial-gradient(transparent,rgba(0,0,0,.2))}.outfits.a2 .outfit .preview .options.a2{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:5px;background-color:#000000bf;border-radius:8px}.outfits.a2 .outfit .preview .options .option.a2{padding:3px;border:1px solid transparent;border-radius:8px;width:100%;font-size:.8rem;cursor:pointer}.outfits.a2 .outfit .preview .options .option.a2:hover{border-color:#fff}.outfits.a2 .outfit .caption.a2{display:flex;flex-direction:row;align-items:center;gap:5px;width:100%}.outfits.a2 .outfit .caption .name.a2{font-size:1rem;flex-grow:1}.outfits.a2 .outfit .caption .edit.a2{width:18px;height:18px;color:#fff;cursor:pointer}.header.a0.a0{display:flex;flex-direction:row;align-items:center;background-color:#191b1d;border-bottom:1px solid #111214;border-top-left-radius:5px;border-top-right-radius:5px;font-size:1rem}.header.a0 .title.a0{padding:8px}.header.a0 .drag.a0{padding:8px;flex-grow:1;height:100%}.tabs.a0.a0{display:flex;flex-direction:row;align-items:center;background-color:#393b3d}.tabs.a0 .tab.a0{text-align:center;padding:6px 12px;font-size:1rem;cursor:pointer}.tabs.a0 .tab.a0:hover{background-color:#5e6165}#app *{box-sizing:border-box;font-family:HCo Gotham SSm,Helvetica Neue,Helvetica,Arial,Lucida Grande,"sans-serif"}#app{position:fixed;top:0;left:0;z-index:9999;display:flex;flex-direction:column;width:700px;height:500px;background:#232527;color:#fff;border:1px solid #111214;border-radius:5px}#app .material-symbols-outlined{font-variation-settings:"FILL" 0,"wght" 400,"GRAD" 0,"opsz" 48}',document.head.appendChild(style);(()=>{var Nt=Object.defineProperty,Dt=(t,e,n)=>e in t?Nt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,B=(t,e,n)=>(Dt(t,"symbol"!=typeof e?e+"":e,n),n);function R(){}function et(t,e){for(const n in e)t[n]=e[n];return t}function bt(t){return t()}function ut(){return Object.create(null)}function N(t){t.forEach(bt)}function kt(t){return"function"==typeof t}function J(t,e){return t!=t?e==e:t!==e||t&&"object"==typeof t||"function"==typeof t}!function(){var t=document.createElement("link").relList;if(!(t&&t.supports&&t.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))o(e);new MutationObserver(t=>{for(const e of t)if("childList"===e.type)for(const n of e.addedNodes)"LINK"===n.tagName&&"modulepreload"===n.rel&&o(n)}).observe(document,{childList:!0,subtree:!0})}function o(t){var e,n;t.ep||(t.ep=!0,n={},(e=t).integrity&&(n.integrity=e.integrity),e.referrerpolicy&&(n.referrerPolicy=e.referrerpolicy),"use-credentials"===e.crossorigin?n.credentials="include":"anonymous"===e.crossorigin?n.credentials="omit":n.credentials="same-origin",fetch(t.href,n))}}();let F;function ft(t,e){return(F=F||document.createElement("a")).href=e,t===F.href}function zt(t){return 0===Object.keys(t).length}function Rt(t,e,n,o){if(t)return e=$t(t,e,n,o),t[0](e)}function $t(t,e,n,o){return t[1]&&o?et(n.ctx.slice(),t[1](o(e))):n.ctx}function It(t,e,n,o){if(t[2]&&o){var r=t[2](o(n));if(void 0===e.dirty)return r;if("object"!=typeof r)return e.dirty|r;var a=[],i=Math.max(e.dirty.length,r.length);for(let t=0;tt.removeEventListener(e,n,o)}function b(t,e,n){null==n?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Gt(t){return Array.from(t.childNodes)}function At(t,e){t.wholeText!==(e=""+e)&&(t.data=e)}function pt(t,e){t.value=e??""}let q;function H(t){q=t}function qt(){if(q)return q;throw new Error("Function called outside component initialization")}function Ot(t){qt().$$.on_mount.push(t)}const Y=[],ht=[],V=[],mt=[],Jt=Promise.resolve();let it=!1;function Xt(){it||(it=!0,Jt.then(Ut))}function st(t){V.push(t)}const rt=new Set;let P=0;function Ut(){if(0===P){var t=q;do{try{for(;P{tt.delete(t),o&&(n&&t.d(1),o())}),t.o(e)):o&&o()}function Kt(t,e){var n={},o={},r={$$scope:1};let a=t.length;for(;a--;){var i=t[a],s=e[a];if(s){for(const c in i)c in s||(o[c]=1);for(const u in s)r[u]||(n[u]=s[u],r[u]=1);t[a]=s}else for(const l in i)r[l]=1}for(const f in o)f in n||(n[f]=void 0);return n}function Wt(t){return"object"==typeof t&&null!==t?t:{}}function ot(t){t&&t.c()}function X(e,t,n,o){var{fragment:r,after_update:a}=e.$$;r&&r.m(t,n),o||st(()=>{var t=e.$$.on_mount.map(bt).filter(kt);e.$$.on_destroy?e.$$.on_destroy.push(...t):N(t),e.$$.on_mount=[]}),a.forEach(st)}function Z(t,e){t=t.$$;null!==t.fragment&&(N(t.on_destroy),t.fragment&&t.fragment.d(e),t.on_destroy=t.fragment=null,t.ctx=[])}function Ft(t,e){-1===t.$$.dirty[0]&&(Y.push(t),Xt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{n=n.length?n[0]:e;return u.ctx&&r(u.ctx[t],u.ctx[t]=n)&&(!u.skip_bound&&u.bound[t]&&u.bound[t](n),l)&&Ft(o,t),e}):[],u.update(),l=!0,N(u.before_update),u.fragment=!!n&&n(u.ctx),t.target&&(t.hydrate?(a=Gt(t.target),u.fragment&&u.fragment.l(a),a.forEach(U)):u.fragment&&u.fragment.c(),t.intro&&M(o.$$.fragment),X(o,t.target,t.anchor,t.customElement),Ut()),H(c)}class W{$destroy(){Z(this,1),this.$destroy=R}$on(t,e){if(!kt(e))return R;const n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{var t=n.indexOf(e);-1!==t&&n.splice(t,1)}}$set(t){this.$$set&&!zt(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}class Qt{constructor(t){B(this,"pos1",0),B(this,"pos2",0),B(this,"pos3",0),B(this,"pos4",0),B(this,"target"),this.target=t}drag(t){this.dragMouseDown(t)}dragMouseDown(t){t.preventDefault();const e=this;this.pos3=t.clientX,this.pos4=t.clientY,document.onmouseup=()=>e.closeDragElement(),document.onmousemove=t=>{e.elementDrag(t)}}elementDrag(t){t.preventDefault(),this.pos1=this.pos3-t.clientX,this.pos2=this.pos4-t.clientY,this.pos3=t.clientX,this.pos4=t.clientY,this.target.style.top=this.target.offsetTop-this.pos2+"px",this.target.style.left=this.target.offsetLeft-this.pos1+"px"}closeDragElement(){document.onmouseup=null,document.onmousemove=null}}function Vt(t){let n;return{c(){(n=A("div")).innerHTML=`
Made with ❤️ by Daw588. - Available on GitHub +const container=document.createElement("div"),toggleBtn=(container.id="app",document.body.appendChild(container),document.createElement("div")),style=(toggleBtn.id="app-toggle",toggleBtn.textContent="Vanita",document.body.appendChild(toggleBtn),document.createElement("style"));style.textContent='@import"https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200";.page.a2.a2{display:flex;flex-direction:column;gap:8px;padding:8px}.page.a2 .link.a2{color:#5e7af7}.page.a2 .link.a2:hover{text-decoration:underline}svg.a1{stroke:currentColor;fill:currentColor;stroke-width:0;width:100%;height:auto;max-height:100%}.info.a3.a3{padding:8px 8px 0;font-size:.9rem}.controls.a3.a3{display:flex;flex-direction:row;gap:8px;padding:8px}.controls.a3 .textfield.a3{padding:8px;background-color:#111212;color:#bdbebe;border:1px solid #414142;border-radius:8px;outline:none;font-size:1rem}.controls.a3 .textfield.a3:focus{border-color:#bdbebe}.controls.a3 .textfield.a3::placeholder{color:#919191}.controls.a3 .button.a3{padding:6px 12px;background-color:transparent;color:#bdbebe;border:1px solid #bdbebe;border-radius:8px;font-size:1rem}.controls.a3 .button.a3:hover{border-color:#e4e4e4;color:#e4e4e4}.outfits.a3.a3{overflow-y:auto;padding:8px;display:flex;flex-direction:row;flex-wrap:wrap;align-items:flex-start;flex-grow:1;gap:8px}.outfits.a3 .outfit.a3{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:5px}.outfits.a3 .outfit .preview.a3{position:relative}.outfits.a3 .outfit .preview .icon.a3{width:126px;height:126px;background-color:#2f3133;border-radius:8px;cursor:pointer;transition:background .3s linear}.outfits.a3 .outfit .preview .icon.a3:hover{background:radial-gradient(transparent,rgba(0,0,0,.2))}.outfits.a3 .outfit .preview .options.a3{position:absolute;top:0;left:0;width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:5px;background-color:#000000bf;border-radius:8px}.outfits.a3 .outfit .preview .options .option.a3{padding:3px;border:1px solid transparent;border-radius:8px;width:100%;font-size:.8rem;cursor:pointer}.outfits.a3 .outfit .preview .options .option.a3:hover{border-color:#fff}.outfits.a3 .outfit .caption.a3{display:flex;flex-direction:row;align-items:center;gap:5px;width:100%}.outfits.a3 .outfit .caption .name.a3{font-size:1rem;flex-grow:1}.outfits.a3 .outfit .caption .edit.a3{width:18px;height:18px;color:#fff;cursor:pointer}.header.a0.a0{display:flex;flex-direction:row;align-items:center;background-color:#191b1d;border-bottom:1px solid #111214;border-top-left-radius:5px;border-top-right-radius:5px;font-size:1rem}.header.a0 .icon.a0{width:24px;height:24px;margin-left:6px;user-select:none}.header.a0 .title.a0{padding:8px}.header.a0 .drag.a0{padding:8px;flex-grow:1;height:100%}.header.a0 .close.a0{width:24px;height:24px;margin-right:6px;cursor:pointer}.header.a0 .close.a0,.header.a0 .close .a0{color:#fff}.tabs.a0.a0{display:flex;flex-direction:row;align-items:center;background-color:#393b3d}.tabs.a0 .tab.a0{text-align:center;padding:6px 12px;font-size:1rem;cursor:pointer}.tabs.a0 .tab.a0:hover{background-color:#5e6165}#app *{box-sizing:border-box;font-family:HCo Gotham SSm,Helvetica Neue,Helvetica,Arial,Lucida Grande,"sans-serif"}#app{position:fixed;top:0;left:0;z-index:9999;display:flex;flex-direction:column;width:700px;height:500px;background:#232527;color:#fff;border:1px solid #111214;border-radius:5px}#app-toggle{position:fixed;top:100%;left:100px;transform:translateY(-100%);z-index:9999;padding:6px 8px;cursor:pointer;background:#232527;color:#fff;border:1px solid #111214;border-bottom:none;border-top-left-radius:8px;border-top-right-radius:8px}#app .material-symbols-outlined{font-variation-settings:"FILL" 0,"wght" 400,"GRAD" 0,"opsz" 48}',document.head.appendChild(style);(()=>{var Mt=Object.defineProperty,St=(t,e,n)=>e in t?Mt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,L=(t,e,n)=>(St(t,"symbol"!=typeof e?e+"":e,n),n);function M(){}function z(t,e){for(const n in e)t[n]=e[n];return t}function $t(t){return t()}function pt(){return Object.create(null)}function S(t){t.forEach($t)}function Ct(t){return"function"==typeof t}function q(t,e){return t!=t?e==e:t!==e||t&&"object"==typeof t||"function"==typeof t}!function(){var t=document.createElement("link").relList;if(!(t&&t.supports&&t.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))a(e);new MutationObserver(t=>{for(const e of t)if("childList"===e.type)for(const n of e.addedNodes)"LINK"===n.tagName&&"modulepreload"===n.rel&&a(n)}).observe(document,{childList:!0,subtree:!0})}function a(t){var e,n;t.ep||(t.ep=!0,n={},(e=t).integrity&&(n.integrity=e.integrity),e.referrerpolicy&&(n.referrerPolicy=e.referrerpolicy),"use-credentials"===e.crossorigin?n.credentials="include":"anonymous"===e.crossorigin?n.credentials="omit":n.credentials="same-origin",fetch(t.href,n))}}();let ot;function ft(t,e){return(ot=ot||document.createElement("a")).href=e,t===ot.href}function Xt(t){return 0===Object.keys(t).length}function zt(t,e,n,a){if(t)return e=xt(t,e,n,a),t[0](e)}function xt(t,e,n,a){return t[1]&&a?z(n.ctx.slice(),t[1](a(e))):n.ctx}function Ft(t,e,n,a){if(t[2]&&a){var o=t[2](a(n));if(void 0===e.dirty)return o;if("object"!=typeof o)return e.dirty|o;var r=[],i=Math.max(e.dirty.length,o.length);for(let t=0;tt.removeEventListener(e,n,a)}function m(t,e,n){null==n?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function Ht(t){return Array.from(t.childNodes)}function Lt(t,e){t.wholeText!==(e=""+e)&&(t.data=e)}function _t(t,e){t.value=e??""}let nt;function tt(t){nt=t}function qt(){if(nt)return nt;throw new Error("Function called outside component initialization")}function Et(t){qt().$$.on_mount.push(t)}const H=[],gt=[],st=[],yt=[],Wt=Promise.resolve();let dt=!1;function Jt(){dt||(dt=!0,Wt.then(Ut))}function mt(t){st.push(t)}const ut=new Set;let G=0;function Ut(){if(0===G){var t=nt;do{try{for(;G{rt.delete(t),a&&(n&&t.d(1),a())}),t.o(e)):a&&a()}function Nt(t,e){var n={},a={},o={$$scope:1};let r=t.length;for(;r--;){var i=t[r],s=e[r];if(s){for(const l in i)l in s||(a[l]=1);for(const c in s)o[c]||(n[c]=s[c],o[c]=1);t[r]=s}else for(const u in i)o[u]=1}for(const d in a)d in n||(n[d]=void 0);return n}function Tt(t){return"object"==typeof t&&null!==t?t:{}}function W(t){t&&t.c()}function F(e,t,n,a){var{fragment:o,after_update:r}=e.$$;o&&o.m(t,n),a||mt(()=>{var t=e.$$.on_mount.map($t).filter(Ct);e.$$.on_destroy?e.$$.on_destroy.push(...t):S(t),e.$$.on_mount=[]}),r.forEach(mt)}function V(t,e){t=t.$$;null!==t.fragment&&(S(t.on_destroy),t.fragment&&t.fragment.d(e),t.on_destroy=t.fragment=null,t.ctx=[])}function Qt(t,e){-1===t.$$.dirty[0]&&(H.push(t),Jt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{n=n.length?n[0]:e;return c.ctx&&o(c.ctx[t],c.ctx[t]=n)&&(!c.skip_bound&&c.bound[t]&&c.bound[t](n),u)&&Qt(a,t),e}):[],c.update(),u=!0,S(c.before_update),c.fragment=!!n&&n(c.ctx),t.target&&(t.hydrate?(r=Ht(t.target),c.fragment&&c.fragment.l(r),r.forEach(O)):c.fragment&&c.fragment.c(),t.intro&&N(a.$$.fragment),F(a,t.target,t.anchor,t.customElement),Ut()),tt(l)}class K{$destroy(){V(this,1),this.$destroy=M}$on(t,e){if(!Ct(e))return M;const n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{var t=n.indexOf(e);-1!==t&&n.splice(t,1)}}$set(t){this.$$set&&!Xt(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}class Zt{constructor(t){L(this,"offX",0),L(this,"offY",0),L(this,"mouseX",0),L(this,"mouseY",0),L(this,"target"),L(this,"dragCompletedCallbacks",[]),this.target=t}drag(t){this.dragMouseDown(t)}dragMouseDown(t){t.preventDefault();const e=this;this.mouseX=t.clientX,this.mouseY=t.clientY,document.onmouseup=()=>e.closeDragElement(),document.onmousemove=t=>{e.elementDrag(t)}}elementDrag(t){t.preventDefault(),this.offX=this.mouseX-t.clientX,this.offY=this.mouseY-t.clientY,this.mouseX=t.clientX,this.mouseY=t.clientY,this.updateWindowPosition()}updateWindowPosition(){this.target.style.top=this.target.offsetTop-this.offY+"px",this.target.style.left=this.target.offsetLeft-this.offX+"px"}get targetX(){return parseFloat(this.target.style.left)}set targetX(t){this.target.style.left=t+"px"}get targetY(){return parseFloat(this.target.style.top)}set targetY(t){this.target.style.top=t+"px"}closeDragElement(){document.onmouseup=null,document.onmousemove=null,this.dragCompletedCallbacks.forEach(t=>t())}onDragCompleted(t){this.dragCompletedCallbacks.push(t)}}function te(t){let n;return{c(){(n=v("div")).innerHTML=`
Made with ❤️ by Daw588. + Available on GitHub for free.
If you would like to support me, - you can donate + you can donate to keep me motivated! Donations go towards improving this product by - putting food on my table :D
`,b(n,"class","page a1")},m(t,e){S(t,n,e)},p:R,i:R,o:R,d(t){t&&U(n)}}}class te extends W{constructor(t){super(),K(this,t,null,Vt,J,{})}}async function Bt(){return(await fetch("https://avatar.roblox.com/v1/avatar/thumbnail-customization",{method:"POST",headers:new Headers({"Content-Type":"application/json"}),credentials:"include"})).headers.get("x-csrf-token")}async function Q(t,e){return fetch(t,{method:"POST",headers:new Headers({"Content-Type":"application/json","x-csrf-token":await Bt()}),credentials:"include",body:e?JSON.stringify(e):null})}async function G(t){return fetch(t,{method:"GET",headers:new Headers({"Content-Type":"application/json","x-csrf-token":await Bt()}),credentials:"include"})}class lt{constructor(){B(this,"id"),B(this,"name"),B(this,"displayName")}static async getCurrentUser(){var t=await(await G("https://users.roblox.com/v1/users/authenticated")).json(),e=new lt;return e.id=t.id,e.name=t.name,e.displayName=t.displayName,e}}class j{constructor(){B(this,"id"),B(this,"thumbnailUrl"),B(this,"data"),B(this,"menuOpen",!1)}async wear(){this.id||console.error("Cannot wear an outfit without an outfit id!"),await Q(`https://avatar.roblox.com/v1/outfits/${this.id}/wear`)}async update(){this.id||console.error("Cannot update outfit without an outfit id!"),this.data||console.error("Cannot update outfit without data!"),await Q(`https://avatar.roblox.com/v1/outfits/${this.id}/update`,this.data)}async create(){this.data||console.error("Cannot create an outfit without data!"),await Q("https://avatar.roblox.com/v1/outfits/create",this.data)}async delete(){this.id||console.error("Cannot delete outfit without an outfit id!"),await Q(`https://avatar.roblox.com/v1/outfits/${this.id}/delete`),this.data=null}static async getOutfitsList(t){t=await(await G(`https://avatar.roblox.com/v1/users/${t}/outfits?page=1&itemsPerPage=100&isEditable=true`)).json();return console.log(t),t.data}static async getOutfitByName(t,e){var t=await j.getOutfitsList(t),t=(console.log(t),t.find(t=>t.name===e)),n=new j;return n.id=t.id,n}static async getOutfit(t){var t=(await G(`https://avatar.roblox.com/v1/outfits/${t}/details`)).json(),e=new j;return e.id=t.id,e.data={assetIds:t.assets.map(t=>t.id),bodyColors:t.bodyColors,name:t.name,outfitType:t.outfitType,playerAvatarType:t.playerAvatarType,scale:t.scale},e}static async getOutfitFromAvatar(){var t=await(await G("https://avatar.roblox.com/v1/avatar")).json(),e=new j;return e.data={name:"TEMPLATE",bodyColors:t.bodyColors,assetIds:t.assets.map(t=>t.id),scale:t.scales,playerAvatarType:t.playerAvatarType,outfitType:"Avatar"},e}}class _t{constructor(){}static async getAvatarBodyShot(t){return(await(await G("https://thumbnails.roblox.com/v1/users/avatar?"+new URLSearchParams({userIds:t.userId.toString(),size:t.size,format:t.format,isCircular:t.isCircular?"true":"false"}).toString())).json()).data[0].imageUrl}}var yt=function(){var g=String.fromCharCode,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",r={};function a(t,e){if(!r[t]){r[t]={};for(var n=0;n>>8,n[2*o+1]=a%256}return n},decompressFromUint8Array:function(t){if(null==t)return i.decompress(t);for(var e=new Array(t.length/2),n=0,o=e.length;n>=1}else{for(r=1,o=0;o>=1}0==--l&&(l=Math.pow(2,d),d++),delete c[u]}else for(r=s[u],o=0;o>=1;0==--l&&(l=Math.pow(2,d),d++),s[i]=f++,u=String(a)}if(""!==u){if(Object.prototype.hasOwnProperty.call(c,u)){if(u.charCodeAt(0)<256){for(o=0;o>=1}else{for(r=1,o=0;o>=1}0==--l&&(l=Math.pow(2,d),d++),delete c[u]}else for(r=s[u],o=0;o>=1;0==--l&&(l=Math.pow(2,d),d++)}for(r=2,o=0;o>=1;for(;;){if(h<<=1,m==e-1){p.push(n(h));break}m++}return p.join("")},decompress:function(e){return null==e?"":""==e?null:i._decompress(e.length,32768,function(t){return e.charCodeAt(t)})},_decompress:function(t,e,n){for(var o,r,a,i,s,c,u=[],l=4,f=4,d=3,p="",h=[],m={val:n(0),position:e,index:1},v=0;v<3;v+=1)u[v]=v;for(r=0,i=Math.pow(2,2),s=1;s!=i;)a=m.val&m.position,m.position>>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0>=1,0==m.position&&(m.position=e,m.val=n(m.index++)),r|=(0{"title"in t&&n(0,a=t.title),"viewBox"in t&&n(1,i=t.viewBox),"$$scope"in t&&n(2,r=t.$$scope)},[a,i,r,o]}class oe extends W{constructor(t){super(),K(this,t,ne,ee,J,{title:0,viewBox:1})}}function re(t){let n;return{c(){b(n=at("path"),"d","M14 8.77v-1.6l-1.94-.64-.45-1.09.88-1.84-1.13-1.13-1.81.91-1.09-.45-.69-1.92h-1.6l-.63 1.94-1.11.45-1.84-.88-1.13 1.13.91 1.81-.45 1.09L0 7.23v1.59l1.94.64.45 1.09-.88 1.84 1.13 1.13 1.81-.91 1.09.45.69 1.92h1.59l.63-1.94 1.11-.45 1.84.88 1.13-1.13-.92-1.81.47-1.09L14 8.75v.02zM7 11c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z")},m(t,e){S(t,n,e)},p:R,d(t){t&&U(n)}}}function ie(t){let o,n;const r=[{viewBox:"0 0 14 16"},t[0]];let e={$$slots:{default:[re]},$$scope:{ctx:t}};for(let t=0;t{n(0,e=et(et({},e),dt(t)))},[e=dt(e)]}class ae extends W{constructor(t){super(),K(this,t,se,ie,J,{})}}function vt(t,e,n){t=t.slice();return t[18]=e[n],t}function gt(n){let o,r,a,i,s,c,u,l,f,d,p,h,m,v,g,w,y=(n[18].data?n[18].data.name:"Unknown")+"",x,k,C,B,_,j,T,P;function R(){return n[8](n[18])}function z(){return n[9](n[18])}function F(){return n[10](n[18])}function I(){return n[11](n[18])}function D(){return n[12](n[18])}return B=new ae({}),{c(){o=A("div"),r=A("div"),a=A("img"),c=E(),u=A("div"),(l=A("div")).textContent="Update",f=E(),(d=A("div")).textContent="Delete",p=E(),(h=A("div")).textContent="Cancel",v=E(),g=A("div"),w=A("div"),x=nt(y),k=E(),C=A("div"),ot(B.$$.fragment),_=E(),b(a,"class","icon a2"),b(a,"alt",i="Bodyshot of "+(n[18].data?n[18].data.name:"Unknown")),ft(a.src,s=n[18].thumbnailUrl||"#")||b(a,"src",s),b(l,"class","option a2"),b(d,"class","option a2"),b(h,"class","option a2"),b(u,"class","options a2"),b(u,"style",m=`display: ${n[18].menuOpen?"flex":"none"};`),b(r,"class","preview a2"),b(w,"class","name a2"),b(C,"class","edit a2"),b(g,"class","caption a2"),b(o,"class","outfit a2")},m(t,e){S(t,o,e),$(o,r),$(r,a),$(r,c),$(r,u),$(u,l),$(u,f),$(u,d),$(u,p),$(u,h),$(o,v),$(o,g),$(g,w),$(w,x),$(g,k),$(g,C),X(B,C,null),$(o,_),j=!0,T||(P=[O(a,"click",R),O(a,"keydown",ce),O(l,"click",z),O(l,"keydown",ue),O(d,"click",F),O(d,"keydown",fe),O(h,"click",I),O(h,"keydown",de),O(C,"click",D),O(C,"keydown",pe)],T=!0)},p(t,e){n=t,(!j||1&e&&i!==(i="Bodyshot of "+(n[18].data?n[18].data.name:"Unknown")))&&b(a,"alt",i),(!j||1&e&&!ft(a.src,s=n[18].thumbnailUrl||"#"))&&b(a,"src",s),(!j||1&e&&m!==(m=`display: ${n[18].menuOpen?"flex":"none"};`))&&b(u,"style",m),(!j||1&e)&&y!==(y=(n[18].data?n[18].data.name:"Unknown")+"")&&At(x,y)},i(t){j||(M(B.$$.fragment,t),j=!0)},o(t){L(B.$$.fragment,t),j=!1},d(t){t&&U(o),Z(B),T=!1,N(P)}}}function le(n){let o,r,a,i,s,c,u,l,f,d,p,h=n[0],m=[];for(let t=0;tL(m[t],1,1,()=>{m[t]=null}))(t);Tt()}},i(t){if(!f){for(let t=0;t{},ue=()=>{},fe=()=>{},de=()=>{},pe=()=>{};function he(e,t,o){let r=[],n="",a,i=!1;async function s(t){var e=t.data.name,n=(t.data.name="TEMPORARY",await t.create(),await j.getOutfitByName(a.id,"TEMPORARY"));await n.wear(),await n.delete(),t.data.name=e,window.location.reload()}function c(t){t.menuOpen=!t.menuOpen,o(0,r)}function u(t){c(t);t=r.indexOf(t);-1!==t&&(r.splice(t,1),o(0,r))}async function l(t){c(t);var e=await j.getOutfitFromAvatar(),n=(e.thumbnailUrl=await _t.getAvatarBodyShot({format:"Png",isCircular:!1,size:"100x100",userId:a.id}),t.data.name);t.thumbnailUrl=e.thumbnailUrl,t.data=e.data,t.data.name=n,o(0,r)}Ot(async()=>{var t;a=await lt.getCurrentUser(),t=localStorage.getItem("rwp-outfits"),i=(t&&(t=yt.decompress(t),t=JSON.parse(t),o(0,r=t.map(t=>{var e=new j;return e.thumbnailUrl=t.thumbnailUrl,e.data=t.data,e}))),!0)});return e.$$.update=()=>{var t;1&e.$$.dirty&&r&&i&&(t=r.map(t=>({data:t.data,thumbnailUrl:t.thumbnailUrl})),t=JSON.stringify(t),t=yt.compress(t),localStorage.setItem("rwp-outfits",t))},[r,n,async function(){var t=await j.getOutfitFromAvatar();t.data.name=""===n.trim()?"New outfit":n,o(1,n=""),t.thumbnailUrl=await _t.getAvatarBodyShot({format:"Png",isCircular:!1,size:"100x100",userId:a.id}),r.push(t),o(0,r)},s,c,u,l,function(){n=this.value,o(1,n)},t=>s(t),t=>l(t),t=>u(t),t=>c(t),t=>c(t)]}class me extends W{constructor(t){super(),K(this,t,he,le,J,{})}}function _e(t){let n,o;return n=new te({}),{c(){ot(n.$$.fragment)},m(t,e){X(n,t,e),o=!0},i(t){o||(M(n.$$.fragment,t),o=!0)},o(t){L(n.$$.fragment,t),o=!1},d(t){Z(n,t)}}}function ye(t){let n,o;return n=new me({}),{c(){ot(n.$$.fragment)},m(t,e){X(n,t,e),o=!0},i(t){o||(M(n.$$.fragment,t),o=!0)},o(t){L(n.$$.fragment,t),o=!1},d(t){Z(n,t)}}}function we(n){let o,r,a,i,s,c,u,l,f,d,p,h,m,v,g,w;const y=[ye,_e],x=[];function k(t){return"outfits"===t[1]?0:"about"===t[1]?1:-1}return~(p=k(n))&&(h=x[p]=y[p](n)),{c(){o=A("div"),(r=A("div")).textContent="RWP - Vanilla Roblox with extended functionality",a=E(),i=A("div"),s=E(),c=A("div"),(u=A("div")).textContent="Outfits",l=E(),(f=A("div")).textContent="About",d=E(),h&&h.c(),m=xt(),b(r,"class","title a0"),b(i,"class","drag a0"),b(o,"class","header a0"),b(u,"class","tab a0"),b(f,"class","tab a0"),b(c,"class","tabs a0")},m(t,e){S(t,o,e),$(o,r),$(o,a),$(o,i),S(t,s,e),S(t,c,e),$(c,u),$(c,l),$(c,f),S(t,d,e),~p&&x[p].m(t,e),S(t,m,e),v=!0,g||(w=[O(i,"mousedown",n[2]),O(u,"click",n[3]),O(u,"keydown",ve),O(f,"click",n[4]),O(f,"keydown",ge)],g=!0)},p(t,[]){let e=p;(p=k(t))!==e&&(h&&(St(),L(x[e],1,1,()=>{x[e]=null}),Tt()),~p?((h=x[p])||(h=x[p]=y[p](t)).c(),M(h,1),h.m(m.parentNode,m)):h=null)},i(t){v||(M(h),v=!0)},o(t){L(h),v=!1},d(t){t&&U(o),t&&U(s),t&&U(c),t&&U(d),~p&&x[p].d(t),t&&U(m),g=!1,N(w)}}}const ve=()=>{},ge=()=>{};function be(t,e,n){let o,r="outfits";return Ot(()=>{var t=document.getElementById("app");n(0,o=new Qt(t))}),[o,r,t=>o.drag(t),()=>n(1,r="outfits"),()=>n(1,r="about")]}class ke extends W{constructor(t){super(),K(this,t,be,we,J,{})}}new ke({target:document.getElementById("app")});})() \ No newline at end of file + putting food on my table :D
`,m(n,"class","page a2")},m(t,e){E(t,n,e)},p:M,i:M,o:M,d(t){t&&O(n)}}}class ee extends K{constructor(t){super(),J(this,t,null,te,q,{})}}async function Yt(){return(await fetch("https://avatar.roblox.com/v1/avatar/thumbnail-customization",{method:"POST",headers:new Headers({"Content-Type":"application/json"}),credentials:"include"})).headers.get("x-csrf-token")}async function at(t,e){return fetch(t,{method:"POST",headers:new Headers({"Content-Type":"application/json","x-csrf-token":await Yt()}),credentials:"include",body:e?JSON.stringify(e):null})}async function et(t){return fetch(t,{method:"GET",headers:new Headers({"Content-Type":"application/json","x-csrf-token":await Yt()}),credentials:"include"})}class ht{constructor(){L(this,"id"),L(this,"name"),L(this,"displayName")}static async getCurrentUser(){var t=await(await et("https://users.roblox.com/v1/users/authenticated")).json(),e=new ht;return e.id=t.id,e.name=t.name,e.displayName=t.displayName,e}}class j{constructor(){L(this,"id"),L(this,"thumbnailUrl"),L(this,"data"),L(this,"menuOpen",!1)}async wear(){this.id||console.error("Cannot wear an outfit without an outfit id!"),await at(`https://avatar.roblox.com/v1/outfits/${this.id}/wear`)}async update(){this.id||console.error("Cannot update outfit without an outfit id!"),this.data||console.error("Cannot update outfit without data!"),await at(`https://avatar.roblox.com/v1/outfits/${this.id}/update`,this.data)}async create(){this.data||console.error("Cannot create an outfit without data!"),await at("https://avatar.roblox.com/v1/outfits/create",this.data)}async delete(){this.id||console.error("Cannot delete outfit without an outfit id!"),await at(`https://avatar.roblox.com/v1/outfits/${this.id}/delete`),this.data=null}static async getOutfitsList(t){t=await(await et(`https://avatar.roblox.com/v1/users/${t}/outfits?page=1&itemsPerPage=100&isEditable=true`)).json();return console.log(t),t.data}static async getOutfitByName(t,e){var t=await j.getOutfitsList(t),t=(console.log(t),t.find(t=>t.name===e)),n=new j;return n.id=t.id,n}static async getOutfit(t){var t=(await et(`https://avatar.roblox.com/v1/outfits/${t}/details`)).json(),e=new j;return e.id=t.id,e.data={assetIds:t.assets.map(t=>t.id),bodyColors:t.bodyColors,name:t.name,outfitType:t.outfitType,playerAvatarType:t.playerAvatarType,scale:t.scale},e}static async getOutfitFromAvatar(){var t=await(await et("https://avatar.roblox.com/v1/avatar")).json(),e=new j;return e.data={name:"TEMPLATE",bodyColors:t.bodyColors,assetIds:t.assets.map(t=>t.id),scale:t.scales,playerAvatarType:t.playerAvatarType,outfitType:"Avatar"},e}}class wt{constructor(){}static async getAvatarBodyShot(t){return(await(await et("https://thumbnails.roblox.com/v1/users/avatar?"+new URLSearchParams({userIds:t.userId.toString(),size:t.size,format:t.format,isCircular:t.isCircular?"true":"false"}).toString())).json()).data[0].imageUrl}}function vt(t){let n,a;return{c(){n=lt("title"),a=ct(t[0])},m(t,e){E(t,n,e),_(n,a)},p(t,e){1&e&&Lt(a,t[0])},d(t){t&&O(n)}}}function ne(t){let n,a,o,r=t[0]&&vt(t);const i=t[3].default,s=zt(i,t,t[2],null);return{c(){n=lt("svg"),r&&r.c(),a=Ot(),s&&s.c(),m(n,"xmlns","http://www.w3.org/2000/svg"),m(n,"viewBox",t[1]),m(n,"class","a1")},m(t,e){E(t,n,e),r&&r.m(n,null),_(n,a),s&&s.m(n,null),o=!0},p(t,[e]){t[0]?r?r.p(t,e):((r=vt(t)).c(),r.m(n,a)):r&&(r.d(1),r=null),s&&s.p&&(!o||4&e)&&Vt(s,i,t,t[2],o?Ft(i,t[2],e,null):Rt(t[2]),null),(!o||2&e)&&m(n,"viewBox",t[1])},i(t){o||(N(s,t),o=!0)},o(t){Y(s,t),o=!1},d(t){t&&O(n),r&&r.d(),s&&s.d(t)}}}function oe(t,e,n){let{$$slots:a={},$$scope:o}=e,{title:r=null}=e,i=e["viewBox"];return t.$$set=t=>{"title"in t&&n(0,r=t.title),"viewBox"in t&&n(1,i=t.viewBox),"$$scope"in t&&n(2,o=t.$$scope)},[r,i,o,a]}class Dt extends K{constructor(t){super(),J(this,t,oe,ne,q,{title:0,viewBox:1})}}function ae(t){let n;return{c(){m(n=lt("path"),"d","M14 8.77v-1.6l-1.94-.64-.45-1.09.88-1.84-1.13-1.13-1.81.91-1.09-.45-.69-1.92h-1.6l-.63 1.94-1.11.45-1.84-.88-1.13 1.13.91 1.81-.45 1.09L0 7.23v1.59l1.94.64.45 1.09-.88 1.84 1.13 1.13 1.81-.91 1.09.45.69 1.92h1.59l.63-1.94 1.11-.45 1.84.88 1.13-1.13-.92-1.81.47-1.09L14 8.75v.02zM7 11c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3z")},m(t,e){E(t,n,e)},p:M,d(t){t&&O(n)}}}function se(t){let a,n;const o=[{viewBox:"0 0 14 16"},t[0]];let e={$$slots:{default:[ae]},$$scope:{ctx:t}};for(let t=0;t{n(0,e=z(z({},e),it(t)))},[e=it(e)]}class ie extends K{constructor(t){super(),J(this,t,re,se,q,{})}}class It{constructor(t,e){L(this,"key"),L(this,"defaultValue"),this.key=t,this.defaultValue=e}async save(t){var e={};e[this.key]=t,await chrome.storage.sync.set(e)}async load(){return(await chrome.storage.sync.get([this.key]))[this.key]||this.defaultValue}}function bt(t,e,n){t=t.slice();return t[18]=e[n],t}function kt(n){let a,o,r,i,s,l,c,u,d,f,p,h,g,y,$,w,b=(n[18].data?n[18].data.name:"Unknown")+"",k,C,L,A,B,M,T,X;function j(){return n[8](n[18])}function z(){return n[9](n[18])}function D(){return n[10](n[18])}function I(){return n[11](n[18])}function P(){return n[12](n[18])}return A=new ie({}),{c(){a=v("div"),o=v("div"),r=v("img"),l=U(),c=v("div"),(u=v("div")).textContent="Update",d=U(),(f=v("div")).textContent="Delete",p=U(),(h=v("div")).textContent="Cancel",y=U(),$=v("div"),w=v("div"),k=ct(b),C=U(),L=v("div"),W(A.$$.fragment),B=U(),m(r,"class","icon a3"),m(r,"alt",i="Bodyshot of "+(n[18].data?n[18].data.name:"Unknown")),ft(r.src,s=n[18].thumbnailUrl||"#")||m(r,"src",s),m(u,"class","option a3"),m(f,"class","option a3"),m(h,"class","option a3"),m(c,"class","options a3"),m(c,"style",g=`display: ${n[18].menuOpen?"flex":"none"};`),m(o,"class","preview a3"),m(w,"class","name a3"),m(L,"class","edit a3"),m($,"class","caption a3"),m(a,"class","outfit a3")},m(t,e){E(t,a,e),_(a,o),_(o,r),_(o,l),_(o,c),_(c,u),_(c,d),_(c,f),_(c,p),_(c,h),_(a,y),_(a,$),_($,w),_(w,k),_($,C),_($,L),F(A,L,null),_(a,B),M=!0,T||(X=[x(r,"click",j),x(r,"keydown",ce),x(u,"click",z),x(u,"keydown",ue),x(f,"click",D),x(f,"keydown",fe),x(h,"click",I),x(h,"keydown",de),x(L,"click",P),x(L,"keydown",me)],T=!0)},p(t,e){n=t,(!M||1&e&&i!==(i="Bodyshot of "+(n[18].data?n[18].data.name:"Unknown")))&&m(r,"alt",i),(!M||1&e&&!ft(r.src,s=n[18].thumbnailUrl||"#"))&&m(r,"src",s),(!M||1&e&&g!==(g=`display: ${n[18].menuOpen?"flex":"none"};`))&&m(c,"style",g),(!M||1&e)&&b!==(b=(n[18].data?n[18].data.name:"Unknown")+"")&&Lt(k,b)},i(t){M||(N(A.$$.fragment,t),M=!0)},o(t){Y(A.$$.fragment,t),M=!1},d(t){t&&O(a),V(A),T=!1,S(X)}}}function le(n){let a,o,r,i,s,l,c,u,d,f,p,h=n[0],g=[];for(let t=0;tY(g[t],1,1,()=>{g[t]=null}))(t);Bt()}},i(t){if(!d){for(let t=0;t{},ue=()=>{},fe=()=>{},de=()=>{},me=()=>{};function he(t,e,a){let o=[],n="",r,i=!1;const s=new It("outfit-list",[]);async function l(t){var e=t.data.name,n=(t.data.name="TEMPORARY",await t.create(),await j.getOutfitByName(r.id,"TEMPORARY"));await n.wear(),await n.delete(),t.data.name=e,window.location.reload()}function c(t){t.menuOpen=!t.menuOpen,a(0,o)}function u(t){c(t);t=o.indexOf(t);-1!==t&&(o.splice(t,1),a(0,o))}async function d(t){c(t);var e=await j.getOutfitFromAvatar(),n=(e.thumbnailUrl=await wt.getAvatarBodyShot({format:"Png",isCircular:!1,size:"100x100",userId:r.id}),t.data.name);t.thumbnailUrl=e.thumbnailUrl,t.data=e.data,t.data.name=n,a(0,o)}Et(async()=>{r=await ht.getCurrentUser(),async function(){var t=await s.load();a(0,o=t.map(t=>{var e=new j;return e.thumbnailUrl=t.thumbnailUrl,e.data=t.data,e})),i=!0}()});return t.$$.update=()=>{1&t.$$.dirty&&o&&async function(){var t;i&&(t=o.map(t=>({data:t.data,thumbnailUrl:t.thumbnailUrl})),await s.save(t))}()},[o,n,async function(){var t=await j.getOutfitFromAvatar();t.data.name=""===n.trim()?"New outfit":n,a(1,n=""),t.thumbnailUrl=await wt.getAvatarBodyShot({format:"Png",isCircular:!1,size:"100x100",userId:r.id}),o.push(t),a(0,o)},l,c,u,d,function(){n=this.value,a(1,n)},t=>l(t),t=>d(t),t=>u(t),t=>c(t),t=>c(t)]}class pe extends K{constructor(t){super(),J(this,t,he,le,q,{})}}function _e(t){let n;return{c(){m(n=lt("path"),"d","M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z")},m(t,e){E(t,n,e)},p:M,d(t){t&&O(n)}}}function ge(t){let a,n;const o=[{viewBox:"0 0 12 16"},t[0]];let e={$$slots:{default:[_e]},$$scope:{ctx:t}};for(let t=0;t{n(0,e=z(z({},e),it(t)))},[e=it(e)]}class we extends K{constructor(t){super(),J(this,t,ye,ge,q,{})}}class ve{constructor(){}static getAssetUrl(t){return chrome.runtime.getURL(t)}}function be(t){let n,a;return n=new ee({}),{c(){W(n.$$.fragment)},m(t,e){F(n,t,e),a=!0},i(t){a||(N(n.$$.fragment,t),a=!0)},o(t){Y(n.$$.fragment,t),a=!1},d(t){V(n,t)}}}function ke(t){let n,a;return n=new pe({}),{c(){W(n.$$.fragment)},m(t,e){F(n,t,e),a=!0},i(t){a||(N(n.$$.fragment,t),a=!0)},o(t){Y(n.$$.fragment,t),a=!1},d(t){V(n,t)}}}function $e(n){let a,o,t,r,i,s,l,c,u,d,f,p,h,g,y,$,w,b,k,C,L,A;d=new we({});const B=[ke,be],M=[];function T(t){return"outfits"===t[2]?0:"about"===t[2]?1:-1}return~(w=T(n))&&(b=M[w]=B[w](n)),{c(){a=v("div"),o=v("img"),r=U(),(i=v("div")).textContent="Vanita",s=U(),l=v("div"),c=U(),u=v("button"),W(d.$$.fragment),f=U(),p=v("div"),(h=v("div")).textContent="Outfits",g=U(),(y=v("div")).textContent="About",$=U(),b&&b.c(),k=Ot(),m(o,"class","icon a0"),m(o,"draggable",!1),ft(o.src,t=ve.getAssetUrl("logo.png"))||m(o,"src",t),m(o,"alt","Vanita Logo"),m(i,"class","title a0"),m(l,"class","drag a0"),m(u,"class","close a0"),m(a,"class","header a0"),m(h,"class","tab a0"),m(y,"class","tab a0"),m(p,"class","tabs a0")},m(t,e){E(t,a,e),_(a,o),_(a,r),_(a,i),_(a,s),_(a,l),_(a,c),_(a,u),F(d,u,null),E(t,f,e),E(t,p,e),_(p,h),_(p,g),_(p,y),E(t,$,e),~w&&M[w].m(t,e),E(t,k,e),C=!0,L||(A=[x(l,"mousedown",n[3]),x(u,"click",n[4]),x(h,"click",n[5]),x(h,"keydown",Ce),x(y,"click",n[6]),x(y,"keydown",xe)],L=!0)},p(t,[]){let e=w;(w=T(t))!==e&&(b&&(At(),Y(M[e],1,1,()=>{M[e]=null}),Bt()),~w?((b=M[w])||(b=M[w]=B[w](t)).c(),N(b,1),b.m(k.parentNode,k)):b=null)},i(t){C||(N(d.$$.fragment,t),N(b),C=!0)},o(t){Y(d.$$.fragment,t),Y(b),C=!1},d(t){t&&O(a),V(d),t&&O(f),t&&O(p),t&&O($),~w&&M[w].d(t),t&&O(k),L=!1,S(A)}}}const Ce=()=>{},xe=()=>{};function Oe(t,e,a){let o,n="outfits",r=!1;Et(async()=>{const t=new It("window-location",{x:0,y:0}),e=document.getElementById("app");a(1,o=new Zt(e));document.getElementById("app-toggle").onclick=()=>{a(0,r=!0)};var n=await t.load();a(1,o.targetX=n.x,o),a(1,o.targetY=n.y,o),o.onDragCompleted(()=>{t.save({x:o.targetX,y:o.targetY})})});return t.$$.update=()=>{1&t.$$.dirty&&null!==r&&(document.getElementById("app-toggle").style.display=r?"none":"flex",document.getElementById("app").style.display=r?"flex":"none")},[r,o,n,t=>o.drag(t),()=>a(0,r=!1),()=>a(2,n="outfits"),()=>a(2,n="about")]}class Le extends K{constructor(t){super(),J(this,t,Oe,$e,q,{})}}new Le({target:document.getElementById("app")});})() \ No newline at end of file diff --git a/extension/logo.png b/extension/logo.png new file mode 100644 index 0000000..3a3d273 Binary files /dev/null and b/extension/logo.png differ diff --git a/extension/manifest.json b/extension/manifest.json index 348e02f..bafd252 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,21 +1,31 @@ { - "name": "Roblox Web Panel", - "description": "RWP stands for Roblox web panel, it's a code snippet that you can run via developer console to try out early Roblox site features before they're officially out without any programming experience.", - "version": "1.0.0", + "name": "Vanita", + "description": "Enhances the Roblox website experience with extra functionality.", + "version": "2.0.0", "manifest_version": 3, - "background": { - "service_worker": "background.js" - }, "permissions": [ - "storage", - "activeTab", - "scripting", - "tabs" + "storage" ], - "action": { - "default_popup": "popup.html" - }, - "host_permissions": [ + "content_scripts": [ + { + "matches": ["https://www.roblox.com/*"], + "js": ["embedded.js"] + } + ], + "host_permissions":[ "https://www.roblox.com/*" + ], + "icons": { + "128": "logo.png" + }, + "web_accessible_resources": [ + { + "resources": [ + "logo.png" + ], + "matches": [ + "https://www.roblox.com/*" + ] + } ] } \ No newline at end of file diff --git a/extension/popup.css b/extension/popup.css deleted file mode 100644 index 63e83e8..0000000 --- a/extension/popup.css +++ /dev/null @@ -1,8 +0,0 @@ -body { - background: #232527; - color: #bdbebe; - - display: flex; - flex-direction: row; - gap: 5px; -} \ No newline at end of file diff --git a/extension/popup.html b/extension/popup.html deleted file mode 100644 index 89ea2ef..0000000 --- a/extension/popup.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/extension/popup.js b/extension/popup.js deleted file mode 100644 index 97f0f8b..0000000 --- a/extension/popup.js +++ /dev/null @@ -1,9 +0,0 @@ -const InjectCheckbox = document.getElementById("inject-checkbox"); - -chrome.storage.sync.get(["injectionEnabled"], data => { - InjectCheckbox.checked = data.injectionEnabled -}); - -InjectCheckbox.addEventListener("change", () => { - chrome.storage.sync.set({injectionEnabled: InjectCheckbox.checked}); -}); \ No newline at end of file diff --git a/loader.js b/loader.js index 33eb0d8..f76e296 100644 --- a/loader.js +++ b/loader.js @@ -2,6 +2,11 @@ const container = document.createElement("div"); container.id = "app"; document.body.appendChild(container); +const toggleBtn = document.createElement("div"); +toggleBtn.id = "app-toggle"; +toggleBtn.textContent = "Vanita"; +document.body.appendChild(toggleBtn); + const style = document.createElement("style"); /* Will be replaced with actual css by pack.js. diff --git a/package.json b/package.json index c7227cd..6028c17 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "rwp", + "name": "vanita", "author": { "name": "Daw588", "url": "https://daw588.glitch.me/" @@ -18,6 +18,7 @@ "devDependencies": { "@sveltejs/vite-plugin-svelte": "^1.4.0", "@tsconfig/svelte": "^3.0.0", + "@types/chrome": "^0.0.216", "@types/fs-extra": "^11.0.1", "@types/uglify-js": "^3.17.1", "sass": "^1.58.1", @@ -28,7 +29,8 @@ "typescript": "^4.9.5", "uglify-js": "^3.17.4", "vite": "^4.1.1", - "vite-plugin-html": "^3.2.0" + "vite-plugin-html": "^3.2.0", + "zip-a-folder": "^1.1.5" }, "dependencies": { "clipboardy": "^3.0.0", diff --git a/scripts/copy.js b/scripts/copy.js index a1752f0..dbd4548 100644 --- a/scripts/copy.js +++ b/scripts/copy.js @@ -1,5 +1,5 @@ import fs from "node:fs/promises"; import clipboard from "clipboardy"; -const relaseJs = await fs.readFile("dist/release.js", { encoding: "utf-8" }); +const relaseJs = await fs.readFile("extension/embedded.js", { encoding: "utf-8" }); await clipboard.write(relaseJs); \ No newline at end of file diff --git a/scripts/pack.js b/scripts/pack.js index 16dd213..f3d206e 100644 --- a/scripts/pack.js +++ b/scripts/pack.js @@ -2,6 +2,7 @@ import fs from "node:fs/promises"; import fsExtra from "fs-extra"; import path from "node:path"; import uglify from "uglify-js"; +import { zip } from "zip-a-folder"; /** * Finds file with desired extension in a given directory. @@ -20,8 +21,8 @@ async function getFilePathByExtension(directoryPath, extension) { // Paths to files needed to be packed const loaderJsPath = "loader.js"; -const indexJsPath = await getFilePathByExtension("dist/assets", ".js"); -const indexCssPath = await getFilePathByExtension("dist/assets", ".css"); +const indexJsPath = await getFilePathByExtension("build/assets", ".js"); +const indexCssPath = await getFilePathByExtension("build/assets", ".css"); // Get raw contents let loaderJsRaw = await fs.readFile(loaderJsPath, { encoding: "utf-8" }); @@ -49,8 +50,6 @@ const indexJsMin = uglify.minify(indexJsRaw).code; */ const finalCode = loaderJsMin + `(()=>{${indexJsMin}})()`; -await fsExtra.emptyDir("dist"); -await fs.writeFile("dist/release.js", finalCode, { encoding: "utf-8" }); - -// Create one for extension as well -await fs.writeFile("extension/embedded.js", finalCode, { encoding: "utf-8" }) \ No newline at end of file +await fsExtra.emptyDir("build"); +await fs.writeFile("extension/embedded.js", finalCode, { encoding: "utf-8" }); +await zip("extension", "build/release.zip"); \ No newline at end of file diff --git a/src/app.svelte b/src/app.svelte index e28b1c0..ef25576 100644 --- a/src/app.svelte +++ b/src/app.svelte @@ -5,19 +5,55 @@ import Draggable from "./lib/draggable"; import About from "./tabs/about.svelte"; import Outfits from "./tabs/outfits.svelte"; + import LocalStorage from "./lib/local-storage"; + import GoX from "svelte-icons/go/GoX.svelte"; + import LocalFiles from "./lib/local-files"; let draggable: Draggable; let currentTabName: string = "outfits"; + let isOpen = false; + + $: if (isOpen !== null) { + document.getElementById("app-toggle").style.display = (isOpen) ? "none" : "flex"; + document.getElementById("app").style.display = (isOpen) ? "flex" : "none"; + } + + onMount(async () => { + const windowLocation = new LocalStorage<{x: number, y: number}>("window-location", { + x: 0, + y: 0 + }); - onMount(() => { const containerElement = document.getElementById("app"); draggable = new Draggable(containerElement); + + const toggleBtn = document.getElementById("app-toggle"); + toggleBtn.onclick = () => { + isOpen = true; + } + + // Load previous window location + + const saved = await windowLocation.load(); + //console.log(saved); + draggable.targetX = saved.x; + draggable.targetY = saved.y; + + draggable.onDragCompleted(() => { + // Save recent window location + windowLocation.save({ + x: draggable.targetX, + y: draggable.targetY + }) + }); });
-
RWP - Vanilla Roblox with extended functionality
+ Vanita Logo +
Vanita
draggable.drag(e)}>
+
@@ -29,4 +65,4 @@ {:else if currentTabName === "about"} -{/if} +{/if} \ No newline at end of file diff --git a/src/lib/draggable.ts b/src/lib/draggable.ts index fc0b9f4..650da44 100644 --- a/src/lib/draggable.ts +++ b/src/lib/draggable.ts @@ -1,9 +1,10 @@ export default class Draggable { - private pos1 = 0; - private pos2 = 0; - private pos3 = 0; - private pos4 = 0; - private target: HTMLElement; + private offX = 0; + private offY = 0; + private mouseX = 0; + private mouseY = 0; + public readonly target: HTMLElement; + private dragCompletedCallbacks: (() => void)[] = []; public constructor(target: HTMLElement) { this.target = target; @@ -18,8 +19,8 @@ export default class Draggable { const self = this; // get the mouse cursor position at startup: - this.pos3 = e.clientX; - this.pos4 = e.clientY; + this.mouseX = e.clientX; + this.mouseY = e.clientY; document.onmouseup = () => self.closeDragElement(); // call a function whenever the cursor moves: @@ -32,19 +33,45 @@ export default class Draggable { e.preventDefault(); // calculate the new cursor position: - this.pos1 = this.pos3 - e.clientX; - this.pos2 = this.pos4 - e.clientY; - this.pos3 = e.clientX; - this.pos4 = e.clientY; + this.offX = this.mouseX - e.clientX; + this.offY = this.mouseY - e.clientY; + this.mouseX = e.clientX; + this.mouseY = e.clientY; // set the element's new position: - this.target.style.top = this.target.offsetTop - this.pos2 + "px"; - this.target.style.left = this.target.offsetLeft - this.pos1 + "px"; + this.updateWindowPosition(); + } + + public updateWindowPosition() { + this.target.style.top = this.target.offsetTop - this.offY + "px"; + this.target.style.left = this.target.offsetLeft - this.offX + "px"; + } + + get targetX() { + return parseFloat(this.target.style.left); + } + + set targetX(value: number) { + this.target.style.left = value + "px"; + } + + get targetY() { + return parseFloat(this.target.style.top); + } + + set targetY(value: number) { + this.target.style.top = value + "px"; } private closeDragElement() { // stop moving when mouse button is released: document.onmouseup = null; document.onmousemove = null; + + this.dragCompletedCallbacks.forEach(callback => callback()); + } + + public onDragCompleted(callback: () => void) { + this.dragCompletedCallbacks.push(callback); } } \ No newline at end of file diff --git a/src/lib/local-files.ts b/src/lib/local-files.ts new file mode 100644 index 0000000..711069f --- /dev/null +++ b/src/lib/local-files.ts @@ -0,0 +1,7 @@ +export default class LocalFiles { + public constructor() {} + + public static getAssetUrl(path: string) { + return chrome.runtime.getURL(path); + } +} \ No newline at end of file diff --git a/src/lib/local-storage.ts b/src/lib/local-storage.ts new file mode 100644 index 0000000..2af1cf9 --- /dev/null +++ b/src/lib/local-storage.ts @@ -0,0 +1,24 @@ +export default class LocalStorage { + public readonly key: string; + public readonly defaultValue: T; + + public constructor(key: string, defaultValue: T) { + this.key = key; + this.defaultValue = defaultValue; + } + + public async save(value: T) { + const target = {}; + target[this.key] = value; + + await chrome.storage.sync.set(target); + } + + public async load() { + const values = await chrome.storage.sync.get([this.key]); + const value = values[this.key]; + const finalValue = (value) ? value : this.defaultValue; + + return finalValue as unknown as T; + } +} \ No newline at end of file diff --git a/src/lib/outfit.ts b/src/lib/outfit.ts index 8f8997b..5603943 100644 --- a/src/lib/outfit.ts +++ b/src/lib/outfit.ts @@ -31,7 +31,7 @@ interface BodyScale { bodyType: number } -interface OutfitCreateData { +export interface OutfitCreateData { name: string, bodyColors: BodyColors, assetIds: number[], diff --git a/src/styles/app.scss b/src/styles/app.scss index fb8da3e..f5e009c 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -10,6 +10,13 @@ font-size: 1rem; + .icon { + width: 24px; + height: 24px; + margin-left: 6px; + user-select: none; + } + .title { padding: 8px; } @@ -19,6 +26,17 @@ flex-grow: 1; height: 100%; } + + .close { + width: 24px; + height: 24px; + margin-right: 6px; + cursor: pointer; + + &, * { + color: #fff; + } + } } .tabs { diff --git a/src/styles/global.css b/src/styles/global.css index 07e33e3..9faaa71 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -30,6 +30,24 @@ border-radius: 5px; } +#app-toggle { + position: fixed; + top: 100%; + left: 100px; + transform: translateY(-100%); + z-index: 9999; + padding: 6px; + padding-left: 8px; + padding-right: 8px; + cursor: pointer; + background: #232527; + color: #fff; + border: 1px solid #111214; + border-bottom: none; + border-top-left-radius: 8px; + border-top-right-radius: 8px; +} + #app .material-symbols-outlined { font-variation-settings: "FILL" 0, diff --git a/src/tabs/outfits.svelte b/src/tabs/outfits.svelte index fffe470..932f326 100644 --- a/src/tabs/outfits.svelte +++ b/src/tabs/outfits.svelte @@ -5,12 +5,14 @@ import { onMount } from "svelte"; import Outfit from "../lib/outfit"; import Thumbnail from "../lib/thumbnail"; - import LZString from "../lib/third-party/lz-string"; - import * as util from "../lib/util"; + //import LZString from "../lib/third-party/lz-string"; + //import * as util from "../lib/util"; import GoGear from "svelte-icons/go/GoGear.svelte"; + import LocalStorage from "../lib/local-storage"; + import type { OutfitCreateData } from "../lib/outfit"; let outfits: Outfit[] = []; - let templateOutfitId = -1; + //let templateOutfitId = -1; let outfitNameInput = ""; let thisUser: User; let outfitsLoaded = false; @@ -33,6 +35,10 @@ } */ + const userOutfitsList = new LocalStorage<{ + data: OutfitCreateData, thumbnailUrl: string + }[]>("outfit-list", []); + onMount(async () => { // Get currently authenticated user thisUser = await User.getCurrentUser(); @@ -48,7 +54,7 @@ saveOutfits(); } - function saveOutfits() { + async function saveOutfits() { if (!outfitsLoaded) { /* Nothing has been loaded yet, @@ -66,10 +72,11 @@ }; }); + await userOutfitsList.save(outfitList); + + /* const uncompressed = JSON.stringify(outfitList); const compressed = LZString.compress(uncompressed); - - /* const decompressed = LZString.decompress(compressed); const uncompressedBytes = util.stringToBytes(uncompressed); @@ -89,21 +96,18 @@ Compression Ratio: ${compressionRatio.toFixed(2)} Saved: ${Math.round(savedSpace)}% `); - */ localStorage.setItem("rwp-outfits", compressed); + */ } - function loadOutfits() { - const compressed = localStorage.getItem("rwp-outfits"); - if (!compressed) { - // Couldn't load, there is nothing to load - outfitsLoaded = true; - return; - } + async function loadOutfits() { + const outfitList = await userOutfitsList.load(); + /* const decompressed = LZString.decompress(compressed); const outfitList = JSON.parse(decompressed); + */ // Overwrite current data with loaded data outfits = outfitList.map(outfitInfo => { diff --git a/tsconfig.json b/tsconfig.json index eef639b..32be31b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,10 @@ * of JS in `.svelte` files. */ "allowJs": true, - "checkJs": true + "checkJs": true, + "types": [ + "chrome" + ] }, "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] } diff --git a/vite.config.js b/vite.config.js index b530c82..85ba238 100644 --- a/vite.config.js +++ b/vite.config.js @@ -25,5 +25,8 @@ export default defineConfig({ port: 443, }, port: 3000 + }, + build: { + outDir: "build" } });