1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-10 13:40:06 +00:00
Files
browser/libs/common/src/tools/achievements/examples/example-validators.ts
✨ Audrey ✨ 7d51b6637c bugfixes
2025-03-21 00:04:04 -04:00

143 lines
4.8 KiB
TypeScript

import { earnedEvent, progressEvent } from "../achievement-events";
import { Type } from "../data";
import { AchievementId, MetricId, AchievementValidator } from "../types";
const ItemCreatedProgress = "item-quantity" as MetricId;
const CredentialGeneratedProgress = "credential-generated" as MetricId;
const TotallyAttachedAchievement = "totally-attached" as AchievementId;
const ItemCreatedMetric = "item-created-metric" as AchievementId;
const UnboundItemCreatedMetric = "unbound-item-created-metric" as AchievementId;
const ItemCreatedAchievement = "item-created" as AchievementId;
const ThreeItemsCreatedAchievement = "three-vault-items-created" as AchievementId;
const FiveItemsCreatedAchievement = "five-vault-items-created" as AchievementId;
const TotallyAttachedValidator = {
achievement: TotallyAttachedAchievement,
name: "Totally attached <3",
description: "Attached a file to a send or item",
validator: Type.HasTag,
active: "until-earned",
hidden: false,
trigger(item) {
return item.tags?.includes("with-attachment") ?? false;
},
award(progress) {
return [earnedEvent(TotallyAttachedAchievement)];
},
} satisfies AchievementValidator;
// 🧠 this validator added to test `measure` in isolation, but
// the pattern of splitting trackers from validators is interesting.
//
// As-is, the design runs all measures before earnings so the logic
// should remain consistent so long as the trackers and validators
// don't emit conflicting logs. The processor's behavior in this
// situation is undefined.
const ItemCreatedTracker = {
achievement: ItemCreatedMetric,
name: `[TRACKER] ${ItemCreatedProgress}`,
description: `Measures ${ItemCreatedProgress}`,
validator: Type.Threshold,
active: { metric: ItemCreatedProgress, high: 1 },
hidden: true,
trigger(item) {
return item.action === "vault-item-added";
},
measure(item, progress) {
const value = 1 + (progress.get(ItemCreatedProgress) ?? 0);
return [progressEvent(ItemCreatedProgress, value)];
},
} satisfies AchievementValidator;
const UnboundItemCreatedTracker = {
achievement: UnboundItemCreatedMetric,
name: `[TRACKER] ${ItemCreatedProgress}`,
description: `Measures ${ItemCreatedProgress}`,
validator: Type.Threshold,
active: { metric: ItemCreatedProgress, low: 1 },
hidden: true,
trigger(item) {
return item.action === "vault-item-added";
},
measure(item, progress) {
const value = 1 + (progress.get(ItemCreatedProgress) ?? 0);
return [progressEvent(ItemCreatedProgress, value)];
},
} satisfies AchievementValidator;
const ItemCreatedValidator = {
achievement: ItemCreatedAchievement,
name: "What an item!",
description: "Add an item to your vault",
validator: Type.Threshold,
active: { metric: ItemCreatedProgress, high: 1 },
hidden: false,
trigger(item) {
return item.action === "vault-item-added";
},
measure(item, progress) {
return [progressEvent(ItemCreatedProgress)];
},
award(progress) {
return [earnedEvent(ItemCreatedAchievement)];
},
} satisfies AchievementValidator;
const ThreeItemsCreatedValidator = {
achievement: ThreeItemsCreatedAchievement,
name: "Three times a charm",
description: "Add three items to your vault",
validator: Type.Threshold,
active: { metric: ItemCreatedProgress, low: 1, high: 3 },
hidden: false,
trigger(item) {
return item.action === "vault-item-added";
},
measure(_item, progress) {
const value = 1 + (progress.get(ItemCreatedProgress) ?? 0);
return [progressEvent(ItemCreatedProgress, value)];
},
award(_measured, progress) {
const value = progress.get(ItemCreatedProgress);
return value === 3 ? [earnedEvent(ThreeItemsCreatedAchievement)] : [];
},
} satisfies AchievementValidator;
const FiveItemsCreatedValidator = {
achievement: FiveItemsCreatedAchievement,
name: "fiiivvve GoOoOoOolllllllD RIIIIIINGS!!!!!!",
description: "Add five items to your vault",
validator: Type.Threshold,
active: { metric: ItemCreatedProgress, low: 3, high: 6 },
hidden: false,
trigger(item) {
return item.action === "vault-item-added";
},
measure(_item, progress) {
const value = 1 + (progress.get(ItemCreatedProgress) ?? 0);
return [progressEvent(ItemCreatedProgress, value)];
},
award(_measured, progress) {
const value = progress.get(ItemCreatedProgress);
return value === 5 ? [earnedEvent(FiveItemsCreatedAchievement)] : [];
},
} satisfies AchievementValidator;
export {
TotallyAttachedAchievement,
TotallyAttachedValidator,
ItemCreatedMetric,
ItemCreatedTracker,
UnboundItemCreatedMetric,
UnboundItemCreatedTracker,
ItemCreatedProgress,
ItemCreatedAchievement,
ItemCreatedValidator,
ThreeItemsCreatedAchievement,
ThreeItemsCreatedValidator,
FiveItemsCreatedAchievement,
FiveItemsCreatedValidator,
CredentialGeneratedProgress,
};