Compare commits
18 Commits
Author | SHA1 | Date |
---|---|---|
|
88997db4ec | 3 years ago |
|
ab1dc88edf | 3 years ago |
|
02b8d01101 | 4 years ago |
|
de281ad03d | 4 years ago |
|
9bb30641ca | 4 years ago |
|
f9ad955ad9 | 4 years ago |
|
767c145e1b | 5 years ago |
|
a56d52b258 | 5 years ago |
|
dbf116c854 | 6 years ago |
|
753ec7e5bb | 6 years ago |
|
d1ccc20d29 | 6 years ago |
|
61ab5bb5ef | 6 years ago |
|
3d2b12ca64 | 6 years ago |
|
46af9953e8 | 6 years ago |
|
c26d09b74f | 6 years ago |
|
879fe8af5c | 6 years ago |
|
61447e7fca | 6 years ago |
|
f719bdf8b9 | 6 years ago |
@ -1,54 +0,0 @@ |
||||
name: Build & deploy |
||||
|
||||
on: |
||||
push: |
||||
branches: |
||||
- master |
||||
pull_request: |
||||
branches: |
||||
- master |
||||
|
||||
jobs: |
||||
build: |
||||
name: Build |
||||
runs-on: ubuntu-latest |
||||
|
||||
steps: |
||||
- name: Checkout code |
||||
uses: actions/checkout@v2 |
||||
|
||||
- name: Install Node.js |
||||
uses: actions/setup-node@v1 |
||||
with: |
||||
node-version: 13.x |
||||
|
||||
- name: Install NPM packages |
||||
run: npm ci |
||||
|
||||
- name: Build project |
||||
run: npm run build |
||||
|
||||
- name: Upload production-ready build files |
||||
uses: actions/upload-artifact@v2 |
||||
with: |
||||
name: production-files |
||||
path: ./build |
||||
|
||||
deploy: |
||||
name: Deploy |
||||
needs: build |
||||
runs-on: ubuntu-latest |
||||
if: github.ref == 'refs/heads/master' |
||||
|
||||
steps: |
||||
- name: Download artifact |
||||
uses: actions/download-artifact@v2 |
||||
with: |
||||
name: production-files |
||||
path: ./build |
||||
|
||||
- name: Deploy to gh-pages |
||||
uses: peaceiris/actions-gh-pages@v3 |
||||
with: |
||||
github_token: ${{ secrets.GITHUB_TOKEN }} |
||||
publish_dir: ./build |
@ -1,23 +0,0 @@ |
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. |
||||
|
||||
# dependencies |
||||
/node_modules |
||||
/.pnp |
||||
.pnp.js |
||||
|
||||
# testing |
||||
/coverage |
||||
|
||||
# production |
||||
/build |
||||
|
||||
# misc |
||||
.DS_Store |
||||
.env.local |
||||
.env.development.local |
||||
.env.test.local |
||||
.env.production.local |
||||
|
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
@ -1,14 +0,0 @@ |
||||
## SkillDisplay |
||||
A simple no-frills ACTWebSocket overlay for showing actions pressed in an overlay window. |
||||
|
||||
## Installation |
||||
Make sure the 'Using BeforeLogLineRead' box is checked in ACTWebSocket then click the 'Add URL' button to add this URL: |
||||
`https://rawrington.github.io/SkillDisplay/` |
||||
|
||||
## Troubleshooting |
||||
I have only tested and confirmed this working on the QT5.8.0 variant of OverlayProc with ACTWebSocket 1.3.3.9 so if you are having trouble please use these versions. |
||||
|
||||
If you find any strange bugs, please report to me on here or find me on the ACT FFXIV discord. |
||||
|
||||
## Preview |
||||
 |
