mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-25 11:57:14 +00:00
test_2
This commit is contained in:
+135
-63
@@ -5,11 +5,25 @@ const quickChatPhrases: Record<
|
|||||||
string,
|
string,
|
||||||
Array<{ text: string; requiresPlayer: boolean }>
|
Array<{ text: string; requiresPlayer: boolean }>
|
||||||
> = {
|
> = {
|
||||||
help: [{ text: "Please give me troops!", requiresPlayer: false }],
|
help: [
|
||||||
attack: [{ text: "Attack [P1]!", requiresPlayer: true }],
|
{ text: "Please give me troops!", requiresPlayer: false },
|
||||||
|
{ text: "Please give me golds!", requiresPlayer: false },
|
||||||
|
{ text: "Please don't attack me!", requiresPlayer: false },
|
||||||
|
],
|
||||||
|
attack: [
|
||||||
|
{ text: "Attack [P1]!", requiresPlayer: true },
|
||||||
|
{ text: "Launch a MIRV at [P1]!", requiresPlayer: true },
|
||||||
|
{ text: "Focus fire on [P1]!", requiresPlayer: true },
|
||||||
|
{ text: "Let's finish off [P1]!", requiresPlayer: true },
|
||||||
|
],
|
||||||
defend: [{ text: "Defend [P1]!", requiresPlayer: true }],
|
defend: [{ text: "Defend [P1]!", requiresPlayer: true }],
|
||||||
greet: [{ text: "Hello!", requiresPlayer: false }],
|
greet: [{ text: "Hello!", requiresPlayer: false }],
|
||||||
misc: [{ text: "Let’s go!", requiresPlayer: false }],
|
misc: [
|
||||||
|
{ text: "Let’s go!", requiresPlayer: false },
|
||||||
|
{ text: "Nice strategy!", requiresPlayer: false },
|
||||||
|
{ text: "This game is fun!", requiresPlayer: false },
|
||||||
|
{ text: "When will my PR finally get merged...?", requiresPlayer: false },
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
@customElement("chat-modal")
|
@customElement("chat-modal")
|
||||||
@@ -23,10 +37,30 @@ export class ChatModal extends LitElement {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private players: string[] = [
|
||||||
|
"Slovakia",
|
||||||
|
"Germany",
|
||||||
|
"Japan",
|
||||||
|
"Anon",
|
||||||
|
"Anon1",
|
||||||
|
"Anon2",
|
||||||
|
"Anon3",
|
||||||
|
"Anon4",
|
||||||
|
"Anon5",
|
||||||
|
"Anon6",
|
||||||
|
"Anon7",
|
||||||
|
"Anon8",
|
||||||
|
"Anon9",
|
||||||
|
"Anon10",
|
||||||
|
];
|
||||||
|
|
||||||
|
private playerSearchQuery: string = "";
|
||||||
private previewText: string | null = null;
|
private previewText: string | null = null;
|
||||||
private requiresPlayerSelection: boolean = false;
|
private requiresPlayerSelection: boolean = false;
|
||||||
private players: string[] = ["Slovakia", "Germany", "Japan"];
|
|
||||||
private selectedCategory: string | null = null;
|
private selectedCategory: string | null = null;
|
||||||
|
private selectedPhraseText: string | null = null;
|
||||||
|
private selectedPlayer: string | null = null;
|
||||||
|
private selectedPhraseTemplate: string | null = null;
|
||||||
|
|
||||||
quickChatPhrases: Record<
|
quickChatPhrases: Record<
|
||||||
string,
|
string,
|
||||||
@@ -52,65 +86,78 @@ export class ChatModal extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const sortedPlayers = [...this.players].sort((a, b) => a.localeCompare(b));
|
||||||
|
|
||||||
|
const filteredPlayers = sortedPlayers.filter((player) =>
|
||||||
|
player.toLowerCase().includes(this.playerSearchQuery),
|
||||||
|
);
|
||||||
|
|
||||||
|
const otherPlayers = sortedPlayers.filter(
|
||||||
|
(player) => !player.toLowerCase().includes(this.playerSearchQuery),
|
||||||
|
);
|
||||||
|
|
||||||
|
const displayPlayers = [...filteredPlayers, ...otherPlayers];
|
||||||
return html`
|
return html`
|
||||||
<o-modal title="Quick Chat">
|
<o-modal title="Quick Chat">
|
||||||
<div class="chat-modal-content">
|
<div class="chat-columns">
|
||||||
<!-- 入力中のチャットプレビュー -->
|
<div class="chat-column">
|
||||||
<div class="chat-preview">
|
<div class="column-title">Category</div>
|
||||||
<span>${this.previewText || "Select a phrase"}</span>
|
${this.categories.map(
|
||||||
|
(category) => html`
|
||||||
|
<button
|
||||||
|
class="chat-option-button ${this.selectedCategory ===
|
||||||
|
category.id
|
||||||
|
? "selected"
|
||||||
|
: ""}"
|
||||||
|
@click=${() => this.selectCategory(category.id)}
|
||||||
|
>
|
||||||
|
${category.name}
|
||||||
|
</button>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- カテゴリ選択 -->
|
|
||||||
<div class="chat-section">
|
|
||||||
<div class="chat-section-title">Categories</div>
|
|
||||||
<div class="chat-options">
|
|
||||||
${this.categories.map(
|
|
||||||
(category) => html`
|
|
||||||
<button
|
|
||||||
class="chat-option-button ${this.selectedCategory ===
|
|
||||||
category.id
|
|
||||||
? "selected"
|
|
||||||
: ""}"
|
|
||||||
@click=${() => this.selectCategory(category.id)}
|
|
||||||
>
|
|
||||||
${category.name}
|
|
||||||
</button>
|
|
||||||
`,
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 定型文選択 -->
|
|
||||||
${this.selectedCategory
|
${this.selectedCategory
|
||||||
? html`
|
? html`
|
||||||
<div class="chat-section">
|
<div class="chat-column">
|
||||||
<div class="chat-section-title">Phrases</div>
|
<div class="column-title">Phrase</div>
|
||||||
<div class="chat-options">
|
${this.getPhrasesForCategory(this.selectedCategory).map(
|
||||||
${this.getPhrasesForCategory(this.selectedCategory).map(
|
(phrase) => html`
|
||||||
(phrase) => html`
|
<button
|
||||||
<button
|
class="chat-option-button ${this.selectedPhraseText ===
|
||||||
class="chat-option-button"
|
phrase.text
|
||||||
@click=${() => this.selectPhrase(phrase)}
|
? "selected"
|
||||||
>
|
: ""}"
|
||||||
${this.renderPhrasePreview(phrase)}
|
@click=${() => this.selectPhrase(phrase)}
|
||||||
</button>
|
>
|
||||||
`,
|
${this.renderPhrasePreview(phrase)}
|
||||||
)}
|
</button>
|
||||||
</div>
|
`,
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: null}
|
: null}
|
||||||
|
${this.requiresPlayerSelection || this.selectedPlayer
|
||||||
<!-- プレイヤー選択(変数が必要な場合のみ表示) -->
|
|
||||||
${this.requiresPlayerSelection
|
|
||||||
? html`
|
? html`
|
||||||
<div class="chat-section">
|
<div class="chat-column">
|
||||||
<div class="chat-section-title">Select Player</div>
|
<div class="column-title">Player</div>
|
||||||
<div class="chat-options">
|
|
||||||
${this.players.map(
|
<input
|
||||||
|
class="player-search-input"
|
||||||
|
type="text"
|
||||||
|
placeholder="Search player..."
|
||||||
|
.value=${this.playerSearchQuery}
|
||||||
|
@input=${this.onPlayerSearchInput}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="player-scroll-area">
|
||||||
|
${this.getSortedFilteredPlayers().map(
|
||||||
(player) => html`
|
(player) => html`
|
||||||
<button
|
<button
|
||||||
class="chat-option-button"
|
class="chat-option-button ${this.selectedPlayer ===
|
||||||
|
player
|
||||||
|
? "selected"
|
||||||
|
: ""}"
|
||||||
@click=${() => this.selectPlayer(player)}
|
@click=${() => this.selectPlayer(player)}
|
||||||
>
|
>
|
||||||
${player}
|
${player}
|
||||||
@@ -121,17 +168,19 @@ export class ChatModal extends LitElement {
|
|||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
: null}
|
: null}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 送信ボタン -->
|
<div class="chat-preview">
|
||||||
<div class="chat-send">
|
${this.previewText || "Build your message..."}
|
||||||
<button
|
</div>
|
||||||
class="chat-send-button"
|
<div class="chat-send">
|
||||||
@click=${this.sendChatMessage}
|
<button
|
||||||
?disabled=${!this.previewText}
|
class="chat-send-button"
|
||||||
>
|
@click=${this.sendChatMessage}
|
||||||
Send
|
?disabled=${!this.previewText}
|
||||||
</button>
|
>
|
||||||
</div>
|
Send
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</o-modal>
|
</o-modal>
|
||||||
`;
|
`;
|
||||||
@@ -139,14 +188,19 @@ export class ChatModal extends LitElement {
|
|||||||
|
|
||||||
private selectCategory(categoryId: string) {
|
private selectCategory(categoryId: string) {
|
||||||
this.selectedCategory = categoryId;
|
this.selectedCategory = categoryId;
|
||||||
|
this.selectedPhraseText = null;
|
||||||
this.previewText = null;
|
this.previewText = null;
|
||||||
this.requiresPlayerSelection = false;
|
this.requiresPlayerSelection = false;
|
||||||
|
this.selectedPlayer = null;
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private selectPhrase(phrase: { text: string; requiresPlayer: boolean }) {
|
private selectPhrase(phrase: { text: string; requiresPlayer: boolean }) {
|
||||||
|
this.selectedPhraseTemplate = phrase.text;
|
||||||
|
this.selectedPhraseText = phrase.text;
|
||||||
this.previewText = phrase.text;
|
this.previewText = phrase.text;
|
||||||
this.requiresPlayerSelection = phrase.requiresPlayer;
|
this.requiresPlayerSelection = phrase.requiresPlayer;
|
||||||
|
this.selectedPlayer = null;
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +210,8 @@ export class ChatModal extends LitElement {
|
|||||||
|
|
||||||
private selectPlayer(player: string) {
|
private selectPlayer(player: string) {
|
||||||
if (this.previewText) {
|
if (this.previewText) {
|
||||||
this.previewText = this.previewText.replace("[P1]", player);
|
this.previewText = this.selectedPhraseTemplate.replace("[P1]", player);
|
||||||
|
this.selectedPlayer = player;
|
||||||
this.requiresPlayerSelection = false;
|
this.requiresPlayerSelection = false;
|
||||||
this.requestUpdate();
|
this.requestUpdate();
|
||||||
}
|
}
|
||||||
@@ -167,7 +222,24 @@ export class ChatModal extends LitElement {
|
|||||||
this.previewText = null;
|
this.previewText = null;
|
||||||
this.selectedCategory = null;
|
this.selectedCategory = null;
|
||||||
this.requiresPlayerSelection = false;
|
this.requiresPlayerSelection = false;
|
||||||
this.close(); // モーダルを閉じる
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onPlayerSearchInput(e: Event) {
|
||||||
|
const target = e.target as HTMLInputElement;
|
||||||
|
this.playerSearchQuery = target.value.toLowerCase();
|
||||||
|
this.requestUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSortedFilteredPlayers(): string[] {
|
||||||
|
const sorted = [...this.players].sort((a, b) => a.localeCompare(b));
|
||||||
|
const filtered = sorted.filter((p) =>
|
||||||
|
p.toLowerCase().includes(this.playerSearchQuery),
|
||||||
|
);
|
||||||
|
const others = sorted.filter(
|
||||||
|
(p) => !p.toLowerCase().includes(this.playerSearchQuery),
|
||||||
|
);
|
||||||
|
return [...filtered, ...others];
|
||||||
}
|
}
|
||||||
|
|
||||||
public open() {
|
public open() {
|
||||||
|
|||||||
+57
-34
@@ -492,65 +492,88 @@ label.option-card:hover {
|
|||||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-modal-content {
|
/* .w. */
|
||||||
|
|
||||||
|
.chat-columns {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
gap: 16px;
|
||||||
gap: 12px;
|
padding: 12px;
|
||||||
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-preview {
|
.chat-column {
|
||||||
background: #222;
|
display: flex;
|
||||||
padding: 10px;
|
flex-direction: column;
|
||||||
border-radius: 6px;
|
gap: 8px;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
margin-bottom: 4px;
|
||||||
}
|
|
||||||
|
|
||||||
.chat-section {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-section-title {
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-options {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-option-button {
|
.chat-option-button {
|
||||||
background: #444;
|
background: #333;
|
||||||
|
color: white;
|
||||||
border: none;
|
border: none;
|
||||||
|
padding: 8px 12px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 6px 10px;
|
text-align: left;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-option-button.selected {
|
.chat-option-button.selected {
|
||||||
background: #66c;
|
background-color: #66c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-preview {
|
||||||
|
margin: 10px 12px;
|
||||||
|
padding: 10px;
|
||||||
|
background: #222;
|
||||||
color: white;
|
color: white;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-send {
|
.chat-send {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: flex-end;
|
||||||
margin-top: 10px;
|
padding: 0 12px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-send-button {
|
.chat-send-button {
|
||||||
background: #4caf50;
|
background: #4caf50;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 8px 14px;
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-cancel-button {
|
.chat-column {
|
||||||
background: #aaa;
|
display: flex;
|
||||||
color: black;
|
flex-direction: column;
|
||||||
padding: 8px 14px;
|
gap: 8px;
|
||||||
|
min-width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-search-input {
|
||||||
|
padding: 6px 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
border: 1px solid #666;
|
||||||
|
font-size: 14px;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
background-color: #fff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-scroll-area {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
padding-right: 4px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user