Webnative Capacitor Doesn’t Have Run Android Option

I have installed the Webnative plugin in Visual Studio Code and created a Capacitor project. But when I click to run in Visual Studio Code, it doesn’t show the Android option. On the Webnative website, it says there is an “integrate capacitor” option, but it doesn’t have one. How to enable the Android option?

enter image description here

Drawing a div overlay sometime gives offsets divs and sometimes positioned correctly

For example, on this site
I want to highlight the paragraph that starts with the words

“Open Arms of Minnesota is a growing…”

So just for test case, I saved that paragraph as a global variable in the Dev-tools (chrome version 133.0.6343.99 using Mac)

(I know this picture is from windows, but this is where I post this thread from)
enter image description here

And pasted this code to highlight it:

const rect = temp1.getBoundingClientRect()
const top1 = rect.top
const left1 = rect.left
const width1 = rect.width
const height1 = rect.height


const overlay = document.createElement("div");
overlay.style.position = "absolute";
overlay.style.top = ${top1 + window.scrollY}px;
overlay.style.left = ${left1 + window.scrollX}px;
overlay.style.width = ${width1}px;
overlay.style.height = ${height1}px;
overlay.style.backgroundColor = "transparent";
overlay.style.border = "3px solid purple";
overlay.style.pointerEvents = "none";
overlay.style.zIndex = "2147483647";

document.body.appendChild(overlay);

(The reason I renamed it to left1 and top1 is because top is a saved keyword and I thought I was interfering with window.top…)
I don’t want it to be fixed positioned because I need it to stay even if the user scrolls.
But for some apparent reason, it just gets an offset above it and looks like this:

enter image description here

I have no idea where I am going wrong, because in other scenarios it works perfectly, the same code. I must also say that it sometimes works for that same paragraph I am talking about.. but I did not change any code or anything! (I tried to refresh multiple times, clear cookies and site data in the ‘Application’ section in the dev tools but to no avail)

Any ideas?

Selector for that paragraph: #post-3398 > div > div > section.elementor-section.elementor-top-section.elementor-element.elementor-element-785b238.elementor-section-boxed.elementor-section-height-default.elementor-section-height-default > div > div > div > div.elementor-element.elementor-element-1fa89a9.elementor-widget.elementor-widget-text-editor > div > p:nth-child(1)

(Even though it happens to the paragraph below it as well, this is just an example that boggles my mind)

Site: https://openarmsmn.org/about-us/careers

Rails not loading finger-printed assets in Production, causing 404 errors for imported javascript modules

I have a rails project and only in production (works fine locally in development), imported JS modules apparently do not load, and I get console errors referencing 404 errors for the files:

**Error: 404 Not Found** https://example.com/assets/controllers/meeting/modules/shared_helpers **imported from** https://example.com/assets/controllers/meeting/parent-file-xxxxxxxxxxxxxxxxx.js

The fingerprinted version of the files do exist in the public folder. However the console errors are not referencing them:
‘GET
https://example.com/assets/controllers/meeting/modules/shared_helpers’

The parent JS file that is importing the JS modules seems to work. In the console it’s referred to by its finger printed name: ‘https://example.com/assets/controllers/meeting/parent-file-xxxxxxxxxxxxxxxxx.js’

In that main parent JS file, the imports look like this:

import sharedHelpers from './modules/shared_helpers';

where shared_helpers.js is located in exampleappjavascriptcontrollersmeetingmodules and the file that is importing it is in exampleappjavascriptcontrollersmeeting

Things I’ve tried:

I’ve already updated production.rb:
config.public_file_server.enabled = true

Then ran
‘rake assets:precompile’

I’ve clobbered the public folder and recompiled and replaced

I added this to nginx conf

location ~ ^/assets/ {
        root /home/ec2-user/example/public;
        gzip_static on;
        expires max;
        add_header Cache-Control public;
    }

Importmap.rb looks like:

pin "application", to: "application.js", preload: true

# Hotwired libraries
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true

# Stimulus controllers
pin_all_from "app/javascript/controllers", under: "controllers"

# Meeting modules
pin_all_from "app/javascript/controllers/meeting/modules", under: "controllers/meeting/modules"

# External libraries
pin "meeting-client", to: "https://xxx.esm.mjs"m"

I’ve tried:
Why does Rails give 404 error for all assets?

Rails 7 and Import-map and loading custom JS file

EDIT
Should also mention I’m using secure-headers gem (csp), which has been .

SecureHeaders::Configuration.override(:disable_csp) do |config|
  config.csp = SecureHeaders::OPT_OUT
end

Why does setTimeout execute before fetch .then despite microtask priority?

I’m running the code below. The output I was expecting was:
Start -> End -> While expires -> joke -> setTimeout
However, the output I’m actually getting is:
Start -> End -> While expires -> setTimeout -> joke
Why is this happening?
Shouldn’t “joke” be printed before “setTimeout”, since fetch callbacks are stored in the microtask queue, which has higher priority than the task queue where setTimeout callbacks are stored?

console.log("Start");

setTimeout(function cb() {
    console.log("setTimeout");
}, 5000);

const apiUrl = "https://api.chucknorris.io/jokes/random";

fetch(apiUrl)
    .then((response) => response.json())
    .then((data) => {
        const joke = data.value;
        console.log(joke);
    })
    .catch((error) => {
        console.error("Error:", error);
    });

console.log("End");

let startDate = new Date().getTime();
let endDate = startDate;
while (endDate < startDate + 10000) {
    endDate = new Date().getTime();
}

console.log("While expires");

Vad är skillnaden mellan hemstädning och flyttstädning i Göteborg?

Jag ska snart flytta från min lägenhet i Göteborg och behöver boka professionell städning. Jag har sett olika tjänster som hemstädning (regelbunden städning av hemmet) och flyttstädning (grundlig städning vid flytt). Jag är osäker på vad skillnaden är mellan dessa tjänster och vad som ingår i flyttstädningen jämfört med hemstädning, särskilt vad som krävs för att hyresvärden ska bli nöjd.

Jag har tittat på städfirmors beskrivningar på nätet, men det finns många olika erbjudanden och prisnivåer. Jag trodde först att hemstädning och flyttstädning är ganska lika, men jag inser att flyttstädning verkar innebära mer omfattande rengöring, som fönsterputs och rengöring bakom spis och kyl. Jag vill veta exakt vad flyttstädning innefattar och om det är värt att boka till extra tjänster som storstädning.

How to make a smooth arc path for one Vec2 point to another?

I have a somewhat theoretical and opinion-based question. I’m building a small particle generator with the goal of creating animated images (developed using JS Web2D canvas to easily download the resulting file later). The issue is that the current movement from one point to another (like the particle generator to the final destruction point) is very basic, and I’d like to achieve something more natural. I’ve tried a few things, but I’d like to hear other people’s opinions on mathematical formulas or simply interesting and natural patterns to follow. Below is an example of how it currently works and the base code I’m using for the paths.

(spawners in green, targets in white)

Particles gif

[class code]

class Particle {
    /** @type {Vec2} */
    pos = { x: 0, y: 0 };

    /** @type {string} */
    color;

    /** @type {number} */
    lifespan = PARTICLE_LIFESPAN;

    /** @type {Vec2[]} */
    trail = [];

    /** @type {number} */
    trailLength = Math.floor(Math.random() * PARTICLE_MAX_LENGTH);

    /** @type {number} */
    targetIndex = Math.floor(Math.random() * targets.length);

    /** @type {Vec2} */
    target =
        targets.length > 0
            ? targets[this.targetIndex]
            : { x: Math.random() * -CANVAS_SIZE_X, y: Math.random() * CANVAS_SIZE_Y * 2 };

    /** @type {number} */
    spawnIndex = Math.floor(Math.random() * spawners.length);

    constructor() {
        // particle spawn position
        this.pos.x =
            spawners.length > 0
                ? spawners[this.spawnIndex].x
                : Math.floor(Math.random() * CANVAS_SIZE_X) + 50;
        this.pos.y =
            spawners.length > 0
                ? spawners[this.spawnIndex].y
                : Math.floor(Math.random() * CANVAS_SIZE_Y) - 50;

        // particle color
        this.color = PARTICLE_COLOR
            ? PARTICLE_COLOR
            : `#${Math.max(0x100, Math.round(Math.random() * 0xfff))}`;

        // creating trail
        for (let i = 0; i < this.trailLength; ++i) {
            this.trail.push({ x: this.pos.x, y: this.pos.y });
        }
    }

    spread() {
        switch (Math.round(Math.random() * 4)) {
            case 0:
                this.pos.x += PARTICLE_SPREAD;
                break;
            case 1:
                this.pos.x -= PARTICLE_SPREAD;
                break;
            case 2:
                this.pos.y += PARTICLE_SPREAD;
                break;
            case 3:
                this.pos.y -= PARTICLE_SPREAD;
                break;
        }
    }

    /** @param {Vec2} target */
    follow(target) {
        this.trail.push({ x: this.pos.x, y: this.pos.y });
        if (this.trail.length > this.trailLength) {
            this.trail.shift();
        }

        if (this.pos.x <= target.x + 10) {
            this.pos.x += PARTICLE_VELOCITY;
        } else if (this.pos.x > target.x + 10) {
            this.pos.x -= PARTICLE_VELOCITY;
        }

        if (this.pos.y <= target.y) {
            this.pos.y += PARTICLE_VELOCITY;
        } else if (this.pos.y > target.y) {
            this.pos.y -= PARTICLE_VELOCITY;
        }

        if (this.pos.x === target.x && this.pos.y === target.y) {
            if (targets.length > 0) {
                this.target = targets[this.targetIndex - 1];
            }
        }
    }
}

[render code]

/** @param {CanvasRenderingContext2D} ctx */
function render(ctx) {
    /** @type {Particle[]} */
    const ps = [];

    // reusable variables
    let i = 0,
        y = 0;

    const loop = () => {
        ctx.fillStyle = CANVAS_BACKGROUND_COLOR;
        ctx.fillRect(0, 0, CANVAS_SIZE_X, CANVAS_SIZE_Y);

        if (ps.length < PARTICLE_NUMBER) {
            for (; i < PARTICLE_NUMBER - ps.length; ++i) ps.push(new Particle());
            i = 0;
        }

        // rendering particles
        for (; i < ps.length; ++i) {
            ps[i].lifespan -= 1;

            for (; y < ps[i].trail.length - 1; ++y) {
                ctx.strokeStyle = ps[i].color;
                ctx.beginPath();
                ctx.moveTo(ps[i].trail[y].x, ps[i].trail[y].y);
                ctx.lineTo(ps[i].trail[y + 1].x, ps[i].trail[y + 1].y);
                ctx.stroke();
            }
            y = 0;

            ps[i].spread();
            ps[i].follow(ps[i].target);

            if (
                ps[i].lifespan <= 0 ||
                ps[i].pos.x < -PARTICLE_MAX_LENGTH * 2 ||
                ps[i].pos.x > CANVAS_SIZE_X + PARTICLE_MAX_LENGTH * 2 ||
                ps[i].pos.y < -PARTICLE_MAX_LENGTH * 2 ||
                ps[i].pos.y > CANVAS_SIZE_Y + (CANVAS_THRESHOLD + PARTICLE_MAX_LENGTH)
            ) {
                ps.splice(i, 1);
            }
        }
        i = 0;

        // rendering targets
        for (; i < targets.length; ++i) {
            ctx.fillStyle = "#ffffff95";
            ctx.fillRect(targets[i].x, targets[i].y, 4, 4);
            ctx.fillStyle = "#fff";
            ctx.fillText(`${i}`, targets[i].x + 2, targets[i].y - 6, 12);
        }
        i = 0;

        // rendering spawnpoints
        for (; i < spawners.length; ++i) {
            ctx.fillStyle = "#4800c695";
            ctx.fillRect(spawners[i].x, spawners[i].y, 4, 4);
            ctx.fillStyle = "#0fde00ff";
            ctx.fillText(`${i}`, spawners[i].x + 2, spawners[i].y - 6, 12);
        }
        i = 0;

        window.requestAnimationFrame(loop);
    };

    loop();
}

PM2 error – App [index:0] exited with code [1] via signal [SIGINT]

So the error started happening after i added:

app.get('/socials', (req, res) => {
    res.sendFile(`${__dirname}/socials.html`)

into my index.js file. I added them to connect up to my other html files for a clickable navbar, so when you click “socials” it would open the socials.html file and redirect me to that page.

I had these two already:

app.get('/', (req, res) => {
    res.sendFile(`${__dirname}/index.html`)
app.get('/donate', (req, res) => {
    res.sendFile(`${__dirname}/donate.html`)

in my index.js file but as soon as i added the socials one so there was 3 it started returning that error?

It was working fine with the index and donate but now i’ve added a 3rd one (socials) my website isnt working.

index.js:

'use strict'

// Modules
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const passport = require('passport')
const session = require('express-session')
const sharedsession = require('express-socket.io-session')
const SteamStrategy = require('passport-steam').Strategy

// Site stuff
const TradeBot = require('./lib/index')
const Trade = new TradeBot({ io })
const config = require('./config')

// Web server
server.listen(config.websitePort)
console.log('[!] Website server is online.')
console.log('[!] Socket server is online.')

// Passport
passport.serializeUser((user, done) => {
    done(null, user)
})
passport.deserializeUser((obj, done) => {
    done(null, obj)
})
passport.use(new SteamStrategy({
    returnURL: `${config.website}/auth/steam/return`,
    realm: `${config.website}/`,
    apiKey: config.steamApiKey,
},
(identifier, profile, done) => {
    process.nextTick(() => {
        const user = profile
        user.identifier = identifier
        return done(null, user)
    })
}))
const sessionMiddleware = session({
    secret: 'csg0tradebot',
    name: 'csg0trade',
    resave: true,
    saveUninitialized: true,
})
app.use(sessionMiddleware)
app.use(passport.initialize())
app.use(passport.session())
app.use('/static', express.static('./static'))

// Routes
app.get('/', (req, res) => {
    res.sendFile(`${__dirname}/index.html`)
app.get('/donate', (req, res) => {
    res.sendFile(`${__dirname}/donate.html`)
app.get('/socials', (req, res) => {
    res.sendFile(`${__dirname}/socials.html`)
});
})
// Auth Routes
app.get('/auth/steam', passport.authenticate('steam'))
app.get('/auth/steam/return', passport.authenticate('steam', { failureRedirect: '/auth/steam' }), (req, res) => {
    // Successful authentication, redirect home.
    res.redirect('/')
})
app.get('/logout', (req, res) => {
    req.logout()
    res.redirect('/')
})

// Sockets
io.use(sharedsession(sessionMiddleware))
io.on('connection', (socket) => {
    let userObject = false
    if (
        typeof socket.handshake.session.passport !== 'undefined' &&
        typeof socket.handshake.session.passport.user !== 'undefined' &&
        typeof socket.handshake.session.passport.user.id !== 'undefined'
    ) {
        userObject = socket.handshake.session.passport.user
    }

    socket.emit('site', config.site)
    socket.emit('user', userObject)
    socket.on('get user inv', (steamID64) => {
        Trade.getInventory(steamID64, config.appID, config.contextID, (err, data) => {
            socket.emit('user inv', { error: err, items: data })
        })
    })
    socket.on('get bot inv', (id) => {
        Trade.getInventory(config.bots[id].steamID64, config.appID, config.contextID, (err, data) => {
            socket.emit('bot inv', { error: err, items: data })
        })
    })
    socket.on('get bots inv', () => {
        const params = []
        Object.keys(config.bots).forEach((index) => {
            const bot = config.bots[index]
            params.push({
                id: index,
                steamID64: bot.steamID64,
                appID: config.appID,
                contextID: config.contextID,
            })
        })
        Trade.getInventories(params, (data) => {
            socket.emit('bots inv', data)
            socket.emit('bots floats', Trade.getFloatValues())
        })
    })
    socket.on('get pricelist', () => {
        socket.emit('pricelist', Trade.getPriceList())
    })
    socket.on('get rates', () => {
        socket.emit('rates', {
            ignore: Trade.getIgnorePrice(),
            trash: Trade.getTrashPrice(),
            user: Trade.getUserRates(),
            bot: Trade.getBotRates(),
        })
    })
    socket.on('get offer', (data) => {
        socket.emit('offer status', {
            error: null,
            status: 4,
        })
        const link = data.tradelink
        const offerData = data
        if (
            link.indexOf('steamcommunity.com/tradeoffer/new/') === -1 ||
            link.indexOf('?partner=') === -1 ||
            link.indexOf('&token=') === -1
        ) {
            socket.emit('offer status', {
                error: 'Invalid trade link!',
                status: false,
            })
        } else {
            Trade.validateOffer(offerData, (err, success) => {
                socket.emit('offer status', {
                    error: err,
                    status: (success) ? 1 : false,
                })
                if (!err && success) {
                    if (typeof config.bots[offerData.bot_id] === 'undefined') {
                        offerData.bot_id = Object.keys(config.bots)[0]
                    }
                    const Bot = Trade.getBot(offerData.bot_id)
                    const offer = Bot.manager.createOffer(offerData.tradelink)
                    offer.addTheirItems(offerData.user.map(assetid => ({
                        assetid,
                        appid: config.appID,
                        contextid: config.contextID,
                        amount: 1,
                    })))
                    if (offerData.bot.length) {
                        offer.addMyItems(offerData.bot.map(assetid => ({
                            assetid,
                            appid: config.appID,
                            contextid: config.contextID,
                            amount: 1,
                        })))
                    }
                    offer.setMessage(config.tradeMessage)
                    offer.getUserDetails((detailsError, me, them) => {
                        if (detailsError) {
                            socket.emit('offer status', {
                                error: detailsError,
                                status: false,
                            })
                        } else if (me.escrowDays + them.escrowDays > 0) {
                            socket.emit('offer status', {
                                error: 'You must have 2FA enabled, we do not accept trades that go into Escrow.',
                                status: false,
                            })
                        } else {
                            offer.send((errSend, status) => {
                                if (errSend) {
                                    socket.emit('offer status', {
                                        error: errSend,
                                        status: false,
                                    })
                                } else {
                                    console.log('[!!!!!] Sent a trade: ', data)
                                    if (status === 'pending') {
                                        socket.emit('offer status', {
                                            error: null,
                                            status: 2,
                                        })
                                        Trade.botConfirmation(data.bot_id, offer.id, (errConfirm) => {
                                            if (!errConfirm) {
                                                socket.emit('offer status', {
                                                    error: null,
                                                    status: 3,
                                                    offer: offer.id,
                                                })
                                            } else {
                                                socket.emit('offer status', {
                                                    error: errConfirm,
                                                    status: false,
                                                })
                                            }
                                        })
                                    } else {
                                        socket.emit('offer status', {
                                            error: null,
                                            status: 3,
                                            offer: offer.id,
                                        })
                                    }
                                }
                            })
                        }
                    })
                }
            })
        }
    })
})

dont understand why after added the 3rd route its started showing this error.
Ubuntu 25.04 x64 | project running on pm2

error logs:
PM2 ERROR LOGS

Does everything need to be included in standard form?

When using standard form is it possible for some of the question or sentence be excluded?

When i was doing the homework for the week i felt that not everything from the sentence needed to be included. I also remember in the video with the example the professor changed the premise. Can we do that or does that change standard from?

Why import requests from a worker have empty headers?

Lets say im executing the following line in the Chrome’s console:

new Worker('data:text/javascript;charset=utf-8,'+encodeURIComponent("import('https://localhost/qwe.js')"))

The problem is that my import which is inside the worker forming a weird request where almost all headers are lost (and most painfully the “origin” one). In the inspector it looks like this:

empty request headers

And this weird request then result in an obvious CORS error: Access to script at 'https://localhost/qwe.js' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Just for comparison, a “healthy” import request executed from my main thread cause no problems and its headers for example looks like this:

healthy request headers

How can i fix this problem?

Href in my html file returning “Cannot Get” (PM2)

I have this coding in my index.html:

    <!-- Href Hyperlinks -->
    <a href="index.html">Trade Bot</a>
    <a href="raffles.html">Monthly Raffles</a>
    <a href="socials.html">Socials</a>
    <a href="donate.html">Donate</a>
    <a href="faq.html">FAQ</a>

I have made separate html files (raffles.html, socials.html,donate.html,faq.html) which are all located in the same directory. Im not too sure if my app.js or index.js is correct but when i click the hyperlinks it redirects me to http://gorillaskins.com/donate.html and displays:

Cannot GET /donate.html

app.js:

$(function() {
    var app = new Vue({
        el: '#app',
        data: {
            priceList: {},
            rates: {
                user: {},
                bot: {}
            },
            disableReload: true,
            disableTrade: true,
            // bot
            floats: {},
            selectedBot: 'All bots',
            botInventories: {},
            botInventory: [],
            botInventorySelected: [],
            botInventorySelectedValue: 0,
            // user
            userInventory: [],
            userInventorySelected: [],
            userInventorySelectedValue: 0,
            // auth
            user: false,
            // site
            site: {
                header: '',
                steamGroup: '#',
                copyrights: ''
            },
            // trade
            offerStatus: {},
            invalidTradelink: false
        },
        methods: {
            setInventorySort: function(who, value) {
                if(who == 'bot') {
                    this.botInventory = this.sortInventory(this.botInventory, value);
                } else {
                    this.userInventory = this.sortInventory(this.userInventory, value);
                }
            },
            sortInventory: function(inventory, desc) {
                return inventory.sort(function(a, b) {
                    if(desc) {
                        return b.price - a.price;
                    } else {
                        return a.price - b.price;
                    }
                });
            },
            addItem: function(who, id, assetid, price) {
                if(typeof price === 'undefined') {
                    price = assetid;
                    assetid = id;
                }
                if(who == 'bot') {
                    if(this.selectedBot !== id) {
                        this.activeBot(id);
                    }
                    var botInventorySelected = this.botInventorySelected;
                    botInventorySelected.push(assetid);
                    this.botInventorySelected = botInventorySelected;
                    this.botInventorySelectedValue += parseFloat(price);
                } else {
                    var userInventorySelected = this.userInventorySelected;
                    userInventorySelected.push(assetid);
                    this.userInventorySelected = userInventorySelected;
                    this.userInventorySelectedValue += parseFloat(price);
                }
                this.checkTradeable();
            },
            removeItem: function(who, id, assetid, price) {
                if(typeof price === 'undefined') {
                    price = assetid;
                    assetid = id;
                }
                if(who == 'bot') {
                    this.botInventorySelected.splice($.inArray(assetid, this.botInventorySelected),1);
                    this.botInventorySelectedValue -= price;
                } else {
                    this.userInventorySelected.splice($.inArray(assetid, this.userInventorySelected),1);
                    this.userInventorySelectedValue -= price;
                    if(this.userInventorySelectedValue <= 0) {
                        this.userInventorySelectedValue = 0;
                    }
                }
                this.checkTradeable();
            },
            checkTradeable: function() {
                var user = parseFloat(this.userInventorySelectedValue.toFixed(2));
                var bot = parseFloat(this.botInventorySelectedValue.toFixed(2));
                if(user != 0 && user >= bot) {
                    this.disableTrade = false;
                } else {
                    this.disableTrade = true;
                }
            },
            activeBot: function(id) {
                if(this.selectedBot !== id) {
                    if(id == 'All Bots') {
                        var botInventory = [];
                        for(var i in this.botInventories) {
                            var bot = this.botInventories[i];
                            for(var y in bot.items) {
                                var item = bot.items[y];
                                item.bot = i;
                                if(app.priceList[item.data.market_hash_name] <= app.rates.trash) {
                                    item.price = (app.priceList[item.data.market_hash_name] * app.rates.bot['trash']).toFixed(2);
                                } else {
                                    item.price = (app.priceList[item.data.market_hash_name] * app.rates.bot[item.item_type.name]).toFixed(2);
                                }
                                botInventory.push(item);
                            }
                        }
                        this.botInventory = sortInventory(botInventory, true);
                    } else {
                        this.botInventory = this.sortInventory(this.botInventories[id].items, true);
                    }
                    this.botInventorySelected = [];
                    this.botInventorySelectedValue = 0;
                    this.selectedBot = id;
                }
            },
            searchInventory: function(who, value) {
                var inventory = [];
                var search = [];
                if(who == 'bot') {
                    search = this.botInventory;
                } else {
                    search = this.userInventory;
                }
                for(var i in search) {
                    var item = search[i];
                    if(item.data.market_hash_name.toLowerCase().indexOf(value.toLowerCase()) === -1) {
                        item.hidden = 1;
                    } else {
                        item.hidden = 0;
                    }
                    inventory.push(item);
                }
                if(who == 'bot') {
                    this.botInventory = sortInventory(inventory, true);
                } else {
                    this.userInventory = sortInventory(inventory, true);
                }
            },
            updateTradelink: function() {
                var link = this.user.tradelink;
                if(typeof link !== 'undefined') {
                    link = link.trim();
                    if(
                        link.indexOf('steamcommunity.com/tradeoffer/new/') === -1 ||
                        link.indexOf('?partner=') === -1 ||
                        link.indexOf('&token=') === -1
                    ) {
                        this.invalidTradelink = true;
                    } else {
                        ga('send', 'updateTradelink', {
                            eventCategory: 'Trade',
                            eventAction: 'click',
                            eventLabel: this.user.tradelink
                        });
                        this.invalidTradelink = false;
                        localStorage.setItem(this.user.id, this.user.tradelink);
                        $('#tradelink').modal('hide');
                    }
                } else {
                    this.invalidTradelink = true;
                }

            },
            reloadInventories: function() {
                this.disableReload = true;
                this.botInventory = [];
                this.botInventorySelected = [];
                this.botInventorySelectedValue = 0;
                this.userInventory = [];
                this.userInventorySelected = [];
                this.userInventorySelectedValue = 0;
                socket.emit('get bots inv');
                if(this.user && typeof this.user.steamID64 !== 'undefined') {
                    socket.emit('get user inv', this.user.steamID64);
                }
                ga('send', 'reloadInventories', {
                    eventCategory: 'Trade',
                    eventAction: 'click',
                    eventLabel: this.user.steamID64 || false
                });
            },
            sendOffer: function() {
                if( ! localStorage[this.user.id]) {
                    $('#tradelink').modal('show');
                } else {
                    ga('send', 'sendOffer', {
                        eventCategory: 'Trade',
                        eventAction: 'click',
                        eventLabel: this.user.id
                    });
                    this.offerStatus = {};
                    this.checkTradeable();
                    if( ! this.disableTrade) {
                        this.disableTrade = true;
                        $('#tradeoffer').modal('show');
                        socket.emit('get offer', {
                            user: this.userInventorySelected,
                            bot: this.botInventorySelected,
                            bot_id: this.selectedBot,
                            steamID64: this.user.id,
                            tradelink: localStorage[this.user.id]
                        });
                    }
                }
            }
        }
    });


    var socket = io();
    socket.emit('get pricelist');
    socket.emit('get rates');

    socket.on('site', function(data) {
        app.site = data;
        window.document.title = data.header + ' | Web-based CS:GO Trading Bot';
    });

    socket.on('offer status', function(data) {
        app.offerStatus = data;
        if(data.status === 3 || data.status === false) {
            app.disableTrade = false;
        }
        if(data.status === 3) {
            app.botInventorySelected = [];
            app.botInventorySelectedValue = 0;
            app.userInventorySelected = [];
            app.userInventorySelectedValue = 0;
        }
    });

    socket.on('user', function(user) {
        user.steamID64 = user.id;
        app.user = user;

        if(app.user.steamID64) {
            socket.emit('get user inv', app.user.steamID64);
        }

        if(localStorage[app.user.id]) {
            app.user.tradelink = localStorage[app.user.id];
        }
        if(typeof app.user.tradelink === 'undefined' && app.user) {
            $('#tradelink').modal('show');
        }
    });

    socket.on('user inv', function(data) {
        app.disableReload = false;
        if( ! data.error) {
            var userInventory = [];
            for(var i in data.items) {
                var item = data.items[i];
                if(app.priceList[item.data.market_hash_name] <= app.rates.trash) {
                    item.price = (app.priceList[item.data.market_hash_name] * app.rates.user['trash']).toFixed(2);
                } else {
                    item.price = (app.priceList[item.data.market_hash_name] * app.rates.user[item.item_type.name]).toFixed(2);
                }
                userInventory.push(item);
            }
            if( ! userInventory.length) {
                userInventory = { error: { error: 'No tradeable items found.' } };
            } else {
                userInventory = sortInventory(userInventory, true);
            }
            app.userInventory = userInventory;
        } else {
            app.userInventory = data;
        }
    });

    socket.on('bots floats', function(floats) {
        app.floats = floats;
    })

    socket.on('bots inv', function(items) {
        app.disableReload = false;
        // Order items object by key name
        const ordered = {};
        Object.keys(items).sort().forEach((key) => {
            ordered[key] = items[key];
        });
        // Assign ordered object to botInventories
        app.botInventories = Object.assign({}, ordered);

        var botInventory = [];
        var error = false;
        for(var i in items) {
            var bot = items[i];
            if(bot.error) {
                error = bot.error;
            }
            for(var y in bot.items) {
                var item = bot.items[y];
                item.bot = i;
                if(app.priceList[item.data.market_hash_name] <= app.rates.trash) {
                    item.price = (app.priceList[item.data.market_hash_name] * app.rates.bot['trash']).toFixed(2);
                } else {
                    item.price = (app.priceList[item.data.market_hash_name] * app.rates.bot[item.item_type.name]).toFixed(2);
                }
                botInventory.push(item);
            }
        }
        if( ! botInventory.length) {
            if( ! error) {
                error = { error: { error: 'No tradeable items found. Make sure all bots have items and are not set to private.' } };
            }
            botInventory = { error: error };
        } else {
            botInventory = sortInventory(botInventory, true);
        }
        app.botInventory = botInventory;
    });
    socket.on('pricelist', function(prices) {
        app.priceList = Object.assign({}, app.priceList, prices);

        socket.emit('get bots inv');
    });
    socket.on('rates', function(rates) {
        app.rates = Object.assign({}, app.rates, rates);
    });

    function sortInventory(inventory, desc) {
        return inventory.sort(function(a, b) {
            return (desc) ? b.price - a.price : a.price - b.price;
        });
    }

});

index.js:

'use strict'

// Modules
const express = require('express')

const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const passport = require('passport')

const session = require('express-session')
const sharedsession = require('express-socket.io-session')
const SteamStrategy = require('passport-steam').Strategy
// Site stuff
const TradeBot = require('./lib/index')

const Trade = new TradeBot({ io })
const config = require('./config')
// Web server
server.listen(config.websitePort)
console.log('[!] Website server is online.')
console.log('[!] Socket server is online.')
// Passport
passport.serializeUser((user, done) => {
    done(null, user)
})
passport.deserializeUser((obj, done) => {
    done(null, obj)
})
passport.use(new SteamStrategy({
    returnURL: `${config.website}/auth/steam/return`,
    realm: `${config.website}/`,
    apiKey: config.steamApiKey,
},
(identifier, profile, done) => {
    process.nextTick(() => {
        const user = profile
        user.identifier = identifier
        return done(null, user)
    })
}))
const sessionMiddleware = session({
    secret: 'csg0tradebot',
    name: 'csg0trade',
    resave: true,
    saveUninitialized: true,
})
app.use(sessionMiddleware)
app.use(passport.initialize())
app.use(passport.session())
app.use('/static', express.static('./static'))
// Routes
app.get('/', (req, res) => {
    res.sendFile(`${__dirname}/index.html`)
})
// Auth Routes
app.get('/auth/steam', passport.authenticate('steam'))
app.get('/auth/steam/return', passport.authenticate('steam', { failureRedirect: '/auth/steam' }), (req, res) => {
    // Successful authentication, redirect home.
    res.redirect('/')
})
app.get('/logout', (req, res) => {
    req.logout()
    res.redirect('/')
})
// Sockets
io.use(sharedsession(sessionMiddleware))
io.on('connection', (socket) => {
    let userObject = false
    if (
        typeof socket.handshake.session.passport !== 'undefined' &&
        typeof socket.handshake.session.passport.user !== 'undefined' &&
        typeof socket.handshake.session.passport.user.id !== 'undefined'
    ) {
        userObject = socket.handshake.session.passport.user
    }

    socket.emit('site', config.site)
    socket.emit('user', userObject)
    socket.on('get user inv', (steamID64) => {
        Trade.getInventory(steamID64, config.appID, config.contextID, (err, data) => {
            socket.emit('user inv', { error: err, items: data })
        })
    })
    socket.on('get bot inv', (id) => {
        Trade.getInventory(config.bots[id].steamID64, config.appID, config.contextID, (err, data) => {
            socket.emit('bot inv', { error: err, items: data })
        })
    })
    socket.on('get bots inv', () => {
        const params = []
        Object.keys(config.bots).forEach((index) => {
            const bot = config.bots[index]
            params.push({
                id: index,
                steamID64: bot.steamID64,
                appID: config.appID,
                contextID: config.contextID,
            })
        })
        Trade.getInventories(params, (data) => {
            socket.emit('bots inv', data)
            socket.emit('bots floats', Trade.getFloatValues())
        })
    })
    socket.on('get pricelist', () => {
        socket.emit('pricelist', Trade.getPriceList())
    })
    socket.on('get rates', () => {
        socket.emit('rates', {
            ignore: Trade.getIgnorePrice(),
            trash: Trade.getTrashPrice(),
            user: Trade.getUserRates(),
            bot: Trade.getBotRates(),
        })
    })
    socket.on('get offer', (data) => {
        socket.emit('offer status', {
            error: null,
            status: 4,
        })
        const link = data.tradelink
        const offerData = data
        if (
            link.indexOf('steamcommunity.com/tradeoffer/new/') === -1 ||
            link.indexOf('?partner=') === -1 ||
            link.indexOf('&token=') === -1
        ) {
            socket.emit('offer status', {
                error: 'Invalid trade link!',
                status: false,
            })
        } else {
            Trade.validateOffer(offerData, (err, success) => {
                socket.emit('offer status', {
                    error: err,
                    status: (success) ? 1 : false,
                })
                if (!err && success) {
                    if (typeof config.bots[offerData.bot_id] === 'undefined') {
                        offerData.bot_id = Object.keys(config.bots)[0]
                    }
                    const Bot = Trade.getBot(offerData.bot_id)
                    const offer = Bot.manager.createOffer(offerData.tradelink)
                    offer.addTheirItems(offerData.user.map(assetid => ({
                        assetid,
                        appid: config.appID,
                        contextid: config.contextID,
                        amount: 1,
                    })))
                    if (offerData.bot.length) {
                        offer.addMyItems(offerData.bot.map(assetid => ({
                            assetid,
                            appid: config.appID,
                            contextid: config.contextID,
                            amount: 1,
                        })))
                    }
                    offer.setMessage(config.tradeMessage)
                    offer.getUserDetails((detailsError, me, them) => {
                        if (detailsError) {
                            socket.emit('offer status', {
                                error: detailsError,
                                status: false,
                            })
                        } else if (me.escrowDays + them.escrowDays > 0) {
                            socket.emit('offer status', {
                                error: 'You must have 2FA enabled, we do not accept trades that go into Escrow.',
                                status: false,
                            })
                        } else {
                            offer.send((errSend, status) => {
                                if (errSend) {
                                    socket.emit('offer status', {
                                        error: errSend,
                                        status: false,
                                    })
                                } else {
                                    console.log('[!!!!!] Sent a trade: ', data)
                                    if (status === 'pending') {
                                        socket.emit('offer status', {
                                            error: null,
                                            status: 2,
                                        })
                                        Trade.botConfirmation(data.bot_id, offer.id, (errConfirm) => {
                                            if (!errConfirm) {
                                                socket.emit('offer status', {
                                                    error: null,
                                                    status: 3,
                                                    offer: offer.id,
                                                })
                                            } else {
                                                socket.emit('offer status', {
                                                    error: errConfirm,
                                                    status: false,
                                                })
                                            }
                                        })
                                    } else {
                                        socket.emit('offer status', {
                                            error: null,
                                            status: 3,
                                            offer: offer.id,
                                        })
                                    }
                                }
                            })
                        }
                    })
                }
            })
        }
    })
})

Is “:host::part()” a valid CSS selector?

I see this pattern all over Microsoft’s homepage microsoft.com.

Here’s an example –

:host::part(tab-item__content) {
    display: var(
      --ds-tab-item-content-display,
      ${t(e.contentDisplay)}
    );
    flex-direction: var(
      --ds-tab-item-content-flex-direction,
      ${t(e.contentFlexDirection)}
    );
    gap: var(--ds-tab-item-content-gap, ${t(e.contentGap)});
    align-items: var(
      --ds-tab-item-content-align-items,
      ${t(e.contentAlignItems)}
    );
    width: var(--ds-tab-item-content-width, ${t(e.contentWidth)});
    max-width: var(
      --ds-tab-item-content-max-width,
      ${t(e.contentMaxWidth)}
    );
    font-size: var(
      --ds-tab-item-content-font-size,
      ${t(e.contentFontSize)}
    );
    font-weight: var(
      --ds-tab-item-content-font-weight,
      ${t(e.contentFontWeight)}
    );
    ...
  }

Homepage url disapear

I’m on Blogger, and when I save the HTML, the home URL disappears. I’ve been searching for months, but being a near-novice, I haven’t found a solution.

The link is in the menu, the first one on the left. When I save the widget in Blogger Layout and load the page, I see the home URL, but when I edit the HTML, it disappears, and the menu link goes from 4 to 3.

Furthermore, since I’ve had this problem, I’ve also lost indexing for my home pages. Perhaps this information can be helpful. I’ve worked hard on my site’s SEO, but I get zero results, and Search Console indexing hasn’t improved after 10 months.

My sitemap hasn’t been read by Search Console since December.

I apologize again for merging multiple topics, but I’m convinced my problem isn’t SEO. It may not be the best SEO, but having zero indexed pages is impossible. Not only that, but I’ve also lost unindexed pages; they’re declining. I have over 4,000 published posts.

I tried creating a test blog with the same theme, and the home URL remains there. So I’m ruling out a theme issue.

Finally, this is my third site in five years, and this time I wanted to do things properly, using Blogger instead of wordpress.org, as I no longer have the money. Okay, Blogger isn’t the best choice for SEO, but it’s better than nothing. I’ve put all my accumulated experience into this site and tried to improve the aspects I was making wrong. Not only that, I’ve compared various competitors’ site design methods and taken inspiration from them. This way, I can avoid the mistakes of the past.

website: https://yoursupergames.blogspot.com/
images: https://imgur.com/a/nUvvksD

I expected to have a simple site to build with Blogger, despite the need for several HTML and JavaScript additions for completeness.

Unfortunately, despite my enormous efforts, the results are zero. It may not be the best site in the world, but I can’t even get the homepage indexed or AdSense validation.

Search Console sees a redirect to the homepage and confirms the error with every validation attempt. However, if I test the homepage with Search Console, it tells me the page is indexable.

I remind you that I’m not asking how to improve my SEO, but rather questions related to technical HTML errors that completely prevent Google from showing up. I would have accepted the last job and given up after all the hard work I’ve put in over five years. But no! Not even last, so I probably did something wrong, especially with Blogger, where I think I did everything right (or almost everything) on ​​the SEO front.

Why does the JavaScript mediaSession API not work in Firefox?

I’ve been programming a streaming service and have now run into the issue of displaying the media’s metadata in the OS’ media controls.

I now have this code:

if ("mediaSession" in navigator) {
    navigator.mediaSession.metadata = new window.MediaMetadata({
        title: song.title,
        artist: song.artists,
        album: "test",
        artwork: [{
            src: (song.imageName
                 ? `${location.origin}/BeatStream/images/song/large/${song.imageName}`
                 : `${location.origin}/BeatStream/images/defaultSong.webp`),
        }]
    });

    navigator.mediaSession.setActionHandler('play', () => this.audio.play());
    navigator.mediaSession.setActionHandler('pause', () => this.audio.pause());
    navigator.mediaSession.setActionHandler('previoustrack', () => this.playPrevious());
    navigator.mediaSession.setActionHandler('nexttrack', () => this.playNext());

    console.log("Image set to " + ((song.imageName)
        ? `${location.origin}/BeatStream/images/song/large/${song.imageName}`
        : `${location.origin}/BeatStream/images/defaultSong.webp`));
}

In Chrome, this all work very nice and I have no issues with it. In Firefox though, the artwork does not show up, even when trying multiple different image formats. I also did not get any errors in the browser console and the URLs that are logged to the console are the correct images. Different AI models tried to tell me that Firefox doesn’t support artwork.

When I go ahead and visit YT music, spotify or any other online streaming service with Firefox though, the artworks are shown perfectly fine. So my question is: What can they do that I can’t do, or do I have an error in my code?

writing structure related to chrome.storage.sync.set

First time I encounter the form of

chrome.storage.sync.set({ var1, var2, var3 });

Which creates in storage something like:

// inspect -> Application -> Extension storage -> sync
var1: "<value of var1 was string>"
var2: [{<value of var2 was a JSON>}]
var3: <value of var3 was int>

Basically the name of the variable becomes the key and the value is automatically being saved as it’s suppose to be.

my question is, where is this documented? (this form of writing) searching for it is a needle in a haystack