@ -0,0 +1,20 @@ |
||||
{ |
||||
"files": { |
||||
"main.css": "/SkillDisplay/static/css/main.af6b9f88.chunk.css", |
||||
"main.js": "/SkillDisplay/static/js/main.e1247fe5.chunk.js", |
||||
"main.js.map": "/SkillDisplay/static/js/main.e1247fe5.chunk.js.map", |
||||
"runtime-main.js": "/SkillDisplay/static/js/runtime-main.58acd0bf.js", |
||||
"runtime-main.js.map": "/SkillDisplay/static/js/runtime-main.58acd0bf.js.map", |
||||
"static/js/2.4d71e7f6.chunk.js": "/SkillDisplay/static/js/2.4d71e7f6.chunk.js", |
||||
"static/js/2.4d71e7f6.chunk.js.map": "/SkillDisplay/static/js/2.4d71e7f6.chunk.js.map", |
||||
"index.html": "/SkillDisplay/index.html", |
||||
"static/css/main.af6b9f88.chunk.css.map": "/SkillDisplay/static/css/main.af6b9f88.chunk.css.map", |
||||
"static/js/2.4d71e7f6.chunk.js.LICENSE.txt": "/SkillDisplay/static/js/2.4d71e7f6.chunk.js.LICENSE.txt" |
||||
}, |
||||
"entrypoints": [ |
||||
"static/js/runtime-main.58acd0bf.js", |
||||
"static/js/2.4d71e7f6.chunk.js", |
||||
"static/css/main.af6b9f88.chunk.css", |
||||
"static/js/main.e1247fe5.chunk.js" |
||||
] |
||||
} |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 199 KiB |
@ -0,0 +1 @@ |
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/SkillDisplay/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/SkillDisplay/manifest.json"/><title>Skill Display</title><link href="/SkillDisplay/static/css/main.af6b9f88.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,u,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)u=i[c],Object.prototype.hasOwnProperty.call(o,u)&&o[u]&&s.push(o[u][0]),o[u]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return l.push.apply(l,p||[]),t()}function t(){for(var e,r=0;r<l.length;r++){for(var t=l[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(l.splice(r--,1),e=u(u.s=t[0]))}return e}var n={},o={1:0},l=[];function u(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,u),t.l=!0,t.exports}u.m=e,u.c=n,u.d=function(e,r,t){u.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},u.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,r){if(1&r&&(e=u(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(u.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)u.d(t,n,function(r){return e[r]}.bind(null,n));return t},u.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(r,"a",r),r},u.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},u.p="/SkillDisplay/";var i=this.webpackJsonpskilldisplay=this.webpackJsonpskilldisplay||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/SkillDisplay/static/js/2.4d71e7f6.chunk.js"></script><script src="/SkillDisplay/static/js/main.e1247fe5.chunk.js"></script></body></html> |
File diff suppressed because it is too large
Load Diff
@ -1,32 +0,0 @@ |
||||
{ |
||||
"name": "skilldisplay", |
||||
"version": "0.3.0", |
||||
"private": true, |
||||
"dependencies": { |
||||
"react": "^17.0.1", |
||||
"react-dom": "^17.0.1", |
||||
"react-scripts": "4.0.1" |
||||
}, |
||||
"scripts": { |
||||
"start": "react-scripts start", |
||||
"build": "react-scripts build", |
||||
"test": "react-scripts test", |
||||
"eject": "react-scripts eject" |
||||
}, |
||||
"eslintConfig": { |
||||
"extends": "react-app" |
||||
}, |
||||
"homepage": "https://rawrington.github.io/SkillDisplay/", |
||||
"browserslist": { |
||||
"production": [ |
||||
">0.2%", |
||||
"not dead", |
||||
"not op_mini all" |
||||
], |
||||
"development": [ |
||||
"last 1 chrome version", |
||||
"last 1 firefox version", |
||||
"last 1 safari version" |
||||
] |
||||
} |
||||
} |
@ -1,25 +0,0 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="utf-8" /> |
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" /> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
||||
<meta name="theme-color" content="#000000" /> |
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" /> |
||||
<title>Skill Display</title> |
||||
</head> |
||||
<body> |
||||
<noscript>You need to enable JavaScript to run this app.</noscript> |
||||
<div id="root"></div> |
||||
<!-- |
||||
This HTML file is a template. |
||||
If you open it directly in the browser, you will see an empty page. |
||||
|
||||
You can add webfonts, meta tags, or analytics to this file. |
||||
The build step will place the bundled scripts into the <body> tag. |
||||
|
||||
To begin the development, run `npm start` or `yarn start`. |
||||
To create a production bundle, use `npm run build` or `yarn build`. |
||||
--> |
||||
</body> |
||||
</html> |
@ -1,42 +0,0 @@ |
||||
const getHost = () => /[?&]HOST_PORT=(wss?:\/\/[^&/]+)/.exec(window.location.search) |
||||
|
||||
export default function listenToACT(callback) { |
||||
if (!getHost()) return listenOverlayPlugin(callback) |
||||
return listenActWebSocket(callback) |
||||
} |
||||
|
||||
function listenActWebSocket(callback) { |
||||
const wsUri = `${getHost()[1]}/BeforeLogLineRead` || undefined |
||||
const ws = new WebSocket(wsUri) |
||||
ws.onerror = () => ws.close() |
||||
ws.onclose = () => |
||||
setTimeout(() => { |
||||
listenActWebSocket(callback) |
||||
}, 1000) |
||||
ws.onmessage = function(e, m) { |
||||
if (e.data === ".") return ws.send(".") |
||||
|
||||
const obj = JSON.parse(e.data) |
||||
if (obj.msgtype === "SendCharName") { |
||||
return callback(obj.msg) |
||||
} else if (obj.msgtype === "Chat") { |
||||
return callback(...obj.msg.split("|")) |
||||
} |
||||
} |
||||
|
||||
return () => { |
||||
ws.close() |
||||
} |
||||
} |
||||
|
||||
function listenOverlayPlugin(callback) { |
||||
const listener = e => { |
||||
callback(...e.detail) |
||||
} |
||||
|
||||
document.addEventListener("onLogLine", listener) |
||||
|
||||
return () => { |
||||
document.removeEventListener("onLogLine", listener) |
||||
} |
||||
} |
@ -1,101 +0,0 @@ |
||||
import React from "react" |
||||
import "./css/Action.css" |
||||
|
||||
const gcdOverrides = new Set([ |
||||
15997, //standard step
|
||||
15998, //technical step
|
||||
15999, |
||||
16000, |
||||
16001, |
||||
16002, //step actions
|
||||
16003, //standard finish
|
||||
16004, //technical finish
|
||||
16191, //single standard finish
|
||||
16192, //double standard finish (WHY IS IT LIKE THIS)
|
||||
16193, //single technical finish
|
||||
16194, //double technical finish
|
||||
16195, //triple technical finish
|
||||
16196, //quadruple technical finish
|
||||
7418, //flamethrower
|
||||
16484, //kaeshi higanbana
|
||||
16485, //kaeshi goken
|
||||
16486, //kaeshi setsugekka
|
||||
2259, //ten
|
||||
18805,
|
||||
2261, //chi
|
||||
18806, |
||||
2263, //jin
|
||||
18807, |
||||
2265, //fuma shurikan
|
||||
18873, |
||||
18874, |
||||
18875, |
||||
2267, //raiton
|
||||
18877, |
||||
2266, //katon
|
||||
18876, |
||||
2268, //hyoton
|
||||
18878, |
||||
16492, //hyosho ranryu
|
||||
16471, //goka meykakku
|
||||
16491, //goka meykakku (16471 is the PvP version, 16491 is the PvE version)
|
||||
2270, //doton
|
||||
18880, |
||||
2269, //huton
|
||||
18879, |
||||
2271, //suiton
|
||||
18881, |
||||
2272, //rabbit medium
|
||||
]) |
||||
|
||||
const ogcdOverrides = new Set([ |
||||
3559, //bard WM
|
||||
116, //bard AP
|
||||
114 //bard MB
|
||||
]) |
||||
|
||||
const actionMap = new Map() |
||||
|
||||
export default function Action({ actionId, additionalClasses }) { |
||||
const [apiData, setApiData] = React.useState() |
||||
|
||||
React.useEffect(() => { |
||||
const mapData = actionMap.get(actionId) |
||||
if (mapData != null) { |
||||
setApiData(mapData) |
||||
return |
||||
} |
||||
|
||||
let current = true |
||||
void (async () => { |
||||
const data = await (await fetch(`https://xivapi.com/Action/${actionId}?columns=Icon,Name,ActionCategoryTargetID`, { |
||||
mode: "cors" |
||||
})).json() |
||||
if (current) { |
||||
actionMap.set(actionId, data) |
||||
setApiData(data) |
||||
} |
||||
})() |
||||
|
||||
return () => { |
||||
current = false |
||||
} |
||||
}, [actionId]) |
||||
|
||||
if (apiData === undefined || !apiData.Icon) { |
||||
return null |
||||
} |
||||
|
||||
return ( |
||||
<img |
||||
className={ |
||||
gcdOverrides.has(actionId) || |
||||
(!ogcdOverrides.has(actionId) && apiData.ActionCategoryTargetID !== 4) |
||||
? `gcd ${additionalClasses}` |
||||
: `ogcd ${additionalClasses}` |
||||
} |
||||
src={`https://xivapi.com/${apiData.Icon}`} |
||||
alt={apiData.Name || ""} |
||||
/> |
||||
) |
||||
} |
@ -1,150 +0,0 @@ |
||||
import React from "react" |
||||
import listenToACT from "./ACTListener" |
||||
import "./css/App.css" |
||||
import Action from "./Action" |
||||
import RotationContainer from "./Rotation" |
||||
import ReactDOM from "react-dom" |
||||
|
||||
const handleCodes = new Set(["00", "01", "02", "21", "22", "33"]) |
||||
|
||||
export default function App() { |
||||
const [actionList, setActionList] = React.useState([]) |
||||
const [encounterList, setEncounterList] = React.useState([]) |
||||
|
||||
React.useEffect(() => { |
||||
let selfId |
||||
let lastTimestamp = "" |
||||
let lastAction = -1 |
||||
let currentZone = "Unknown" |
||||
|
||||
let lastKey = 1 |
||||
|
||||
let closeFn = listenToACT((...logSplit) => { |
||||
const openNewEncounter = () => { |
||||
setEncounterList(encounterList => { |
||||
if ( |
||||
encounterList[0] && |
||||
encounterList[0].rotation && |
||||
encounterList[0].rotation.length <= 0 |
||||
) { |
||||
encounterList.shift() |
||||
} |
||||
|
||||
encounterList.unshift({ |
||||
name: currentZone, |
||||
rotation: [] |
||||
}) |
||||
|
||||
return encounterList.slice(0, 3) |
||||
}) |
||||
} |
||||
|
||||
if (logSplit.length === 1 && logSplit[0].charID) { |
||||
selfId = logSplit[0].charID |
||||
openNewEncounter() |
||||
return |
||||
} |
||||
|
||||
const [ |
||||
logCode, |
||||
logTimestamp, |
||||
logParameter1, |
||||
logParameter2, |
||||
logParameter3 |
||||
] = logSplit |
||||
|
||||
if (!handleCodes.has(logCode)) return |
||||
|
||||
switch (logCode) { |
||||
case "00": |
||||
if (logParameter1 === "0038" && logParameter3 === "end") |
||||
openNewEncounter() |
||||
return |
||||
case "01": |
||||
currentZone = logParameter2 |
||||
return |
||||
case "02": |
||||
selfId = parseInt(logParameter1, 16) |
||||
openNewEncounter() |
||||
return |
||||
case "33": |
||||
if (logParameter2 === "40000012" || logParameter2 === "40000010") |
||||
openNewEncounter() |
||||
return |
||||
default: |
||||
break |
||||
} |
||||
|
||||
if (selfId === undefined) return |
||||
|
||||
if (parseInt(logParameter1, 16) !== selfId) return |
||||
|
||||
const action = parseInt(logParameter3, 16) |
||||
|
||||
if ( //sanity check the tea sis period wig snapped
|
||||
((action < 9 || action > 30000) && //is not a combat action
|
||||
(action < 100001 || action > 100300)) || //and is not a crafting action
|
||||
(logTimestamp === lastTimestamp && action === lastAction) //or this action is a bug/duplicate
|
||||
) |
||||
return |
||||
|
||||
if (Date.now() - Date.parse(lastTimestamp) > 120000) openNewEncounter() //last action > 120s ago
|
||||
|
||||
lastTimestamp = logTimestamp |
||||
lastAction = action |
||||
|
||||
const key = (lastKey % 256) + 1 |
||||
lastKey = key |
||||
|
||||
// This is pretty silly but it's the neatest way to handle the updates going
|
||||
// out at the same time, without finding some way to merge the action lists....
|
||||
ReactDOM.unstable_batchedUpdates(() => { |
||||
setActionList(actionList => actionList.concat({ action, key })) |
||||
setEncounterList(encounterList => { |
||||
if (!encounterList[0]) { |
||||
encounterList[0] = { |
||||
name: currentZone, |
||||
rotation: [] |
||||
} |
||||
} |
||||
|
||||
encounterList[0].rotation.push(action) |
||||
|
||||
return encounterList |
||||
}) |
||||
}) |
||||
|
||||
setTimeout(() => { |
||||
setActionList(actionList => actionList.slice(1)) |
||||
}, 10000) |
||||
}) |
||||
|
||||
return () => { |
||||
closeFn() |
||||
} |
||||
}, []) |
||||
|
||||
return ( |
||||
<> |
||||
<div className="container"> |
||||
<div className="actions"> |
||||
{actionList.map(({ action, key }) => ( |
||||
<Action |
||||
key={key} |
||||
actionId={action} |
||||
additionalClasses="action-move" |
||||
/> |
||||
))} |
||||
</div> |
||||
{encounterList.map((encounter, i) => ( |
||||
<RotationContainer |
||||
key={i} |
||||
encounterId={i} |
||||
name={encounter.name} |
||||
actionList={encounter.rotation} |
||||
/> |
||||
))} |
||||
</div> |
||||
</> |
||||
) |
||||
} |
@ -1,33 +0,0 @@ |
||||
import React from "react" |
||||
import "./css/Rotation.css" |
||||
import Action from "./Action" |
||||
|
||||
export default function RotationContainer({ encounterId, name, actionList }) { |
||||
const [open, setOpen] = React.useState(false) |
||||
|
||||
return ( |
||||
<> |
||||
<button |
||||
className={open ? "rotation-button expanded" : "rotation-button"} |
||||
onClick={() => { |
||||
setOpen(open => !open) |
||||
}} |
||||
> |
||||
{encounterId === 0 ? "Current Rotation" : name} |
||||
</button> |
||||
<RotationContents expanded={open} actionList={actionList} /> |
||||
</> |
||||
) |
||||
} |
||||
|
||||
function RotationContents({ expanded, actionList }) { |
||||
if (!expanded) return null |
||||
|
||||
return ( |
||||
<div className="rotation-list"> |
||||
{actionList.map((action, i) => ( |
||||
<Action key={i} actionId={action} additionalClasses="action-rotation" /> |
||||
))} |
||||
</div> |
||||
) |
||||
} |
@ -1,37 +0,0 @@ |
||||
.action-move { |
||||
animation-duration: 10s; |
||||
animation-name: action-move; |
||||
animation-timing-function: linear; |
||||
animation-fill-mode: forwards; |
||||
position: absolute; |
||||
} |
||||
|
||||
.gcd { |
||||
width: 3rem; |
||||
vertical-align: top; |
||||
} |
||||
|
||||
.ogcd { |
||||
width: 2rem; |
||||
vertical-align: top; |
||||
} |
||||
|
||||
.action-rotation.gcd { |
||||
margin-left: 1em; |
||||
} |
||||
|
||||
.action-rotation.gcd::before { |
||||
content: '\25B6'; /* Unicode character for right arrow */ |
||||
font-size: 13px; |
||||
color: rgba(255, 255, 255, 0.5); |
||||
} |
||||
|
||||
@keyframes action-move { |
||||
from { |
||||
transform: translateX(calc(100vw - 3rem)); |
||||
} |
||||
|
||||
to { |
||||
transform: translateX(-3rem); |
||||
} |
||||
} |
@ -1,40 +0,0 @@ |
||||
body { |
||||
margin: 0; |
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", |
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", |
||||
sans-serif; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
html { |
||||
height: 100vh; |
||||
overflow: hidden; |
||||
background-image: none; |
||||
background-repeat: no-repeat; |
||||
} |
||||
|
||||
.actions { |
||||
padding-top: 1rem; |
||||
background: linear-gradient(180deg, |
||||
rgba(0,0,0,0) calc(25% - 1px), |
||||
rgba(255,255,255,0.5) calc(25%), |
||||
rgba(0,0,0,0) calc(25% + 1px), |
||||
rgba(0,0,0,0) calc(50% - 1px), |
||||
rgba(255,255,255,0.5) calc(50%), |
||||
rgba(0,0,0,0) calc(50% + 1px), |
||||
rgba(0,0,0,0) calc(75% - 1px), |
||||
rgba(255,255,255,0.5) calc(75%), |
||||
rgba(0,0,0,0) calc(75% + 1px) |
||||
); |
||||
height: 3rem; |
||||
padding-bottom: 1rem; |
||||
background-color: rgba(20, 20, 20, 0.3); |
||||
display: inline-block; |
||||
} |
||||
|
||||
.container { |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
@ -1,32 +0,0 @@ |
||||
.rotation-list { |
||||
padding: 0 18px; |
||||
background-color: rgba(80, 80, 80, 0.3); |
||||
display: block; |
||||
} |
||||
|
||||
.rotation-button { |
||||
background-color: rgba(100, 100, 100, 0.3); |
||||
color: rgba(255, 255, 255, 0.5); |
||||
padding: 0.1em; |
||||
width: 100vw; |
||||
border: none; |
||||
outline: none; |
||||
transition: 0.4s; |
||||
display: block; |
||||
} |
||||
|
||||
.rotation-button.expanded, .rotation-button:hover { |
||||
background-color: rgba(120, 120, 120, 0.3); |
||||
} |
||||
|
||||
.rotation-button:after { |
||||
content: '\25BC'; |
||||
font-size: 13px; |
||||
color: rgb(119,119,119); |
||||
float: right; |
||||
margin-left: 5px; |
||||
} |
||||
|
||||
.rotation-button.expanded:after { |
||||
content: "\25B2"; |
||||
} |
@ -1,15 +0,0 @@ |
||||
body { |
||||
margin: 0; |
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", |
||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", |
||||
sans-serif; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
font-size: 16px; |
||||
} |
||||
|
||||
html { |
||||
margin: 0; |
||||
height: 100vh; |
||||
overflow: hidden; |
||||
} |
@ -1,5 +0,0 @@ |
||||
import React from 'react' |
||||
import ReactDOM from 'react-dom' |
||||
import App from './App' |
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root')) |
@ -0,0 +1,2 @@ |
||||
body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px}html{height:100vh;overflow:hidden;background-image:none;background-repeat:no-repeat}.actions{padding-top:1rem;background:linear-gradient(180deg,transparent calc(25% - 1px),hsla(0,0%,100%,.5) 25%,transparent calc(25% + 1px),transparent calc(50% - 1px),hsla(0,0%,100%,.5) 50%,transparent calc(50% + 1px),transparent calc(75% - 1px),hsla(0,0%,100%,.5) 75%,transparent calc(75% + 1px));height:3rem;padding-bottom:1rem;background-color:rgba(20,20,20,.3);display:inline-block}.container{display:flex;flex-direction:column}.action-move{-webkit-animation-duration:10s;animation-duration:10s;-webkit-animation-name:action-move;animation-name:action-move;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;position:absolute}.gcd{width:3rem}.gcd,.ogcd{vertical-align:top}.ogcd{width:2rem}.action-rotation.gcd{margin-left:1em}.action-rotation.gcd:before{content:"\25B6";font-size:13px;color:hsla(0,0%,100%,.5)}@-webkit-keyframes action-move{0%{transform:translateX(calc(100vw - 3rem))}to{transform:translateX(-3rem)}}@keyframes action-move{0%{transform:translateX(calc(100vw - 3rem))}to{transform:translateX(-3rem)}}.rotation-list{padding:0 18px;background-color:rgba(80,80,80,.3);display:block}.rotation-button{background-color:hsla(0,0%,39.2%,.3);color:hsla(0,0%,100%,.5);padding:.1em;width:100vw;border:none;outline:none;transition:.4s;display:block}.rotation-button.expanded,.rotation-button:hover{background-color:hsla(0,0%,47.1%,.3)}.rotation-button:after{content:"\25BC";font-size:13px;color:#777;float:right;margin-left:5px}.rotation-button.expanded:after{content:"\25B2"} |
||||
/*# sourceMappingURL=main.af6b9f88.chunk.css.map */ |
@ -0,0 +1 @@ |
||||
{"version":3,"sources":["webpack://src/css/App.css","webpack://src/css/Action.css","webpack://src/css/Rotation.css"],"names":[],"mappings":"AAAA,KACC,QAAS,CACT,mJAEW,CACX,kCAAmC,CACnC,iCAAkC,CAClC,cACD,CAEA,KACC,YAAa,CACb,eAAgB,CAChB,qBAAsB,CACtB,2BACD,CAEA,SACC,gBAAiB,CACjB,+QAUI,CACJ,WAAY,CACZ,mBAAoB,CACpB,kCAAuC,CACvC,oBACD,CAEA,WACC,YAAa,CACb,qBACD,CCvCA,aACC,8BAAuB,CAAvB,sBAAuB,CACvB,kCAA2B,CAA3B,0BAA2B,CAC3B,wCAAiC,CAAjC,gCAAiC,CACjC,oCAA6B,CAA7B,4BAA6B,CAC7B,iBACD,CAEA,KACC,UAED,CAEA,WAHC,kBAMD,CAHA,MACC,UAED,CAEA,qBACC,eACD,CAEA,4BACC,eAAgB,CAChB,cAAe,CACf,wBACD,CAEA,+BACC,GACC,wCACD,CAEA,GACC,2BACD,CACD,CARA,uBACC,GACC,wCACD,CAEA,GACC,2BACD,CACD,CCpCA,eACC,cAAe,CACf,kCAAuC,CACvC,aACD,CAEA,iBACC,oCAA0C,CAC1C,wBAA+B,CAC/B,YAAc,CACd,WAAY,CACZ,WAAY,CACZ,YAAa,CACb,cAAgB,CAChB,aACD,CAEA,iDACC,oCACD,CAEA,uBACC,eAAgB,CAChB,cAAe,CACf,UAAuB,CACvB,WAAY,CACZ,eACD,CAEA,gCACC,eACD","file":"main.af6b9f88.chunk.css","sourcesContent":["body {\n\tmargin: 0;\n\tfont-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n\t\t\"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n\t\tsans-serif;\n\t-webkit-font-smoothing: antialiased;\n\t-moz-osx-font-smoothing: grayscale;\n\tfont-size: 16px;\n}\n\nhtml {\n\theight: 100vh;\n\toverflow: hidden;\n\tbackground-image: none;\n\tbackground-repeat: no-repeat;\n}\n\n.actions {\n\tpadding-top: 1rem;\n\tbackground: linear-gradient(180deg, \n\t\trgba(0,0,0,0) calc(25% - 1px), \n rgba(255,255,255,0.5) calc(25%), \n rgba(0,0,0,0) calc(25% + 1px),\n rgba(0,0,0,0) calc(50% - 1px), \n rgba(255,255,255,0.5) calc(50%), \n rgba(0,0,0,0) calc(50% + 1px),\n\t\trgba(0,0,0,0) calc(75% - 1px), \n rgba(255,255,255,0.5) calc(75%), \n rgba(0,0,0,0) calc(75% + 1px)\n );\n\theight: 3rem;\n\tpadding-bottom: 1rem;\n\tbackground-color: rgba(20, 20, 20, 0.3);\n\tdisplay: inline-block;\n}\n\n.container {\n\tdisplay: flex;\n\tflex-direction: column;\n}",".action-move {\n\tanimation-duration: 10s;\n\tanimation-name: action-move;\n\tanimation-timing-function: linear;\n\tanimation-fill-mode: forwards;\n\tposition: absolute;\n}\n\n.gcd {\n\twidth: 3rem;\n\tvertical-align: top;\n}\n\n.ogcd {\n\twidth: 2rem;\n\tvertical-align: top;\n}\n\n.action-rotation.gcd {\n\tmargin-left: 1em;\n}\n\n.action-rotation.gcd::before {\n\tcontent: '\\25B6'; /* Unicode character for right arrow */\n\tfont-size: 13px;\n\tcolor: rgba(255, 255, 255, 0.5);\n}\n\n@keyframes action-move {\n\tfrom {\n\t\ttransform: translateX(calc(100vw - 3rem));\n\t}\n \n\tto {\n\t\ttransform: translateX(-3rem);\n\t}\n}",".rotation-list {\n\tpadding: 0 18px;\n\tbackground-color: rgba(80, 80, 80, 0.3);\n\tdisplay: block;\n}\n\n.rotation-button {\n\tbackground-color: rgba(100, 100, 100, 0.3);\n\tcolor: rgba(255, 255, 255, 0.5);\n\tpadding: 0.1em;\n\twidth: 100vw;\n\tborder: none;\n\toutline: none;\n\ttransition: 0.4s;\n\tdisplay: block;\n}\n\n.rotation-button.expanded, .rotation-button:hover {\n\tbackground-color: rgba(120, 120, 120, 0.3);\n}\n\n.rotation-button:after {\n\tcontent: '\\25BC';\n\tfont-size: 13px;\n\tcolor: rgb(119,119,119);\n\tfloat: right;\n\tmargin-left: 5px;\n}\n\n.rotation-button.expanded:after {\n\tcontent: \"\\25B2\";\n}"]} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,41 @@ |
||||
/* |
||||
object-assign |
||||
(c) Sindre Sorhus |
||||
@license MIT |
||||
*/ |
||||
|
||||
/** @license React v0.20.1 |
||||
* scheduler.production.min.js |
||||
* |
||||
* Copyright (c) Facebook, Inc. and its affiliates. |
||||
* |
||||
* This source code is licensed under the MIT license found in the |
||||
* LICENSE file in the root directory of this source tree. |
||||
*/ |
||||
|
||||
/** @license React v17.0.1 |
||||
* react-dom.production.min.js |
||||
* |
||||
* Copyright (c) Facebook, Inc. and its affiliates. |
||||
* |
||||
* This source code is licensed under the MIT license found in the |
||||
* LICENSE file in the root directory of this source tree. |
||||
*/ |
||||
|
||||
/** @license React v17.0.1 |
||||
* react-jsx-runtime.production.min.js |
||||
* |
||||
* Copyright (c) Facebook, Inc. and its affiliates. |
||||
* |
||||
* This source code is licensed under the MIT license found in the |
||||
* LICENSE file in the root directory of this source tree. |
||||
*/ |
||||
|
||||
/** @license React v17.0.1 |
||||
* react.production.min.js |
||||
* |
||||
* Copyright (c) Facebook, Inc. and its affiliates. |
||||
* |
||||
* This source code is licensed under the MIT license found in the |
||||
* LICENSE file in the root directory of this source tree. |
||||
*/ |
File diff suppressed because one or more lines are too long
@ -0,0 +1,2 @@ |
||||
(this.webpackJsonpskilldisplay=this.webpackJsonpskilldisplay||[]).push([[0],{15:function(n,t,e){},17:function(n,t,e){},18:function(n,t,e){},19:function(n,t,e){"use strict";e.r(t);var a=e(0),o=e(1),c=e.n(o),r=e(4),i=e.n(r),s=e(2),u=e(8),d=function(){return/[?&]HOST_PORT=(wss?:\/\/[^&/]+)/.exec(window.location.search)};function f(n){return d()?l(n):function(n){var t=function(t){n.apply(void 0,Object(u.a)(t.detail))};return document.addEventListener("onLogLine",t),function(){document.removeEventListener("onLogLine",t)}}(n)}function l(n){var t="".concat(d()[1],"/BeforeLogLineRead")||!1,e=new WebSocket(t);return e.onerror=function(){return e.close()},e.onclose=function(){return setTimeout((function(){l(n)}),1e3)},e.onmessage=function(t,a){if("."===t.data)return e.send(".");var o=JSON.parse(t.data);return"SendCharName"===o.msgtype?n(o.msg):"Chat"===o.msgtype?n.apply(void 0,Object(u.a)(o.msg.split("|"))):void 0},function(){e.close()}}e(15);var v=e(7),m=e.n(v),p=e(9),j=(e(17),new Set([15997,15998,15999,16e3,16001,16002,16003,16004,16191,16192,16193,16194,16195,16196,7418,16484,16485,16486,2259,18805,2261,18806,2263,18807,2265,18873,18874,18875,2267,18877,2266,18876,2268,18878,16492,16471,16491,2270,18880,2269,18879,2271,18881,2272])),h=new Set([3559,116,114]),b=new Map;function g(n){var t=n.actionId,e=n.additionalClasses,o=c.a.useState(),r=Object(s.a)(o,2),i=r[0],u=r[1];return c.a.useEffect((function(){var n=b.get(t);if(null==n){var e=!0;return Object(p.a)(m.a.mark((function n(){var a;return m.a.wrap((function(n){for(;;)switch(n.prev=n.next){case 0:return n.next=2,fetch("https://xivapi.com/Action/".concat(t,"?columns=Icon,Name,ActionCategoryTargetID"),{mode:"cors"});case 2:return n.next=4,n.sent.json();case 4:a=n.sent,e&&(b.set(t,a),u(a));case 6:case"end":return n.stop()}}),n)})))(),function(){e=!1}}u(n)}),[t]),void 0!==i&&i.Icon?Object(a.jsx)("img",{className:j.has(t)||!h.has(t)&&4!==i.ActionCategoryTargetID?"gcd ".concat(e):"ogcd ".concat(e),src:"https://xivapi.com/".concat(i.Icon),alt:i.Name||""}):null}e(18);function O(n){var t=n.encounterId,e=n.name,o=n.actionList,r=c.a.useState(!1),i=Object(s.a)(r,2),u=i[0],d=i[1];return Object(a.jsxs)(a.Fragment,{children:[Object(a.jsx)("button",{className:u?"rotation-button expanded":"rotation-button",onClick:function(){d((function(n){return!n}))},children:0===t?"Current Rotation":e}),Object(a.jsx)(x,{expanded:u,actionList:o})]})}function x(n){var t=n.expanded,e=n.actionList;return t?Object(a.jsx)("div",{className:"rotation-list",children:e.map((function(n,t){return Object(a.jsx)(g,{actionId:n,additionalClasses:"action-rotation"},t)}))}):null}var w=new Set(["00","01","02","21","22","33"]);function I(){var n=c.a.useState([]),t=Object(s.a)(n,2),e=t[0],o=t[1],r=c.a.useState([]),u=Object(s.a)(r,2),d=u[0],l=u[1];return c.a.useEffect((function(){var n,t="",e=-1,a="Unknown",c=1,r=f((function(){for(var r=function(){l((function(n){return n[0]&&n[0].rotation&&n[0].rotation.length<=0&&n.shift(),n.unshift({name:a,rotation:[]}),n.slice(0,3)}))},s=arguments.length,u=new Array(s),d=0;d<s;d++)u[d]=arguments[d];if(1===u.length&&u[0].charID)return n=u[0].charID,void r();var f=u[0],v=u[1],m=u[2],p=u[3],j=u[4];if(w.has(f)){switch(f){case"00":return void("0038"===m&&"end"===j&&r());case"01":return void(a=p);case"02":return n=parseInt(m,16),void r();case"33":return void("40000012"!==p&&"40000010"!==p||r())}if(void 0!==n&&parseInt(m,16)===n){var h=parseInt(j,16);if(!((h<9||h>3e4)&&(h<100001||h>100300)||v===t&&h===e)){Date.now()-Date.parse(t)>12e4&&r(),t=v,e=h;var b=c%256+1;c=b,i.a.unstable_batchedUpdates((function(){o((function(n){return n.concat({action:h,key:b})})),l((function(n){return n[0]||(n[0]={name:a,rotation:[]}),n[0].rotation.push(h),n}))})),setTimeout((function(){o((function(n){return n.slice(1)}))}),1e4)}}}}));return function(){r()}}),[]),Object(a.jsx)(a.Fragment,{children:Object(a.jsxs)("div",{className:"container",children:[Object(a.jsx)("div",{className:"actions",children:e.map((function(n){var t=n.action,e=n.key;return Object(a.jsx)(g,{actionId:t,additionalClasses:"action-move"},e)}))}),d.map((function(n,t){return Object(a.jsx)(O,{encounterId:t,name:n.name,actionList:n.rotation},t)}))]})})}i.a.render(Object(a.jsx)(I,{}),document.getElementById("root"))}},[[19,1,2]]]); |
||||
//# sourceMappingURL=main.e1247fe5.chunk.js.map
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,2 @@ |
||||
!function(e){function r(r){for(var n,u,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)u=i[c],Object.prototype.hasOwnProperty.call(o,u)&&o[u]&&s.push(o[u][0]),o[u]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return l.push.apply(l,p||[]),t()}function t(){for(var e,r=0;r<l.length;r++){for(var t=l[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(l.splice(r--,1),e=u(u.s=t[0]))}return e}var n={},o={1:0},l=[];function u(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,u),t.l=!0,t.exports}u.m=e,u.c=n,u.d=function(e,r,t){u.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},u.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.t=function(e,r){if(1&r&&(e=u(e)),8&r)return e;if(4&r&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(u.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)u.d(t,n,function(r){return e[r]}.bind(null,n));return t},u.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(r,"a",r),r},u.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},u.p="/SkillDisplay/";var i=this.webpackJsonpskilldisplay=this.webpackJsonpskilldisplay||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([]); |
||||
//# sourceMappingURL=runtime-main.58acd0bf.js.map
|
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue