mirror of
https://github.com/captbaritone/webamp.git
synced 2026-01-23 18:25:30 +00:00
First stab at dashboard
Show the % of classes that are complete Use a table for the dashboard Enable dashboard via `modern/ready`
This commit is contained in:
parent
284e4b231a
commit
b0fc08bc6a
5 changed files with 674 additions and 480 deletions
|
|
@ -61,6 +61,14 @@ module.exports = {
|
|||
template: "../modern/index.html",
|
||||
chunks: ["modern"],
|
||||
}),
|
||||
// Ideally we could just do this via client-side routing, but it's tricky
|
||||
// with both the real app and this sub directory. So we just hack it to
|
||||
// duplicate the html file in both places and move on with our lives.
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "modern/ready/index.html",
|
||||
template: "../modern/index.html",
|
||||
chunks: ["modern"],
|
||||
}),
|
||||
// Automatically generates the manifest.json file inside the built
|
||||
// directory, and injects a tag into the gererated index.html file
|
||||
// it also, applies cache-busting for all the icons.
|
||||
|
|
@ -104,6 +112,7 @@ module.exports = {
|
|||
entry: {
|
||||
webamp: ["./js/index.js"],
|
||||
modern: ["../modern/src/index.js"],
|
||||
wat: ["../modern/src/index.js"],
|
||||
},
|
||||
context: path.resolve(__dirname, "../"),
|
||||
output: {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useEffect, useReducer } from "react";
|
||||
import React, { useEffect, useReducer, Suspense } from "react";
|
||||
import "./App.css";
|
||||
import * as Utils from "./utils";
|
||||
import * as Actions from "./Actions";
|
||||
|
|
@ -9,6 +9,7 @@ import { useDispatch, useSelector, useStore } from "react-redux";
|
|||
import DropTarget from "../../js/components/DropTarget";
|
||||
import Debugger from "./debugger";
|
||||
import Sidebar from "./Sidebar";
|
||||
const Dashboard = React.lazy(() => import("./Dashboard"));
|
||||
|
||||
const skinUrls = [
|
||||
cornerSkin,
|
||||
|
|
@ -647,7 +648,11 @@ function setSkinUrlToQueryParams(skinUrl) {
|
|||
window.history.pushState(null, "", newRelativePathQuery);
|
||||
}
|
||||
|
||||
function App() {
|
||||
function Loading() {
|
||||
return <h1>Loading...</h1>;
|
||||
}
|
||||
|
||||
function Modern() {
|
||||
const dispatch = useDispatch();
|
||||
const store = useStore();
|
||||
const root = useSelector(Selectors.getMakiTree);
|
||||
|
|
@ -656,7 +661,7 @@ function App() {
|
|||
dispatch(Actions.gotSkinUrl(defaultSkinUrl, store));
|
||||
}, [store]);
|
||||
if (root == null) {
|
||||
return <h1>Loading...</h1>;
|
||||
return <Loading />;
|
||||
}
|
||||
return (
|
||||
<div style={{ width: "100vw", height: "100vh", display: "flex" }}>
|
||||
|
|
@ -689,5 +694,12 @@ function App() {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
function App() {
|
||||
return (
|
||||
<Suspense fallback={<Loading />}>
|
||||
{window.location.pathname.includes("ready") ? <Dashboard /> : <Modern />}
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
|
|||
169
modern/src/Dashboard.tsx
Normal file
169
modern/src/Dashboard.tsx
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
import React from "react";
|
||||
import { objects } from "./maki-interpreter/objects";
|
||||
import snapshotString from "./maki-interpreter/__snapshots__/objects.test.js.snap";
|
||||
import methodData from "../resources/maki-skin-data.json";
|
||||
|
||||
const methodsSting =
|
||||
snapshotString["Maki classes Track unimplemented methods 1"];
|
||||
|
||||
const unimplemented = new Set(
|
||||
methodsSting.substring(1, methodsSting.length - 2).split("\n")
|
||||
);
|
||||
|
||||
const GREEN = "rgba(0, 255, 0, 0.2)";
|
||||
const RED = "rgba(255, 0, 0, 0.2)";
|
||||
|
||||
let METHOD_COUNT = 0;
|
||||
let IMPLEMENTED_METHOD_COUNT = 0;
|
||||
|
||||
const normalizedMethods = [];
|
||||
Object.keys(objects).forEach(key => {
|
||||
const makiObject = objects[key];
|
||||
makiObject.functions.forEach(method => {
|
||||
METHOD_COUNT++;
|
||||
const normalizedName = `${makiObject.name}.${method.name.toLowerCase()}`;
|
||||
const implemented = !unimplemented.has(normalizedName);
|
||||
if (implemented) {
|
||||
IMPLEMENTED_METHOD_COUNT++;
|
||||
}
|
||||
const foundInSkins = methodData.foundInSkins[normalizedName] || 0;
|
||||
const totalCalls = methodData.totalCalls[normalizedName] || 0;
|
||||
normalizedMethods.push({
|
||||
className: makiObject.name,
|
||||
totalCalls,
|
||||
foundInSkins,
|
||||
methodName: method.name,
|
||||
normalizedName,
|
||||
implemented,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function PercentBox({ number, total, label }) {
|
||||
const percent = total === 0 ? 1 : number / total;
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex" }}>
|
||||
<div
|
||||
style={{
|
||||
width: "100px",
|
||||
border: "1px solid lightgrey",
|
||||
marginRight: "10px",
|
||||
textAlign: "center",
|
||||
color: "lightgrey",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
{Math.round(percent * 100)}%
|
||||
<div
|
||||
style={{
|
||||
top: "0",
|
||||
position: "absolute",
|
||||
height: "100%",
|
||||
width: `${percent * 100}%`,
|
||||
backgroundColor: GREEN,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<span
|
||||
style={{
|
||||
textDecoration: percent === 1 ? "line-through" : null,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</span>{" "}
|
||||
<span style={{ color: "lightgrey" }}>
|
||||
({number}/{total})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function() {
|
||||
const [searchQuery, setSearchQuery] = React.useState("");
|
||||
const [sortKey, setSortKey] = React.useState("totalCalls");
|
||||
const [sortDirection, setSortDirection] = React.useState("ASC");
|
||||
function setOrToggleSort(key) {
|
||||
if (sortKey === key) {
|
||||
setSortDirection(dir => (dir === "ASC" ? "DESC" : "ASC"));
|
||||
} else {
|
||||
setSortKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
const sortAscending = (a, b) => (b[sortKey] > a[sortKey] ? 1 : -1);
|
||||
const sortDecending = (a, b) => (b[sortKey] < a[sortKey] ? 1 : -1);
|
||||
const sortFunction = sortDirection === "ASC" ? sortAscending : sortDecending;
|
||||
|
||||
let filterFunction: (string) => boolean = () => true;
|
||||
if (searchQuery) {
|
||||
const normalizedQuery = searchQuery.toLowerCase();
|
||||
|
||||
filterFunction = method => {
|
||||
return method.normalizedName.toLowerCase().includes(normalizedQuery);
|
||||
};
|
||||
}
|
||||
return (
|
||||
<div style={{ padding: "20px" }}>
|
||||
<h1>Are Modern Skins Ready Yet?</h1>
|
||||
<PercentBox
|
||||
number={IMPLEMENTED_METHOD_COUNT}
|
||||
total={METHOD_COUNT}
|
||||
label="Methods"
|
||||
/>
|
||||
<input
|
||||
placeholder={"Search..."}
|
||||
value={searchQuery}
|
||||
onChange={e => setSearchQuery(e.target.value)}
|
||||
/>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th onClick={() => setOrToggleSort("implemented")}>Status</th>
|
||||
<th onClick={() => setOrToggleSort("className")}>Class</th>
|
||||
<th onClick={() => setOrToggleSort("methodName")}>Method Name</th>
|
||||
<th onClick={() => setOrToggleSort("foundInSkins")}>
|
||||
Found In Skins
|
||||
</th>
|
||||
<th onClick={() => setOrToggleSort("totalCalls")}>Total Calls</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{normalizedMethods
|
||||
.sort(sortFunction)
|
||||
.filter(filterFunction)
|
||||
.map(
|
||||
({
|
||||
className,
|
||||
methodName,
|
||||
foundInSkins,
|
||||
totalCalls,
|
||||
implemented,
|
||||
}) => {
|
||||
return (
|
||||
<tr key={className + methodName}>
|
||||
<td>
|
||||
<span
|
||||
style={{
|
||||
display: "inline-block",
|
||||
padding: "10px",
|
||||
border: "1px solid lightgrey",
|
||||
backgroundColor: implemented ? GREEN : RED,
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
<td>{className}</td>
|
||||
<td>{methodName}</td>
|
||||
<td>{foundInSkins}</td>
|
||||
<td>{totalCalls}</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
477
modern/src/maki-interpreter/__snapshots__/objects.test.js.snap
Normal file
477
modern/src/maki-interpreter/__snapshots__/objects.test.js.snap
Normal file
|
|
@ -0,0 +1,477 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Maki classes Track unimplemented methods 1`] = `
|
||||
"System.getparam
|
||||
System.getskinname
|
||||
System.getplayitemstring
|
||||
System.geteq
|
||||
System.geteqband
|
||||
System.geteqpreamp
|
||||
System.getstatus
|
||||
System.getplayitemlength
|
||||
System.seekto
|
||||
System.newdynamiccontainer
|
||||
System.newgroup
|
||||
System.newgroupaslayout
|
||||
System.getnumcontainers
|
||||
System.enumcontainer
|
||||
System.getwac
|
||||
System.getplayitemmetadatastring
|
||||
System.getplayitemdisplaytitle
|
||||
System.getextfamily
|
||||
System.playfile
|
||||
System.play
|
||||
System.stop
|
||||
System.pause
|
||||
System.next
|
||||
System.previous
|
||||
System.eject
|
||||
System.getposition
|
||||
System.seteqband
|
||||
System.seteqpreamp
|
||||
System.seteq
|
||||
System.removepath
|
||||
System.getpath
|
||||
System.getextension
|
||||
System.setpublicstring
|
||||
System.setpublicint
|
||||
System.getpublicstring
|
||||
System.getpublicint
|
||||
System.getviewportwidthfrompoint
|
||||
System.getviewportheightfrompoint
|
||||
System.getviewportleft
|
||||
System.getviewportleftfrompoint
|
||||
System.getviewporttop
|
||||
System.getviewporttopfrompoint
|
||||
System.debugstring
|
||||
System.ddesend
|
||||
System.onlookforcomponent
|
||||
System.getcurappleft
|
||||
System.getcurapptop
|
||||
System.getcurappwidth
|
||||
System.getcurappheight
|
||||
System.isappactive
|
||||
System.switchskin
|
||||
System.isloadingskin
|
||||
System.lockui
|
||||
System.unlockui
|
||||
System.getmainbrowser
|
||||
System.popmainbrowser
|
||||
System.navigateurl
|
||||
System.isobjectvalid
|
||||
System.setmenutransparency
|
||||
System.ongetcancelcomponent
|
||||
System.iskeydown
|
||||
System.setclipboardtext
|
||||
System.selectfile
|
||||
System.systemmenu
|
||||
System.windowmenu
|
||||
System.triggeraction
|
||||
System.showwindow
|
||||
System.hidewindow
|
||||
System.hidenamedwindow
|
||||
System.isnamedwindowvisible
|
||||
System.setatom
|
||||
System.getatom
|
||||
System.invokedebugger
|
||||
System.isvideo
|
||||
System.isvideofullscreen
|
||||
System.getidealvideowidth
|
||||
System.getidealvideoheight
|
||||
System.isminimized
|
||||
System.minimizeapplication
|
||||
System.restoreapplication
|
||||
System.activateapplication
|
||||
System.getplaylistlength
|
||||
System.getplaylistindex
|
||||
System.isdesktopalphaavailable
|
||||
System.istransparencyavailable
|
||||
System.getsonginfotext
|
||||
System.getvisband
|
||||
Wac.getguid
|
||||
Wac.getname
|
||||
Wac.sendcommand
|
||||
Wac.show
|
||||
Wac.hide
|
||||
Wac.isvisible
|
||||
Wac.setstatusbar
|
||||
Wac.getstatusbar
|
||||
Map.loadmap
|
||||
Map.getwidth
|
||||
Map.getheight
|
||||
Map.getvalue
|
||||
Map.inregion
|
||||
Map.getregion
|
||||
Region.loadfrommap
|
||||
Region.offset
|
||||
Region.add
|
||||
Region.sub
|
||||
Region.stretch
|
||||
Region.copy
|
||||
Region.loadfrombitmap
|
||||
Region.getboundingboxx
|
||||
Region.getboundingboxy
|
||||
Region.getboundingboxw
|
||||
Region.getboundingboxh
|
||||
Timer.getskipped
|
||||
Group.getnumobjects
|
||||
Group.enumobject
|
||||
Group.islayout
|
||||
GuiObject.getalpha
|
||||
GuiObject.setenabled
|
||||
GuiObject.getenabled
|
||||
GuiObject.ismouseover
|
||||
GuiObject.settargetx
|
||||
GuiObject.settargety
|
||||
GuiObject.settargetw
|
||||
GuiObject.settargeth
|
||||
GuiObject.settargeta
|
||||
GuiObject.settargetspeed
|
||||
GuiObject.gototarget
|
||||
GuiObject.canceltarget
|
||||
GuiObject.reversetarget
|
||||
GuiObject.isgoingtotarget
|
||||
GuiObject.bringtofront
|
||||
GuiObject.bringtoback
|
||||
GuiObject.bringabove
|
||||
GuiObject.bringbelow
|
||||
GuiObject.getguix
|
||||
GuiObject.getguiy
|
||||
GuiObject.getguiw
|
||||
GuiObject.getguih
|
||||
GuiObject.getguirelatx
|
||||
GuiObject.getguirelaty
|
||||
GuiObject.getguirelatw
|
||||
GuiObject.getguirelath
|
||||
GuiObject.isactive
|
||||
GuiObject.gettopparent
|
||||
GuiObject.runmodal
|
||||
GuiObject.endmodal
|
||||
GuiObject.findobjectxy
|
||||
GuiObject.getname
|
||||
GuiObject.clienttoscreenx
|
||||
GuiObject.clienttoscreeny
|
||||
GuiObject.clienttoscreenw
|
||||
GuiObject.clienttoscreenh
|
||||
GuiObject.screentoclientx
|
||||
GuiObject.screentoclienty
|
||||
GuiObject.screentoclientw
|
||||
GuiObject.screentoclienth
|
||||
GuiObject.getautowidth
|
||||
GuiObject.getautoheight
|
||||
GuiObject.setfocus
|
||||
GuiObject.ismouseoverrect
|
||||
GuiObject.getinterface
|
||||
GuiObject.sendaction
|
||||
GuiObject.onaction
|
||||
Button.setactivated
|
||||
Button.getactivated
|
||||
Button.setactivatednocallback
|
||||
AnimatedLayer.ispaused
|
||||
AnimatedLayer.isstopped
|
||||
AnimatedLayer.getdirection
|
||||
AnimatedLayer.setrealtime
|
||||
ToggleButton.getcurcfgval
|
||||
PopupMenu.checkcommand
|
||||
PopupMenu.addsubmenu
|
||||
PopupMenu.popatxy
|
||||
PopupMenu.getnumcommands
|
||||
PopupMenu.disablecommand
|
||||
Container.getnumlayouts
|
||||
Container.enumlayout
|
||||
Container.switchtolayout
|
||||
Container.close
|
||||
Container.toggle
|
||||
Container.isdynamic
|
||||
Container.setname
|
||||
Container.getcurlayout
|
||||
Layout.getscale
|
||||
Layout.setscale
|
||||
Layout.setdesktopalpha
|
||||
Layout.getdesktopalpha
|
||||
Layout.center
|
||||
Layout.snapadjust
|
||||
Layout.getsnapadjusttop
|
||||
Layout.getsnapadjustright
|
||||
Layout.getsnapadjustleft
|
||||
Layout.getsnapadjustbottom
|
||||
Layout.setredrawonresize
|
||||
Layout.beforeredock
|
||||
Layout.redock
|
||||
Layout.istransparencysafe
|
||||
Layout.islayoutanimationsafe
|
||||
List.additem
|
||||
List.removeitem
|
||||
List.enumitem
|
||||
List.finditem
|
||||
List.getnumitems
|
||||
List.removeall
|
||||
Layer.setregion
|
||||
Layer.setregionfrommap
|
||||
Layer.fx_oninit
|
||||
Layer.fx_onframe
|
||||
Layer.fx_ongetpixelr
|
||||
Layer.fx_ongetpixeld
|
||||
Layer.fx_ongetpixelx
|
||||
Layer.fx_ongetpixely
|
||||
Layer.fx_ongetpixela
|
||||
Layer.fx_setenabled
|
||||
Layer.fx_getenabled
|
||||
Layer.fx_setwrap
|
||||
Layer.fx_getwrap
|
||||
Layer.fx_setrect
|
||||
Layer.fx_getrect
|
||||
Layer.fx_setbgfx
|
||||
Layer.fx_getbgfx
|
||||
Layer.fx_setclear
|
||||
Layer.fx_getclear
|
||||
Layer.fx_setspeed
|
||||
Layer.fx_getspeed
|
||||
Layer.fx_setrealtime
|
||||
Layer.fx_getrealtime
|
||||
Layer.fx_setlocalized
|
||||
Layer.fx_getlocalized
|
||||
Layer.fx_setbilinear
|
||||
Layer.fx_getbilinear
|
||||
Layer.fx_setalphamode
|
||||
Layer.fx_getalphamode
|
||||
Layer.fx_setgridsize
|
||||
Layer.fx_update
|
||||
Layer.fx_restart
|
||||
Text.setalternatetext
|
||||
Text.settext
|
||||
Text.gettext
|
||||
Text.gettextwidth
|
||||
Component.getguid
|
||||
Component.getwac
|
||||
Component.setregionfrommap
|
||||
Component.setregion
|
||||
Component.setacceptwac
|
||||
Component.getcontent
|
||||
ComponentBucket.getmaxheight
|
||||
ComponentBucket.getmaxwidth
|
||||
ComponentBucket.setscroll
|
||||
ComponentBucket.getscroll
|
||||
ComponentBucket.getnumchildren
|
||||
ComponentBucket.enumchildren
|
||||
Edit.settext
|
||||
Edit.setautoenter
|
||||
Edit.getautoenter
|
||||
Edit.gettext
|
||||
Edit.selectall
|
||||
Edit.enter
|
||||
Edit.setidleenabled
|
||||
Edit.getidleenabled
|
||||
Slider.getposition
|
||||
Slider.setposition
|
||||
Slider.lock
|
||||
Slider.unlock
|
||||
Vis.setmode
|
||||
Vis.setrealtime
|
||||
Vis.getrealtime
|
||||
Vis.getmode
|
||||
Vis.nextmode
|
||||
Browser.navigateurl
|
||||
Browser.back
|
||||
Browser.forward
|
||||
Browser.stop
|
||||
Browser.refresh
|
||||
Browser.home
|
||||
Browser.settargetname
|
||||
GroupList.instantiate
|
||||
GroupList.getnumitems
|
||||
GroupList.enumitem
|
||||
GroupList.removeall
|
||||
GroupList.scrolltopercent
|
||||
CfgGroup.cfggetint
|
||||
CfgGroup.cfgsetint
|
||||
CfgGroup.cfggetstring
|
||||
CfgGroup.cfggetfloat
|
||||
CfgGroup.cfgsetfloat
|
||||
CfgGroup.cfgsetstring
|
||||
CfgGroup.cfggetguid
|
||||
CfgGroup.cfggetname
|
||||
MouseRedir.setredirection
|
||||
MouseRedir.getredirection
|
||||
MouseRedir.setregionfrommap
|
||||
MouseRedir.setregion
|
||||
DropDownList.getitemselected
|
||||
DropDownList.setlistheight
|
||||
DropDownList.openlist
|
||||
DropDownList.closelist
|
||||
DropDownList.setitems
|
||||
DropDownList.additem
|
||||
DropDownList.delitem
|
||||
DropDownList.finditem
|
||||
DropDownList.getnumitems
|
||||
DropDownList.selectitem
|
||||
DropDownList.getitemtext
|
||||
DropDownList.getselected
|
||||
DropDownList.getselectedtext
|
||||
DropDownList.getcustomtext
|
||||
DropDownList.deleteallitems
|
||||
DropDownList.setnoitemtext
|
||||
LayoutStatus.callme
|
||||
TabSheet.getcurpage
|
||||
TabSheet.setcurpage
|
||||
GuiList.getnumitems
|
||||
GuiList.getwantautodeselect
|
||||
GuiList.setwantautodeselect
|
||||
GuiList.setautosort
|
||||
GuiList.next
|
||||
GuiList.selectcurrent
|
||||
GuiList.selectfirstentry
|
||||
GuiList.previous
|
||||
GuiList.pagedown
|
||||
GuiList.pageup
|
||||
GuiList.home
|
||||
GuiList.end
|
||||
GuiList.reset
|
||||
GuiList.addcolumn
|
||||
GuiList.getnumcolumns
|
||||
GuiList.getcolumnwidth
|
||||
GuiList.setcolumnwidth
|
||||
GuiList.getcolumnlabel
|
||||
GuiList.setcolumnlabel
|
||||
GuiList.getcolumnnumeric
|
||||
GuiList.setcolumndynamic
|
||||
GuiList.iscolumndynamic
|
||||
GuiList.setminimumsize
|
||||
GuiList.additem
|
||||
GuiList.insertitem
|
||||
GuiList.getlastaddeditempos
|
||||
GuiList.setsubitem
|
||||
GuiList.deleteallitems
|
||||
GuiList.deletebypos
|
||||
GuiList.getitemlabel
|
||||
GuiList.setitemlabel
|
||||
GuiList.getitemselected
|
||||
GuiList.isitemfocused
|
||||
GuiList.getitemfocused
|
||||
GuiList.setitemfocused
|
||||
GuiList.ensureitemvisible
|
||||
GuiList.invalidatecolumns
|
||||
GuiList.scrollabsolute
|
||||
GuiList.scrollrelative
|
||||
GuiList.scrollleft
|
||||
GuiList.scrollright
|
||||
GuiList.scrollup
|
||||
GuiList.scrolldown
|
||||
GuiList.getsubitemtext
|
||||
GuiList.getfirstitemselected
|
||||
GuiList.getnextitemselected
|
||||
GuiList.selectall
|
||||
GuiList.deselectall
|
||||
GuiList.invertselection
|
||||
GuiList.invalidateitem
|
||||
GuiList.getfirstitemvisible
|
||||
GuiList.getlastitemvisible
|
||||
GuiList.setfontsize
|
||||
GuiList.getfontsize
|
||||
GuiList.jumptonext
|
||||
GuiList.scrolltoitem
|
||||
GuiList.resort
|
||||
GuiList.getsortdirection
|
||||
GuiList.getsortcolumn
|
||||
GuiList.setsortcolumn
|
||||
GuiList.setsortdirection
|
||||
GuiList.getitemcount
|
||||
GuiList.setselectionstart
|
||||
GuiList.setselectionend
|
||||
GuiList.setselected
|
||||
GuiList.toggleselection
|
||||
GuiList.getheaderheight
|
||||
GuiList.getpreventmultipleselection
|
||||
GuiList.setpreventmultipleselection
|
||||
GuiList.moveitem
|
||||
GuiList.onrightclick
|
||||
GuiList.oncolumndblclick
|
||||
GuiList.oncolumnlabelclick
|
||||
GuiTree.onwantautocontextmenu
|
||||
GuiTree.onmousewheelup
|
||||
GuiTree.onmousewheeldown
|
||||
GuiTree.oncontextmenu
|
||||
GuiTree.onchar
|
||||
GuiTree.getnumrootitems
|
||||
GuiTree.enumrootitem
|
||||
GuiTree.jumptonext
|
||||
GuiTree.ensureitemvisible
|
||||
GuiTree.getcontentswidth
|
||||
GuiTree.getcontentsheight
|
||||
GuiTree.addtreeitem
|
||||
GuiTree.removetreeitem
|
||||
GuiTree.movetreeitem
|
||||
GuiTree.deleteallitems
|
||||
GuiTree.expanditem
|
||||
GuiTree.expanditemdeferred
|
||||
GuiTree.collapseitem
|
||||
GuiTree.collapseitemdeferred
|
||||
GuiTree.selectitem
|
||||
GuiTree.selectitemdeferred
|
||||
GuiTree.delitemdeferred
|
||||
GuiTree.hiliteitem
|
||||
GuiTree.unhiliteitem
|
||||
GuiTree.getcuritem
|
||||
GuiTree.hittest
|
||||
GuiTree.edititemlabel
|
||||
GuiTree.canceleditlabel
|
||||
GuiTree.setautoedit
|
||||
GuiTree.getautoedit
|
||||
GuiTree.getbylabel
|
||||
GuiTree.setsorted
|
||||
GuiTree.getsorted
|
||||
GuiTree.sorttreeitems
|
||||
GuiTree.getsibling
|
||||
GuiTree.setautocollapse
|
||||
GuiTree.setfontsize
|
||||
GuiTree.getfontsize
|
||||
GuiTree.getnumvisiblechilditems
|
||||
GuiTree.getnumvisibleitems
|
||||
GuiTree.enumvisibleitems
|
||||
GuiTree.enumvisiblechilditems
|
||||
GuiTree.enumallitems
|
||||
GuiTree.getitemrectx
|
||||
GuiTree.getitemrecty
|
||||
GuiTree.getitemrectw
|
||||
GuiTree.getitemrecth
|
||||
GuiTree.getitemfrompoint
|
||||
TreeItem.getnumchildren
|
||||
TreeItem.setlabel
|
||||
TreeItem.getlabel
|
||||
TreeItem.ensurevisible
|
||||
TreeItem.getnthchild
|
||||
TreeItem.getchild
|
||||
TreeItem.getchildsibling
|
||||
TreeItem.getsibling
|
||||
TreeItem.getparent
|
||||
TreeItem.editlabel
|
||||
TreeItem.hassubitems
|
||||
TreeItem.setsorted
|
||||
TreeItem.setchildtab
|
||||
TreeItem.issorted
|
||||
TreeItem.iscollapsed
|
||||
TreeItem.isexpanded
|
||||
TreeItem.invalidate
|
||||
TreeItem.isselected
|
||||
TreeItem.ishilited
|
||||
TreeItem.sethilited
|
||||
TreeItem.collapse
|
||||
TreeItem.expand
|
||||
TreeItem.gettree
|
||||
MenuButton.openmenu
|
||||
MenuButton.closemenu
|
||||
CheckBox.setchecked
|
||||
CheckBox.ischecked
|
||||
CheckBox.settext
|
||||
CheckBox.gettext
|
||||
Config.newitem
|
||||
Config.getitem
|
||||
Config.getitembyguid
|
||||
ConfigItem.getattribute
|
||||
ConfigItem.newattribute
|
||||
ConfigItem.getguid
|
||||
ConfigAttribute.setdata
|
||||
ConfigAttribute.getdata
|
||||
ConfigAttribute.getparentitem
|
||||
ConfigAttribute.getattributename"
|
||||
`;
|
||||
|
|
@ -89,482 +89,9 @@ describe("Maki classes", () => {
|
|||
});
|
||||
|
||||
test("Track unimplemented methods", () => {
|
||||
expect(unimplementedRuntimeMethods).toMatchInlineSnapshot(`
|
||||
Set {
|
||||
"System.getparam",
|
||||
"System.getskinname",
|
||||
"System.getplayitemstring",
|
||||
"System.geteq",
|
||||
"System.geteqband",
|
||||
"System.geteqpreamp",
|
||||
"System.getstatus",
|
||||
"System.getplayitemlength",
|
||||
"System.seekto",
|
||||
"System.newdynamiccontainer",
|
||||
"System.newgroup",
|
||||
"System.newgroupaslayout",
|
||||
"System.getnumcontainers",
|
||||
"System.enumcontainer",
|
||||
"System.getwac",
|
||||
"System.getplayitemmetadatastring",
|
||||
"System.getplayitemdisplaytitle",
|
||||
"System.getextfamily",
|
||||
"System.playfile",
|
||||
"System.play",
|
||||
"System.stop",
|
||||
"System.pause",
|
||||
"System.next",
|
||||
"System.previous",
|
||||
"System.eject",
|
||||
"System.getposition",
|
||||
"System.seteqband",
|
||||
"System.seteqpreamp",
|
||||
"System.seteq",
|
||||
"System.removepath",
|
||||
"System.getpath",
|
||||
"System.getextension",
|
||||
"System.setpublicstring",
|
||||
"System.setpublicint",
|
||||
"System.getpublicstring",
|
||||
"System.getpublicint",
|
||||
"System.getviewportwidthfrompoint",
|
||||
"System.getviewportheightfrompoint",
|
||||
"System.getviewportleft",
|
||||
"System.getviewportleftfrompoint",
|
||||
"System.getviewporttop",
|
||||
"System.getviewporttopfrompoint",
|
||||
"System.debugstring",
|
||||
"System.ddesend",
|
||||
"System.onlookforcomponent",
|
||||
"System.getcurappleft",
|
||||
"System.getcurapptop",
|
||||
"System.getcurappwidth",
|
||||
"System.getcurappheight",
|
||||
"System.isappactive",
|
||||
"System.switchskin",
|
||||
"System.isloadingskin",
|
||||
"System.lockui",
|
||||
"System.unlockui",
|
||||
"System.getmainbrowser",
|
||||
"System.popmainbrowser",
|
||||
"System.navigateurl",
|
||||
"System.isobjectvalid",
|
||||
"System.setmenutransparency",
|
||||
"System.ongetcancelcomponent",
|
||||
"System.iskeydown",
|
||||
"System.setclipboardtext",
|
||||
"System.selectfile",
|
||||
"System.systemmenu",
|
||||
"System.windowmenu",
|
||||
"System.triggeraction",
|
||||
"System.showwindow",
|
||||
"System.hidewindow",
|
||||
"System.hidenamedwindow",
|
||||
"System.isnamedwindowvisible",
|
||||
"System.setatom",
|
||||
"System.getatom",
|
||||
"System.invokedebugger",
|
||||
"System.isvideo",
|
||||
"System.isvideofullscreen",
|
||||
"System.getidealvideowidth",
|
||||
"System.getidealvideoheight",
|
||||
"System.isminimized",
|
||||
"System.minimizeapplication",
|
||||
"System.restoreapplication",
|
||||
"System.activateapplication",
|
||||
"System.getplaylistlength",
|
||||
"System.getplaylistindex",
|
||||
"System.isdesktopalphaavailable",
|
||||
"System.istransparencyavailable",
|
||||
"System.getsonginfotext",
|
||||
"System.getvisband",
|
||||
"Wac.getguid",
|
||||
"Wac.getname",
|
||||
"Wac.sendcommand",
|
||||
"Wac.show",
|
||||
"Wac.hide",
|
||||
"Wac.isvisible",
|
||||
"Wac.setstatusbar",
|
||||
"Wac.getstatusbar",
|
||||
"Map.loadmap",
|
||||
"Map.getwidth",
|
||||
"Map.getheight",
|
||||
"Map.getvalue",
|
||||
"Map.inregion",
|
||||
"Map.getregion",
|
||||
"Region.loadfrommap",
|
||||
"Region.offset",
|
||||
"Region.add",
|
||||
"Region.sub",
|
||||
"Region.stretch",
|
||||
"Region.copy",
|
||||
"Region.loadfrombitmap",
|
||||
"Region.getboundingboxx",
|
||||
"Region.getboundingboxy",
|
||||
"Region.getboundingboxw",
|
||||
"Region.getboundingboxh",
|
||||
"Timer.getskipped",
|
||||
"Group.getnumobjects",
|
||||
"Group.enumobject",
|
||||
"Group.islayout",
|
||||
"GuiObject.getalpha",
|
||||
"GuiObject.setenabled",
|
||||
"GuiObject.getenabled",
|
||||
"GuiObject.ismouseover",
|
||||
"GuiObject.settargetx",
|
||||
"GuiObject.settargety",
|
||||
"GuiObject.settargetw",
|
||||
"GuiObject.settargeth",
|
||||
"GuiObject.settargeta",
|
||||
"GuiObject.settargetspeed",
|
||||
"GuiObject.gototarget",
|
||||
"GuiObject.canceltarget",
|
||||
"GuiObject.reversetarget",
|
||||
"GuiObject.isgoingtotarget",
|
||||
"GuiObject.bringtofront",
|
||||
"GuiObject.bringtoback",
|
||||
"GuiObject.bringabove",
|
||||
"GuiObject.bringbelow",
|
||||
"GuiObject.getguix",
|
||||
"GuiObject.getguiy",
|
||||
"GuiObject.getguiw",
|
||||
"GuiObject.getguih",
|
||||
"GuiObject.getguirelatx",
|
||||
"GuiObject.getguirelaty",
|
||||
"GuiObject.getguirelatw",
|
||||
"GuiObject.getguirelath",
|
||||
"GuiObject.isactive",
|
||||
"GuiObject.gettopparent",
|
||||
"GuiObject.runmodal",
|
||||
"GuiObject.endmodal",
|
||||
"GuiObject.findobjectxy",
|
||||
"GuiObject.getname",
|
||||
"GuiObject.clienttoscreenx",
|
||||
"GuiObject.clienttoscreeny",
|
||||
"GuiObject.clienttoscreenw",
|
||||
"GuiObject.clienttoscreenh",
|
||||
"GuiObject.screentoclientx",
|
||||
"GuiObject.screentoclienty",
|
||||
"GuiObject.screentoclientw",
|
||||
"GuiObject.screentoclienth",
|
||||
"GuiObject.getautowidth",
|
||||
"GuiObject.getautoheight",
|
||||
"GuiObject.setfocus",
|
||||
"GuiObject.ismouseoverrect",
|
||||
"GuiObject.getinterface",
|
||||
"GuiObject.sendaction",
|
||||
"GuiObject.onaction",
|
||||
"Button.setactivated",
|
||||
"Button.getactivated",
|
||||
"Button.setactivatednocallback",
|
||||
"AnimatedLayer.ispaused",
|
||||
"AnimatedLayer.isstopped",
|
||||
"AnimatedLayer.getdirection",
|
||||
"AnimatedLayer.setrealtime",
|
||||
"ToggleButton.getcurcfgval",
|
||||
"PopupMenu.checkcommand",
|
||||
"PopupMenu.addsubmenu",
|
||||
"PopupMenu.popatxy",
|
||||
"PopupMenu.getnumcommands",
|
||||
"PopupMenu.disablecommand",
|
||||
"Container.getnumlayouts",
|
||||
"Container.enumlayout",
|
||||
"Container.switchtolayout",
|
||||
"Container.close",
|
||||
"Container.toggle",
|
||||
"Container.isdynamic",
|
||||
"Container.setname",
|
||||
"Container.getcurlayout",
|
||||
"Layout.getscale",
|
||||
"Layout.setscale",
|
||||
"Layout.setdesktopalpha",
|
||||
"Layout.getdesktopalpha",
|
||||
"Layout.center",
|
||||
"Layout.snapadjust",
|
||||
"Layout.getsnapadjusttop",
|
||||
"Layout.getsnapadjustright",
|
||||
"Layout.getsnapadjustleft",
|
||||
"Layout.getsnapadjustbottom",
|
||||
"Layout.setredrawonresize",
|
||||
"Layout.beforeredock",
|
||||
"Layout.redock",
|
||||
"Layout.istransparencysafe",
|
||||
"Layout.islayoutanimationsafe",
|
||||
"List.additem",
|
||||
"List.removeitem",
|
||||
"List.enumitem",
|
||||
"List.finditem",
|
||||
"List.getnumitems",
|
||||
"List.removeall",
|
||||
"Layer.setregion",
|
||||
"Layer.setregionfrommap",
|
||||
"Layer.fx_oninit",
|
||||
"Layer.fx_onframe",
|
||||
"Layer.fx_ongetpixelr",
|
||||
"Layer.fx_ongetpixeld",
|
||||
"Layer.fx_ongetpixelx",
|
||||
"Layer.fx_ongetpixely",
|
||||
"Layer.fx_ongetpixela",
|
||||
"Layer.fx_setenabled",
|
||||
"Layer.fx_getenabled",
|
||||
"Layer.fx_setwrap",
|
||||
"Layer.fx_getwrap",
|
||||
"Layer.fx_setrect",
|
||||
"Layer.fx_getrect",
|
||||
"Layer.fx_setbgfx",
|
||||
"Layer.fx_getbgfx",
|
||||
"Layer.fx_setclear",
|
||||
"Layer.fx_getclear",
|
||||
"Layer.fx_setspeed",
|
||||
"Layer.fx_getspeed",
|
||||
"Layer.fx_setrealtime",
|
||||
"Layer.fx_getrealtime",
|
||||
"Layer.fx_setlocalized",
|
||||
"Layer.fx_getlocalized",
|
||||
"Layer.fx_setbilinear",
|
||||
"Layer.fx_getbilinear",
|
||||
"Layer.fx_setalphamode",
|
||||
"Layer.fx_getalphamode",
|
||||
"Layer.fx_setgridsize",
|
||||
"Layer.fx_update",
|
||||
"Layer.fx_restart",
|
||||
"Text.setalternatetext",
|
||||
"Text.settext",
|
||||
"Text.gettext",
|
||||
"Text.gettextwidth",
|
||||
"Component.getguid",
|
||||
"Component.getwac",
|
||||
"Component.setregionfrommap",
|
||||
"Component.setregion",
|
||||
"Component.setacceptwac",
|
||||
"Component.getcontent",
|
||||
"ComponentBucket.getmaxheight",
|
||||
"ComponentBucket.getmaxwidth",
|
||||
"ComponentBucket.setscroll",
|
||||
"ComponentBucket.getscroll",
|
||||
"ComponentBucket.getnumchildren",
|
||||
"ComponentBucket.enumchildren",
|
||||
"Edit.settext",
|
||||
"Edit.setautoenter",
|
||||
"Edit.getautoenter",
|
||||
"Edit.gettext",
|
||||
"Edit.selectall",
|
||||
"Edit.enter",
|
||||
"Edit.setidleenabled",
|
||||
"Edit.getidleenabled",
|
||||
"Slider.getposition",
|
||||
"Slider.setposition",
|
||||
"Slider.lock",
|
||||
"Slider.unlock",
|
||||
"Vis.setmode",
|
||||
"Vis.setrealtime",
|
||||
"Vis.getrealtime",
|
||||
"Vis.getmode",
|
||||
"Vis.nextmode",
|
||||
"Browser.navigateurl",
|
||||
"Browser.back",
|
||||
"Browser.forward",
|
||||
"Browser.stop",
|
||||
"Browser.refresh",
|
||||
"Browser.home",
|
||||
"Browser.settargetname",
|
||||
"GroupList.instantiate",
|
||||
"GroupList.getnumitems",
|
||||
"GroupList.enumitem",
|
||||
"GroupList.removeall",
|
||||
"GroupList.scrolltopercent",
|
||||
"CfgGroup.cfggetint",
|
||||
"CfgGroup.cfgsetint",
|
||||
"CfgGroup.cfggetstring",
|
||||
"CfgGroup.cfggetfloat",
|
||||
"CfgGroup.cfgsetfloat",
|
||||
"CfgGroup.cfgsetstring",
|
||||
"CfgGroup.cfggetguid",
|
||||
"CfgGroup.cfggetname",
|
||||
"MouseRedir.setredirection",
|
||||
"MouseRedir.getredirection",
|
||||
"MouseRedir.setregionfrommap",
|
||||
"MouseRedir.setregion",
|
||||
"DropDownList.getitemselected",
|
||||
"DropDownList.setlistheight",
|
||||
"DropDownList.openlist",
|
||||
"DropDownList.closelist",
|
||||
"DropDownList.setitems",
|
||||
"DropDownList.additem",
|
||||
"DropDownList.delitem",
|
||||
"DropDownList.finditem",
|
||||
"DropDownList.getnumitems",
|
||||
"DropDownList.selectitem",
|
||||
"DropDownList.getitemtext",
|
||||
"DropDownList.getselected",
|
||||
"DropDownList.getselectedtext",
|
||||
"DropDownList.getcustomtext",
|
||||
"DropDownList.deleteallitems",
|
||||
"DropDownList.setnoitemtext",
|
||||
"LayoutStatus.callme",
|
||||
"TabSheet.getcurpage",
|
||||
"TabSheet.setcurpage",
|
||||
"GuiList.getnumitems",
|
||||
"GuiList.getwantautodeselect",
|
||||
"GuiList.setwantautodeselect",
|
||||
"GuiList.setautosort",
|
||||
"GuiList.next",
|
||||
"GuiList.selectcurrent",
|
||||
"GuiList.selectfirstentry",
|
||||
"GuiList.previous",
|
||||
"GuiList.pagedown",
|
||||
"GuiList.pageup",
|
||||
"GuiList.home",
|
||||
"GuiList.end",
|
||||
"GuiList.reset",
|
||||
"GuiList.addcolumn",
|
||||
"GuiList.getnumcolumns",
|
||||
"GuiList.getcolumnwidth",
|
||||
"GuiList.setcolumnwidth",
|
||||
"GuiList.getcolumnlabel",
|
||||
"GuiList.setcolumnlabel",
|
||||
"GuiList.getcolumnnumeric",
|
||||
"GuiList.setcolumndynamic",
|
||||
"GuiList.iscolumndynamic",
|
||||
"GuiList.setminimumsize",
|
||||
"GuiList.additem",
|
||||
"GuiList.insertitem",
|
||||
"GuiList.getlastaddeditempos",
|
||||
"GuiList.setsubitem",
|
||||
"GuiList.deleteallitems",
|
||||
"GuiList.deletebypos",
|
||||
"GuiList.getitemlabel",
|
||||
"GuiList.setitemlabel",
|
||||
"GuiList.getitemselected",
|
||||
"GuiList.isitemfocused",
|
||||
"GuiList.getitemfocused",
|
||||
"GuiList.setitemfocused",
|
||||
"GuiList.ensureitemvisible",
|
||||
"GuiList.invalidatecolumns",
|
||||
"GuiList.scrollabsolute",
|
||||
"GuiList.scrollrelative",
|
||||
"GuiList.scrollleft",
|
||||
"GuiList.scrollright",
|
||||
"GuiList.scrollup",
|
||||
"GuiList.scrolldown",
|
||||
"GuiList.getsubitemtext",
|
||||
"GuiList.getfirstitemselected",
|
||||
"GuiList.getnextitemselected",
|
||||
"GuiList.selectall",
|
||||
"GuiList.deselectall",
|
||||
"GuiList.invertselection",
|
||||
"GuiList.invalidateitem",
|
||||
"GuiList.getfirstitemvisible",
|
||||
"GuiList.getlastitemvisible",
|
||||
"GuiList.setfontsize",
|
||||
"GuiList.getfontsize",
|
||||
"GuiList.jumptonext",
|
||||
"GuiList.scrolltoitem",
|
||||
"GuiList.resort",
|
||||
"GuiList.getsortdirection",
|
||||
"GuiList.getsortcolumn",
|
||||
"GuiList.setsortcolumn",
|
||||
"GuiList.setsortdirection",
|
||||
"GuiList.getitemcount",
|
||||
"GuiList.setselectionstart",
|
||||
"GuiList.setselectionend",
|
||||
"GuiList.setselected",
|
||||
"GuiList.toggleselection",
|
||||
"GuiList.getheaderheight",
|
||||
"GuiList.getpreventmultipleselection",
|
||||
"GuiList.setpreventmultipleselection",
|
||||
"GuiList.moveitem",
|
||||
"GuiList.onrightclick",
|
||||
"GuiList.oncolumndblclick",
|
||||
"GuiList.oncolumnlabelclick",
|
||||
"GuiTree.onwantautocontextmenu",
|
||||
"GuiTree.onmousewheelup",
|
||||
"GuiTree.onmousewheeldown",
|
||||
"GuiTree.oncontextmenu",
|
||||
"GuiTree.onchar",
|
||||
"GuiTree.getnumrootitems",
|
||||
"GuiTree.enumrootitem",
|
||||
"GuiTree.jumptonext",
|
||||
"GuiTree.ensureitemvisible",
|
||||
"GuiTree.getcontentswidth",
|
||||
"GuiTree.getcontentsheight",
|
||||
"GuiTree.addtreeitem",
|
||||
"GuiTree.removetreeitem",
|
||||
"GuiTree.movetreeitem",
|
||||
"GuiTree.deleteallitems",
|
||||
"GuiTree.expanditem",
|
||||
"GuiTree.expanditemdeferred",
|
||||
"GuiTree.collapseitem",
|
||||
"GuiTree.collapseitemdeferred",
|
||||
"GuiTree.selectitem",
|
||||
"GuiTree.selectitemdeferred",
|
||||
"GuiTree.delitemdeferred",
|
||||
"GuiTree.hiliteitem",
|
||||
"GuiTree.unhiliteitem",
|
||||
"GuiTree.getcuritem",
|
||||
"GuiTree.hittest",
|
||||
"GuiTree.edititemlabel",
|
||||
"GuiTree.canceleditlabel",
|
||||
"GuiTree.setautoedit",
|
||||
"GuiTree.getautoedit",
|
||||
"GuiTree.getbylabel",
|
||||
"GuiTree.setsorted",
|
||||
"GuiTree.getsorted",
|
||||
"GuiTree.sorttreeitems",
|
||||
"GuiTree.getsibling",
|
||||
"GuiTree.setautocollapse",
|
||||
"GuiTree.setfontsize",
|
||||
"GuiTree.getfontsize",
|
||||
"GuiTree.getnumvisiblechilditems",
|
||||
"GuiTree.getnumvisibleitems",
|
||||
"GuiTree.enumvisibleitems",
|
||||
"GuiTree.enumvisiblechilditems",
|
||||
"GuiTree.enumallitems",
|
||||
"GuiTree.getitemrectx",
|
||||
"GuiTree.getitemrecty",
|
||||
"GuiTree.getitemrectw",
|
||||
"GuiTree.getitemrecth",
|
||||
"GuiTree.getitemfrompoint",
|
||||
"TreeItem.getnumchildren",
|
||||
"TreeItem.setlabel",
|
||||
"TreeItem.getlabel",
|
||||
"TreeItem.ensurevisible",
|
||||
"TreeItem.getnthchild",
|
||||
"TreeItem.getchild",
|
||||
"TreeItem.getchildsibling",
|
||||
"TreeItem.getsibling",
|
||||
"TreeItem.getparent",
|
||||
"TreeItem.editlabel",
|
||||
"TreeItem.hassubitems",
|
||||
"TreeItem.setsorted",
|
||||
"TreeItem.setchildtab",
|
||||
"TreeItem.issorted",
|
||||
"TreeItem.iscollapsed",
|
||||
"TreeItem.isexpanded",
|
||||
"TreeItem.invalidate",
|
||||
"TreeItem.isselected",
|
||||
"TreeItem.ishilited",
|
||||
"TreeItem.sethilited",
|
||||
"TreeItem.collapse",
|
||||
"TreeItem.expand",
|
||||
"TreeItem.gettree",
|
||||
"MenuButton.openmenu",
|
||||
"MenuButton.closemenu",
|
||||
"CheckBox.setchecked",
|
||||
"CheckBox.ischecked",
|
||||
"CheckBox.settext",
|
||||
"CheckBox.gettext",
|
||||
"Config.newitem",
|
||||
"Config.getitem",
|
||||
"Config.getitembyguid",
|
||||
"ConfigItem.getattribute",
|
||||
"ConfigItem.newattribute",
|
||||
"ConfigItem.getguid",
|
||||
"ConfigAttribute.setdata",
|
||||
"ConfigAttribute.getdata",
|
||||
"ConfigAttribute.getparentitem",
|
||||
"ConfigAttribute.getattributename",
|
||||
}
|
||||
`);
|
||||
// Write this as a newline delineated string to make it easier to other
|
||||
// tools to extract from the `.snap` file.
|
||||
const expected = Array.from(unimplementedRuntimeMethods).join("\n");
|
||||
expect(expected).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue