mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-12-29 03:20:46 +08:00
feat(frontend): add feature flag for tribe multiplayer (@eikomaniac) (#7234)
### Description Adds a tribeEnabled feature flag to gate tribe multiplayer functionality. # Note Once this PR is approved and merged into `newtribemerge`, `newtribemerge` can safely be merged into `master` --------- Co-authored-by: Miodec <jack@monkeytype.com>
This commit is contained in:
parent
5d229e712b
commit
7a17ba25ec
15 changed files with 81 additions and 19 deletions
|
|
@ -104,6 +104,7 @@ export const BASE_CONFIGURATION: Configuration = {
|
|||
},
|
||||
},
|
||||
connections: { enabled: false, maxPerUser: 100 },
|
||||
tribe: { enabled: false },
|
||||
};
|
||||
|
||||
type BaseSchema = {
|
||||
|
|
@ -615,5 +616,12 @@ export const CONFIGURATION_FORM_SCHEMA: ObjectSchema<Configuration> = {
|
|||
},
|
||||
},
|
||||
},
|
||||
tribe: {
|
||||
type: "object",
|
||||
label: "Tribe (Multiplayer)",
|
||||
fields: {
|
||||
enabled: { type: "boolean", label: "Enabled" },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@
|
|||
</div>
|
||||
</a>
|
||||
<a
|
||||
class="textButton view-tribe"
|
||||
class="textButton view-tribe hidden"
|
||||
href="/tribe"
|
||||
onclick="this.blur();"
|
||||
onclick="this.blur()"
|
||||
router-link
|
||||
title="tribe"
|
||||
>
|
||||
|
|
@ -122,7 +122,7 @@
|
|||
<i class="fas fa-fw fa-cog"></i>
|
||||
</div>
|
||||
</a>
|
||||
<div></div>
|
||||
<div class="spacer"></div>
|
||||
<button class="text showAlerts" onclick="this.blur()">
|
||||
<div class="icon">
|
||||
<i class="fas fa-fw fa-bell"></i>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<i class="fas icon fa-keyboard"></i>
|
||||
input
|
||||
</a>
|
||||
<a class="textButton" href="#group_tribe">
|
||||
<a class="textButton hidden" href="#group_tribe">
|
||||
<i class="fas icon fa-satellite"></i>
|
||||
tribe
|
||||
</a>
|
||||
|
|
@ -654,11 +654,11 @@
|
|||
<div id="ad-settings-2-small"></div>
|
||||
</div>
|
||||
|
||||
<button id="group_tribe" class="text sectionGroupTitle" group="tribe">
|
||||
<button id="group_tribe" class="text sectionGroupTitle hidden" group="tribe">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
tribe
|
||||
</button>
|
||||
<div class="settingsGroup tribe1">
|
||||
<div class="settingsGroup tribe hidden">
|
||||
<div class="section" data-config-name="tribeDelta">
|
||||
<div class="groupTitle">
|
||||
<i class="fas fa-exchange-alt"></i>
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@ nav {
|
|||
font-size: 1rem;
|
||||
line-height: 1rem;
|
||||
color: var(--sub-color);
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
// margin-bottom: -0.4rem;
|
||||
width: -moz-fit-content;
|
||||
width: fit-content;
|
||||
width: 100%;
|
||||
grid-template-columns: auto auto auto auto auto 1fr auto;
|
||||
|
||||
.spacer {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
button.showAlerts {
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import * as UpdateConfig from "../../config";
|
||||
import { Command, CommandsSubgroup } from "../types";
|
||||
import { isTribeEnabled } from "../../utils/misc";
|
||||
|
||||
const subgroup: CommandsSubgroup = {
|
||||
title: "Tribe carets...",
|
||||
|
|
@ -38,6 +39,7 @@ const commands: Command[] = [
|
|||
display: "Tribe carets...",
|
||||
icon: "fa-i-cursor",
|
||||
subgroup,
|
||||
available: (): boolean => isTribeEnabled(),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import * as UpdateConfig from "../../config";
|
||||
import { Command, CommandsSubgroup } from "../types";
|
||||
import { isTribeEnabled } from "../../utils/misc";
|
||||
|
||||
const subgroup: CommandsSubgroup = {
|
||||
title: "Tribe delta...",
|
||||
|
|
@ -38,6 +39,7 @@ const commands: Command[] = [
|
|||
display: "Tribe delta...",
|
||||
icon: "fa-exchange-alt",
|
||||
subgroup,
|
||||
available: (): boolean => isTribeEnabled(),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import * as DB from "./db";
|
|||
import * as Notifications from "./elements/notifications";
|
||||
import { isAuthenticated } from "./firebase";
|
||||
import { canSetFunboxWithConfig } from "./test/funbox/funbox-validation";
|
||||
import { isDevEnvironment, reloadAfter } from "./utils/misc";
|
||||
import { isDevEnvironment, isTribeEnabled, reloadAfter } from "./utils/misc";
|
||||
import * as ConfigSchemas from "@monkeytype/schemas/configs";
|
||||
import { roundTo1 } from "@monkeytype/util/numbers";
|
||||
import { capitalizeFirstLetter } from "./utils/strings";
|
||||
|
|
@ -209,12 +209,18 @@ export const configMetadata: ConfigMetadataObject = {
|
|||
displayString: "tribe delta",
|
||||
changeRequiresRestart: false,
|
||||
group: "tribe",
|
||||
isBlocked: () => {
|
||||
return !isTribeEnabled();
|
||||
},
|
||||
},
|
||||
tribeCarets: {
|
||||
icon: "fa-users",
|
||||
displayString: "tribe carets",
|
||||
changeRequiresRestart: false,
|
||||
group: "tribe",
|
||||
isBlocked: () => {
|
||||
return !isTribeEnabled();
|
||||
},
|
||||
},
|
||||
|
||||
// behavior
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import * as Notifications from "../elements/notifications";
|
|||
import tribeSocket from "../tribe/tribe-socket";
|
||||
import { setAutoJoin } from "../tribe/tribe-auto-join";
|
||||
import * as NavigationEvent from "../observables/navigation-event";
|
||||
import { isTribeEnabled } from "../utils/misc";
|
||||
|
||||
//source: https://www.youtube.com/watch?v=OstALBk-jTc
|
||||
// https://www.youtube.com/watch?v=OstALBk-jTc
|
||||
|
|
@ -59,7 +60,7 @@ const routes: Route[] = [
|
|||
return;
|
||||
}
|
||||
|
||||
if (TribeState.getState() >= 5) {
|
||||
if (isTribeEnabled() && TribeState.getState() >= 5) {
|
||||
if (TribeState.getState() === 22 && TribeState.getSelf()?.isLeader) {
|
||||
tribeSocket.out.room.backToLobby();
|
||||
} else {
|
||||
|
|
@ -176,6 +177,11 @@ const routes: Route[] = [
|
|||
{
|
||||
path: "/tribe",
|
||||
load: async (params, options): Promise<void> => {
|
||||
if (!isTribeEnabled()) {
|
||||
await navigate("/", options);
|
||||
return;
|
||||
}
|
||||
|
||||
if (options?.tribeOverride === true) {
|
||||
await PageController.change("tribe", {
|
||||
tribeOverride: options?.tribeOverride ?? false,
|
||||
|
|
@ -198,7 +204,12 @@ const routes: Route[] = [
|
|||
},
|
||||
{
|
||||
path: "/tribe/:roomId",
|
||||
load: async (params): Promise<void> => {
|
||||
load: async (params, options): Promise<void> => {
|
||||
if (!isTribeEnabled()) {
|
||||
await navigate("/", options);
|
||||
return;
|
||||
}
|
||||
|
||||
setAutoJoin(params["roomId"] as string);
|
||||
await PageController.change("tribe", {
|
||||
force: true,
|
||||
|
|
@ -215,6 +226,7 @@ export async function navigate(
|
|||
options = {} as NavigationEvent.NavigateOptions,
|
||||
): Promise<void> {
|
||||
if (
|
||||
isTribeEnabled() &&
|
||||
TribeState.getState() > 5 &&
|
||||
TribeState.getState() < 22 &&
|
||||
!options?.tribeOverride
|
||||
|
|
|
|||
|
|
@ -251,8 +251,10 @@ async function initGroups(): Promise<void> {
|
|||
"customBackgroundSize",
|
||||
"button",
|
||||
);
|
||||
groups["tribeDelta"] = new SettingsGroup("tribeDelta", "button");
|
||||
groups["tribeCarets"] = new SettingsGroup("tribeCarets", "button");
|
||||
if (Misc.isTribeEnabled()) {
|
||||
groups["tribeDelta"] = new SettingsGroup("tribeDelta", "button");
|
||||
groups["tribeCarets"] = new SettingsGroup("tribeCarets", "button");
|
||||
}
|
||||
}
|
||||
|
||||
async function fillSettingsPage(): Promise<void> {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { getActiveFunboxesWithFunction } from "./test/funbox/list";
|
|||
import { configLoadPromise } from "./config";
|
||||
import { authPromise } from "./firebase";
|
||||
import { animate } from "animejs";
|
||||
import { onDocumentReady, qs } from "./utils/dom";
|
||||
import { onDocumentReady, qs, qsa } from "./utils/dom";
|
||||
|
||||
onDocumentReady(async () => {
|
||||
await configLoadPromise;
|
||||
|
|
@ -44,6 +44,18 @@ onDocumentReady(async () => {
|
|||
if (!ServerConfiguration.get()?.connections.enabled) {
|
||||
qs(".accountButtonAndMenu .goToFriends")?.addClass("hidden");
|
||||
}
|
||||
if (Misc.isTribeEnabled()) {
|
||||
qs("header nav .textButton.view-tribe")?.removeClass("hidden");
|
||||
for (const el of qsa(".pageSettings [group='tribe']")) {
|
||||
el.removeClass("hidden");
|
||||
}
|
||||
for (const el of qsa(".pageSettings .settingsGroup.tribe")) {
|
||||
el.removeClass("hidden");
|
||||
}
|
||||
qs(
|
||||
".pageSettings .settingsGroup.quickNav button[href='#group_tribe']",
|
||||
)?.removeClass("hidden");
|
||||
}
|
||||
});
|
||||
}
|
||||
MonkeyPower.init();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ import * as Random from "../utils/random";
|
|||
import TribeSocket from "./tribe-socket";
|
||||
import * as ActivePage from "../states/active-page";
|
||||
import * as TribeState from "./tribe-state";
|
||||
import { escapeRegExp, escapeHTML, isDevEnvironment } from "../utils/misc";
|
||||
import {
|
||||
escapeRegExp,
|
||||
escapeHTML,
|
||||
isTribeEnabled,
|
||||
isDevEnvironment,
|
||||
} from "../utils/misc";
|
||||
import * as Time from "../states/time";
|
||||
import * as TestWords from "../test/test-words";
|
||||
import * as TestStats from "../test/test-stats";
|
||||
|
|
@ -119,6 +124,8 @@ function updateState(newState: number): void {
|
|||
}
|
||||
|
||||
export async function init(): Promise<void> {
|
||||
if (!isTribeEnabled()) return;
|
||||
|
||||
TribePagePreloader.updateIcon("circle-notch", true);
|
||||
// TribePagePreloader.updateText("Waiting for login");
|
||||
// await AccountController.authPromise;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ export type EnvConfig = {
|
|||
recaptchaSiteKey: string;
|
||||
quickLoginEmail: string | undefined;
|
||||
quickLoginPassword: string | undefined;
|
||||
forceTribe: boolean;
|
||||
};
|
||||
|
||||
declare module "virtual:env-config" {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import * as Loader from "../elements/loader";
|
||||
import * as Random from "../utils/random";
|
||||
import { envConfig } from "virtual:env-config";
|
||||
import * as ServerConfiguration from "../ape/server-configuration";
|
||||
import { lastElementFromArray } from "./arrays";
|
||||
import { Config } from "@monkeytype/schemas/configs";
|
||||
import { Mode, Mode2, PersonalBests } from "@monkeytype/schemas/shared";
|
||||
|
|
@ -492,6 +493,11 @@ export function isDevEnvironment(): boolean {
|
|||
return envConfig.isDevelopment;
|
||||
}
|
||||
|
||||
export function isTribeEnabled(): boolean {
|
||||
if (envConfig.forceTribe) return true;
|
||||
return ServerConfiguration.get()?.tribe?.enabled ?? false;
|
||||
}
|
||||
|
||||
export function zipfyRandomArrayIndex(dictLength: number): number {
|
||||
/**
|
||||
* get random index based on probability distribution of Zipf's law,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ export function envConfig(options: {
|
|||
recaptchaSiteKey: "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI",
|
||||
quickLoginEmail: options.env["QUICK_LOGIN_EMAIL"],
|
||||
quickLoginPassword: options.env["QUICK_LOGIN_PASSWORD"],
|
||||
forceTribe: options.env["FORCE_TRIBE"] === "true",
|
||||
};
|
||||
|
||||
const prodConfig: EnvConfig = {
|
||||
|
|
@ -39,6 +40,7 @@ export function envConfig(options: {
|
|||
quickLoginEmail: undefined,
|
||||
quickLoginPassword: undefined,
|
||||
clientVersion: options.clientVersion,
|
||||
forceTribe: options.env["FORCE_TRIBE"] === "true",
|
||||
};
|
||||
|
||||
const envConfig = options.isDevelopment ? devConfig : prodConfig;
|
||||
|
|
|
|||
|
|
@ -127,5 +127,8 @@ export const ConfigurationSchema = z.object({
|
|||
enabled: z.boolean(),
|
||||
maxPerUser: z.number().int().nonnegative(),
|
||||
}),
|
||||
tribe: z.object({
|
||||
enabled: z.boolean(),
|
||||
}),
|
||||
});
|
||||
export type Configuration = z.infer<typeof ConfigurationSchema>;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue