fix(app): show the official badge and a visible account menu (#3265)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-08 03:03:05 +02:00
1 parent ee1c861eb2
commit 4b88d64b2d
3 files changed
+39 -10

No files matched your search

@@ -231,16 +231,17 @@
justify-content: center; justify-content: center;
box-sizing: border-box; box-sizing: border-box;
padding: 0; padding: 0;
border: 0; border: 0.0625rem solid color-mix(in srgb, var(--account-profile-name-color) 45%, transparent);
border-radius: 50%; border-radius: 50%;
background: color-mix(in srgb, var(--account-profile-name-color) 14%, transparent); background: var(--background-tertiary);
color: color-mix(in srgb, var(--account-profile-name-color) 78%, transparent); color: var(--text-primary);
box-shadow: 0 0.125rem 0.5rem rgb(0 0 0 / 0.28);
cursor: pointer; cursor: pointer;
outline: none; outline: none;
pointer-events: auto; pointer-events: auto;
transition: transition:
background-color 40ms ease, background-color 40ms ease,
color 40ms ease; border-color 40ms ease;
} }
.moreButton:disabled { .moreButton:disabled {
@@ -250,8 +251,8 @@
:global(:where(html.window-focused, html.unfocused-fully-interactive):not(.window-focus-activation-guard)) :global(:where(html.window-focused, html.unfocused-fully-interactive):not(.window-focus-activation-guard))
.moreButton:not(:disabled):hover { .moreButton:not(:disabled):hover {
background: color-mix(in srgb, var(--account-profile-name-color) 26%, transparent); border-color: color-mix(in srgb, var(--account-profile-name-color) 70%, transparent);
color: var(--account-profile-name-color); background: color-mix(in srgb, var(--text-primary) 14%, var(--background-tertiary));
} }
.nameText { .nameText {
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
import {resolveInstanceLabel} from '@app/features/auth/flow/instance_selector/InstanceDirectoryStorage'; import {resolveInstanceLabel} from '@app/features/auth/flow/instance_selector/InstanceDirectoryStorage';
import {isOfficialInstanceHost} from '@fluxer/instance_bootstrap/src/OfficialInstance';
import {describe, expect, test} from 'vitest'; import {describe, expect, test} from 'vitest';
describe('resolveInstanceLabel', () => { describe('resolveInstanceLabel', () => {
@@ -23,3 +24,18 @@ describe('resolveInstanceLabel', () => {
expect(resolveInstanceLabel(null, 'fluxer.app')).toBe('Fluxer'); expect(resolveInstanceLabel(null, 'fluxer.app')).toBe('Fluxer');
}); });
}); });
describe('isOfficialInstanceHost', () => {
test('an official API endpoint with a path is official', () => {
expect(isOfficialInstanceHost('https://web.canary.fluxer.app/api')).toBe(true);
expect(isOfficialInstanceHost('https://canary.fluxer.com/api/')).toBe(true);
expect(isOfficialInstanceHost('https://web.fluxer.app')).toBe(true);
});
test('other hosts are not official whatever the path', () => {
expect(isOfficialInstanceHost('http://localhost:48090/api')).toBe(false);
expect(isOfficialInstanceHost('https://fluxer.app.example.com/api')).toBe(false);
expect(isOfficialInstanceHost('https://example.com/web.fluxer.app')).toBe(false);
expect(isOfficialInstanceHost('https://web.fluxer.app/api?x=1')).toBe(false);
});
});
@@ -1,6 +1,10 @@
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
import {normalizeHTTPNetworkOrigin} from '@fluxer/instance_bootstrap/src/NetworkOrigin'; import {
type CanonicalNetworkEndpointRule,
HTTP_NETWORK_PROTOCOLS,
normalizeCanonicalNetworkEndpoint,
} from '@fluxer/instance_bootstrap/src/NetworkOrigin';
export const OFFICIAL_INSTANCE_NAME = 'Fluxer'; export const OFFICIAL_INSTANCE_NAME = 'Fluxer';
@@ -70,11 +74,19 @@ export const OFFICIAL_INSTANCE_HOSTS: ReadonlyArray<string> = Object.freeze([
'canary.fluxer.com', 'canary.fluxer.com',
]); ]);
const OFFICIAL_HOST_LOOKUP_RULE: CanonicalNetworkEndpointRule = Object.freeze({
protocols: HTTP_NETWORK_PROTOCOLS,
allowPath: true,
allowRelative: false,
});
export function isOfficialInstanceHost(value: string): boolean { export function isOfficialInstanceHost(value: string): boolean {
const origin = normalizeHTTPNetworkOrigin(value); const endpoint = normalizeCanonicalNetworkEndpoint(value, OFFICIAL_HOST_LOOKUP_RULE);
if (origin == null) { if (endpoint == null) {
return false; return false;
} }
const host = origin.slice(origin.indexOf('//') + 2).toLowerCase(); const authority = endpoint.slice(endpoint.indexOf('//') + 2);
const pathStart = authority.indexOf('/');
const host = (pathStart === -1 ? authority : authority.slice(0, pathStart)).toLowerCase();
return OFFICIAL_INSTANCE_HOSTS.some((officialHost) => officialHost === host); return OFFICIAL_INSTANCE_HOSTS.some((officialHost) => officialHost === host);
} }