From bb6fe7ec3ef2496e3092ee44b310dffdfd8afe34 Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Thu, 16 May 2019 05:30:27 +1000 Subject: [PATCH] Improve teambuilder stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should give an idea of the direction I want to take the teambuilder in: a text editor, but with special features. This neatly sidesteps a lot of UI questions, especially all the export and input buttons, because the regular editing mode can be used to import and export without anything fancy. This also makes way for a better way to implement team/set comments: comments are just invalid Pokémon in a team. --- preactalpha.template.html | 1 + src/battle-log.ts | 22 ++--- src/panel-chat.tsx | 2 +- src/panel-teambuilder.tsx | 81 ++++++++++++++++--- src/panel-teamdropdown.tsx | 161 ++++++++++++++++++++----------------- style/teambuilder.css | 25 ++++++ testclient-beta.html | 1 + 7 files changed, 199 insertions(+), 94 deletions(-) create mode 100644 style/teambuilder.css diff --git a/preactalpha.template.html b/preactalpha.template.html index a936fc9a1..b351ecb58 100644 --- a/preactalpha.template.html +++ b/preactalpha.template.html @@ -47,6 +47,7 @@ } linkStyle("/style/sim-types.css"); linkStyle("/style/battle.css"); + linkStyle("/style/teambuilder.css"); linkStyle("/style/utilichart.css"); linkStyle("/style/font-awesome.css"); diff --git a/src/battle-log.ts b/src/battle-log.ts index b70495f44..3152b5be7 100644 --- a/src/battle-log.ts +++ b/src/battle-log.ts @@ -22,21 +22,22 @@ class BattleLog { className: string; battleParser: BattleTextParser | null = null; /** - * -1 = spectator: "Red sent out Pikachu!" "Blue's Eevee used Tackle!" - * 0 = player 1: "Go! Pikachu!" "The opposing Eevee used Tackle!" - * 1 = player 2: "Red sent out Pikachu!" "Eevee used Tackle!" + * * -1 = spectator: "Red sent out Pikachu!" "Blue's Eevee used Tackle!" + * * 0 = player 1: "Go! Pikachu!" "The opposing Eevee used Tackle!" + * * 1 = player 2: "Red sent out Pikachu!" "Eevee used Tackle!" */ perspective: -1 | 0 | 1 = -1; - constructor(elem: HTMLDivElement, scene?: BattleScene) { + constructor(elem: HTMLDivElement, scene?: BattleScene | null, innerElem?: HTMLDivElement) { this.elem = elem; - elem.setAttribute('role', 'log'); - elem.innerHTML = ''; - const innerElem = document.createElement('div'); - innerElem.className = 'inner'; - elem.appendChild(innerElem); + if (!innerElem) { + elem.setAttribute('role', 'log'); + elem.innerHTML = ''; + innerElem = document.createElement('div'); + innerElem.className = 'inner'; + elem.appendChild(innerElem); + } this.innerElem = innerElem; - this.className = elem.className; if (scene) { this.scene = scene; @@ -47,6 +48,7 @@ class BattleLog { this.battleParser = new BattleTextParser(); } + this.className = elem.className; elem.onscroll = this.onScroll; } onScroll = () => { diff --git a/src/panel-chat.tsx b/src/panel-chat.tsx index 354a4055e..d631c3a8e 100644 --- a/src/panel-chat.tsx +++ b/src/panel-chat.tsx @@ -106,7 +106,7 @@ class ChatTextEntry extends preact.Component<{room: PSRoom, onMessage: (msg: str }; focusIfNoSelection = (e: Event) => { if ((e.target as HTMLElement).tagName === 'TEXTAREA') return; - const selection = window.getSelection(); + const selection = window.getSelection()!; if (selection.type === 'Range') return; const elem = this.base!.children[0].children[1] as HTMLTextAreaElement; elem.focus(); diff --git a/src/panel-teambuilder.tsx b/src/panel-teambuilder.tsx index d0b6c61e5..790ca85f6 100644 --- a/src/panel-teambuilder.tsx +++ b/src/panel-teambuilder.tsx @@ -137,8 +137,11 @@ class TeambuilderPanel extends PSRoomPanel { } else { formatName = BattleLog.escapeHTML(formatName); } - renderedFolders.push( - + const isCurFolder = this.curFolder === format; + renderedFolders.push( + {formatName} ); continue; @@ -217,6 +220,64 @@ class TeambuilderPanel extends PSRoomPanel { } } +class TeamTextbox extends preact.Component<{sets: PokemonSet[]}> { + separators: number[] = []; + textbox: HTMLTextAreaElement = null!; + heightTester: HTMLTextAreaElement = null!; + update = () => { + const textbox = this.textbox; + const heightTester = this.heightTester; + heightTester.style.width = `${textbox.offsetWidth}px`; + const value = textbox.value; + + let separatorIndex = value.indexOf('\n\n'); + const separators: number[] = []; + while (separatorIndex >= 0) { + while (value.charAt(separatorIndex + 2) === '\n') separatorIndex++; + heightTester.value = value.slice(0, separatorIndex); + separators.push(heightTester.scrollHeight); + + separatorIndex = value.indexOf('\n\n', separatorIndex + 1); + } + + heightTester.value = textbox.value; + textbox.style.height = `${heightTester.scrollHeight + 100}px`; + this.separators = separators; + this.forceUpdate(); + }; + componentDidMount() { + this.textbox = this.base!.getElementsByClassName('teamtextbox')[0] as HTMLTextAreaElement; + this.heightTester = this.base!.getElementsByClassName('heighttester')[0] as HTMLTextAreaElement; + + const exportedTeam = PSTeambuilder.exportTeam(this.props.sets); + this.textbox.value = exportedTeam; + this.update(); + } + componentWillUnmount() { + this.textbox = null!; + this.heightTester = null!; + } + render() { + return
+