Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions src/environment.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export const environment = {
},
reverse_watch_base_api_url: 'http://localhost:3434/api',
floatdb_gateway_url: 'https://gateway.floatdb.com',
skincraft_embed_origin: 'https://localhost:3000',
};
1 change: 1 addition & 0 deletions src/environment.staging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export const environment = {
},
reverse_watch_base_api_url: 'https://reverse.watch/api',
floatdb_gateway_url: 'https://gateway.floatdb.com',
skincraft_embed_origin: 'https://skincraft.gg',
};
1 change: 1 addition & 0 deletions src/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export const environment = {
},
reverse_watch_base_api_url: 'https://reverse.watch/api',
floatdb_gateway_url: 'https://gateway.floatdb.com',
skincraft_embed_origin: 'https://skincraft.gg',
};
111 changes: 101 additions & 10 deletions src/lib/components/inventory/selected_item_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ import {Contract} from '../../types/float_market';
import '../common/ui/floatbar';
import {ClientSend} from '../../bridge/client';
import {FetchBluegem, FetchBluegemResponse} from '../../bridge/handlers/fetch_bluegem';
import {environment} from '../../../environment';
import {gSkinCraftEmbed} from '../../services/skincraft_embed';
import {getActiveInventoryAssetProperties, toSkinCraftItem} from '../../services/skincraft_inventory_targets';
import type {SkinCraftItem} from '../../services/skincraft_viewer_protocol';
import {gWebGpuAvailability} from '../../services/webgpu_availability';
import type {WebGpuAvailability} from '../../services/webgpu_availability';
import './list_item_modal';

/**
Expand All @@ -48,6 +54,13 @@ export class SelectedItemInfo extends FloatElement {
margin-bottom: 10px;
}

.market-btn-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 10px;
}

.market-btn-container {
margin: 10px 0 10px 0;
padding: 5px;
Expand All @@ -64,6 +77,43 @@ export class SelectedItemInfo extends FloatElement {
color: #ebebeb;
text-decoration: none;
}

.view-3d-btn {
display: inline-flex;
align-items: center;
gap: 6px;
height: 32px;
padding: 0 12px;
font-size: 13px;
font-weight: 600;
color: #f5f8ff;
background-color: #5155eb;
border: 0;
border-radius: 8px;
cursor: pointer;
font-family: inherit;
text-decoration: none;
transition:
filter 180ms ease,
transform 180ms ease;
box-shadow:
0 4px 12px hsl(0 0% 0% / 0.22),
0 1px 2px hsl(0 0% 0% / 0.16),
inset 0 1px 0 rgba(255, 255, 255, 0.22);
}

.view-3d-btn img {
filter: brightness(0) invert(1);
}

.view-3d-btn:hover {
filter: brightness(1.1);
}

.view-3d-btn:active {
transform: scale(0.98);
filter: brightness(0.95);
}
`,
];

Expand All @@ -79,6 +129,9 @@ export class SelectedItemInfo extends FloatElement {
@state()
private showListModal: boolean = false;

@state()
private webGpuStatus: WebGpuAvailability = gWebGpuAvailability.status;

private bluegemData: FetchBluegemResponse | undefined;

get asset(): InventoryAsset | undefined {
Expand Down Expand Up @@ -151,8 +204,14 @@ export class SelectedItemInfo extends FloatElement {
);
}

if (this.canListOnCSFloat || this.canViewInSkinCraft) {
containerChildren.push(
html`<div class="market-btn-row">${this.renderListOnCSFloat()} ${this.renderViewIn3D()}</div>`
);
}

if (isSellableOnCSFloat(this.asset.description)) {
containerChildren.push(html`${this.renderListOnCSFloat()} ${this.renderFloatMarketListing()}`);
containerChildren.push(this.renderFloatMarketListing());
}

if (containerChildren.length === 0) {
Expand Down Expand Up @@ -216,19 +275,39 @@ export class SelectedItemInfo extends FloatElement {
`;
}

renderListOnCSFloat(): TemplateResult<1> {
if (this.stallListing) {
// Don't tell them to list it if it's already listed...
return html``;
}
private get canListOnCSFloat(): boolean {
return (
!!this.asset?.description &&
isSellableOnCSFloat(this.asset.description) &&
!this.stallListing &&
g_ActiveInventory?.m_owner?.strSteamId === g_steamID &&
!!this.asset.description.tradable
);
}

if (g_ActiveInventory?.m_owner?.strSteamId !== g_steamID) {
// Not the signed-in user, don't show
private get skinCraftItem(): SkinCraftItem | undefined {
return toSkinCraftItem(this.asset, getActiveInventoryAssetProperties(g_ActiveInventory, this.asset?.assetid));
}

private get canViewInSkinCraft(): boolean {
return this.webGpuStatus === 'available' && !!this.skinCraftItem;
}

renderViewIn3D(): TemplateResult<1> {
if (!this.canViewInSkinCraft) {
return html``;
}

if (!this.asset?.description?.tradable) {
// Don't show if item isn't tradable
return html`
<button class="view-3d-btn" type="button" @click="${this.handleViewIn3D}">
<img src="${environment.skincraft_embed_origin}/icon.svg" height="22" alt="" />
<span>View in 3D</span>
</button>
`;
}

renderListOnCSFloat(): TemplateResult<1> {
if (!this.canListOnCSFloat) {
return html``;
}

Expand All @@ -249,6 +328,11 @@ export class SelectedItemInfo extends FloatElement {
`;
}

private handleViewIn3D(): void {
const item = this.skinCraftItem;
if (item) gSkinCraftEmbed.open(item);
}

async processSelectChange() {
// Reset state in-case they swap between skin and non-skin
this.itemInfo = undefined;
Expand Down Expand Up @@ -289,9 +373,16 @@ export class SelectedItemInfo extends FloatElement {
this.loading = false;
}

private async resolveWebGpuStatus(): Promise<void> {
if (this.webGpuStatus === 'checking') this.webGpuStatus = await gWebGpuAvailability.settled();
}

connectedCallback() {
super.connectedCallback();

// Settles once per session; the 3D button stays hidden until it does
void this.resolveWebGpuStatus();

// For the initial load, in case an item is pre-selected
this.processSelectChange();

Expand Down
Loading