Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Manifest (performance improvement) #182

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions webAO/client/fetchLists.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { client } from "../client";
import { AO_HOST } from "./aoHost";
import { request } from "../services/request.js";
import { canonicalizePath } from "../utils/paths";

export const fetchBackgroundList = async () => {
try {
Expand All @@ -27,7 +28,7 @@ export const fetchCharacterList = async () => {
char_select.innerHTML = "";

char_select.add(new Option("Custom", "0"));

try {
const chardata = await request(`${AO_HOST}characters.json`);
const char_array = JSON.parse(chardata);
Expand Down Expand Up @@ -58,7 +59,7 @@ export const fetchEvidenceList = async () => {
evi_array.forEach((evi: string) => {
evi_select.add(new Option(evi));
});

} catch (err) {
console.warn("there was no evidence.json file");
}
Expand All @@ -68,10 +69,15 @@ export const fetchEvidenceList = async () => {
export const fetchManifest = async () => {
try {
const manifestdata = await request(`${AO_HOST}manifest.txt`);
client.manifest = manifestdata.split(/\r\n|\n\r|\n|\r/);
const tmp: string[] = manifestdata
.replace("\\", "/")
.split(/\r\n|\n\r|\n|\r/);
client.manifest = tmp.map(x => canonicalizePath(x)).sort();

// the try catch will fail before here when there is no file

} catch (err) {
console.warn("there was no manifest.txt file");
console.warn("no manifest.txt, webao will be slow");
client.manifest = [];
}
}
}
6 changes: 3 additions & 3 deletions webAO/client/handleCharacterInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { client } from "../client";
import { safeTags } from "../encoding";
import iniParse from "../iniParse";
import request from "../services/request";
import fileExists from "../utils/fileExists";
import { fileExistsManifest } from "../utils/fileExists";
import { AO_HOST } from "./aoHost";


Expand All @@ -23,7 +23,7 @@ export const handleCharacterInfo = async (chargs: string[], charid: number) => {
)}/char_icon`;
for (let i = 0; i < extensions.length; i++) {
const fileUrl = charIconBaseUrl + extensions[i];
const exists = await fileExists(fileUrl);
const exists = await fileExistsManifest(fileUrl);
if (exists) {
img.alt = chargs[0];
img.title = chargs[0];
Expand Down Expand Up @@ -102,4 +102,4 @@ export const handleCharacterInfo = async (chargs: string[], charid: number) => {
console.warn(`missing charid ${charid}`);
img.style.display = "none";
}
}
}
7 changes: 4 additions & 3 deletions webAO/client/setEmote.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Client from "../client";
import transparentPng from "../constants/transparentPng";
import fileExists from "../utils/fileExists";
import {fileExistsManifest} from "../utils/fileExists";

/**
* Sets all the img tags to the right sources
Expand Down Expand Up @@ -39,13 +39,14 @@ const setEmote = async (
} else if (extension === ".webp.static") {
url = `${characterFolder}${encodeURI(charactername)}/${encodeURI(
emotename
)}.webp`;
)}.webp`;
} else {
url = `${characterFolder}${encodeURI(charactername)}/${encodeURI(
prefix
)}${encodeURI(emotename)}${extension}`;
}
const exists = await fileExists(url);

const exists = await fileExistsManifest(url);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to update the unit tests for setEmote

if (exists) {
emoteSelector.src = url;
break;
Expand Down
6 changes: 3 additions & 3 deletions webAO/packets/handlers/handlePV.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { client } from "../../client";
import fileExists from "../../utils/fileExists";
import { fileExistsManifest } from "../../utils/fileExists";
import { updateActionCommands } from '../../dom/updateActionCommands'
import { pickEmotion } from '../../dom/pickEmotion'
import { AO_HOST } from "../../client/aoHost";
Expand Down Expand Up @@ -73,8 +73,8 @@ export const handlePV = async (args: string[]) => {
}

if (
await fileExists(
`${AO_HOST}characters/${encodeURI(me.name.toLowerCase())}/custom.gif`
await fileExistsManifest(
`characters/${encodeURI(me.name.toLowerCase())}/custom.gif`
)
) {
document.getElementById("button_4")!.style.display = "";
Expand Down
21 changes: 21 additions & 0 deletions webAO/utils/binarySearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* Returns the index of `needle' in `haystack', or `null' if it wasn't found. */
export function binarySearch(haystack,
needle,
cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0) {
let start = 0;
let end = haystack.length - 1;

while (start <= end) {
const middle = Math.floor((start + end) / 2);
const comparison = cmp(haystack[middle], needle);

if (comparison == 0)
return middle;
else if (comparison < 0)
start = middle + 1;
else
end = middle - 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get unit tests for this file and can you also convert it to TS?

}

return null;
}
24 changes: 24 additions & 0 deletions webAO/utils/fileExists.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {AO_HOST} from "../client/aoHost"
import {client} from "../client"
import {canonicalizePath} from "./paths"
import {binarySearch} from "./binarySearch"

const fileExists = async (url) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('HEAD', url);
Expand All @@ -16,3 +21,22 @@ const fileExists = async (url) => new Promise((resolve, reject) => {
xhr.send(null);
});
export default fileExists;

/* Returns whether file exists.
* `url' is a URL, including the base URL for bw compat.
* If manifest is empty, check the old way.
* Otherwise, look it up in the manifest */
const fileExistsManifest = async (url) =>
new Promise((resolve, reject) => {
if(client.manifest.length == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

=== here please

resolve(fileExists(url));
return;
}
const c_url = encodeURI(canonicalizePath(decodeURI(url.slice(AO_HOST.length))));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, JS uses camel case, so it may be a good idea to stick with that schema. Also calling it the full canonical.
Kinda nitpicking that since c has to be slightly interpreted


if(binarySearch(client.manifest, c_url) != null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!==

resolve(true);

resolve(false);
});
export {fileExistsManifest};
6 changes: 4 additions & 2 deletions webAO/utils/getAnimLength.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {client} from '../client'
import {AO_HOST} from '../client/aoHost'
import calculatorHandler from './calculatorHandler';
import fileExists from './fileExists.js';
import {fileExistsManifest} from './fileExists.js';
import { requestBuffer } from '../services/request.js';
/**
* Gets animation length. If the animation cannot be found, it will
Expand All @@ -11,7 +13,7 @@ const getAnimLength = async (url) => {
const extensions = ['.gif', '.webp', '.apng'];
for (const extension of extensions) {
const urlWithExtension = url + extension;
const exists = await fileExists(urlWithExtension);
const exists = await fileExistsManifest(urlWithExtension);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's some extra spacing here

if (exists) {
const fileBuffer = await requestBuffer(urlWithExtension);
const length = calculatorHandler[extension](fileBuffer);
Expand Down
19 changes: 19 additions & 0 deletions webAO/utils/paths.ts
Original file line number Diff line number Diff line change
@@ -1 +1,20 @@
export const getFilenameFromPath = (path: string) => path.substring(path.lastIndexOf('/') + 1)

/* Removes `/./`, `/../`, and `//`.
* Does not add a leading `/` or `./`.
* Does not add a trailing `/`. */
export function canonicalizePath(path: string): string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to update the unit tests please

const path_elements = path.split("/");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

camelCasing here please

var result: string[] = [];

for (const el of path_elements) {
if (el === "..")
result.pop();
else if (el === "." || el === "")
continue;

result.push(el);
}

return result.join("/");
}
6 changes: 3 additions & 3 deletions webAO/utils/tryUrls.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fileExists from './fileExists'
import {fileExistsManifest} from './fileExists'
import transparentPng from '../constants/transparentPng'
const urlExtensionsToTry = [
'.png',
Expand All @@ -10,11 +10,11 @@ const tryUrls = async (url: string) => {
for (let i = 0; i < urlExtensionsToTry.length; i++) {
const extension = urlExtensionsToTry[i]
const fullFileUrl = url + extension
const exists = await fileExists(fullFileUrl);
const exists = await fileExistsManifest(fullFileUrl);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit tests for this please

if (exists) {
return fullFileUrl
}
}
return transparentPng
}
export default tryUrls
export default tryUrls
10 changes: 6 additions & 4 deletions webAO/viewport/utils/setSide.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { positions } from '../constants/positions'
import { AO_HOST } from '../../client/aoHost'
import { client } from '../../client'
import tryUrls from '../../utils/tryUrls';
import fileExists from '../../utils/fileExists';
import { fileExistsManifest } from '../../utils/fileExists';

/**
* Changes the viewport background based on a given position.
Expand Down Expand Up @@ -57,10 +57,12 @@ export const set_side = async ({
} else {
court.src = await tryUrls(client.viewport.getBackgroundFolder() + bg);
}


if (showDesk === true && desk) {
const deskFilename = (await fileExists(client.viewport.getBackgroundFolder() + desk.ao2))
const deskFilename = (await fileExistsManifest(
(client.viewport.getBackgroundFolder() +
desk.ao2)))
? desk.ao2
: desk.ao1;
bench.src = client.viewport.getBackgroundFolder() + deskFilename;
Expand Down