SYMBOL INDEX (1199 symbols across 280 files) FILE: convex/_generated/dataModel.d.ts type TableNames (line 23) | type TableNames = TableNamesInDataModel; type Doc (line 30) | type Doc = DocumentByName< type Id (line 48) | type Id = type DataModel (line 60) | type DataModel = DataModelFromSchemaDefinition; FILE: convex/_generated/server.d.ts type QueryCtx (line 107) | type QueryCtx = GenericQueryCtx; type MutationCtx (line 115) | type MutationCtx = GenericMutationCtx; type ActionCtx (line 123) | type ActionCtx = GenericActionCtx; type DatabaseReader (line 132) | type DatabaseReader = GenericDatabaseReader; type DatabaseWriter (line 143) | type DatabaseWriter = GenericDatabaseWriter; FILE: convex/adminData.ts type AuthCtx (line 11) | type AuthCtx = MutationCtx | QueryCtx; function isAdmin (line 13) | async function isAdmin(ctx: AuthCtx) { function findAuthUserByLegacyId (line 98) | async function findAuthUserByLegacyId(ctx: AuthCtx, legacyId: number) { function toAdminUser (line 114) | function toAdminUser( function getDiscordAccountIdsByAuthUserIds (line 178) | async function getDiscordAccountIdsByAuthUserIds( function getStoriesRoleSnapshotsByLegacyUserIds (line 207) | async function getStoriesRoleSnapshotsByLegacyUserIds( FILE: convex/adminWrite.ts function toLegacyLanguageResponse (line 6) | function toLegacyLanguageResponse(row: { function getNextLegacyId (line 37) | async function getNextLegacyId( function getNextUnusedLegacyId (line 49) | async function getNextUnusedLegacyId( function getLanguageByLegacyId (line 65) | async function getLanguageByLegacyId(ctx: MutationCtx, legacyId: number) { FILE: convex/authMigration.ts constant PAGE_SIZE (line 5) | const PAGE_SIZE = 200; function normalizeUsername (line 129) | function normalizeUsername(input: string): string { FILE: convex/betterAuth/_generated/component.ts type ComponentApi (line 24) | type ComponentApi = FILE: convex/betterAuth/_generated/dataModel.ts type TableNames (line 23) | type TableNames = TableNamesInDataModel; type Doc (line 30) | type Doc = DocumentByName< type Id (line 48) | type Id = type DataModel (line 60) | type DataModel = DataModelFromSchemaDefinition; FILE: convex/betterAuth/_generated/server.ts type QueryCtx (line 118) | type QueryCtx = GenericQueryCtx; type MutationCtx (line 128) | type MutationCtx = GenericMutationCtx; type ActionCtx (line 136) | type ActionCtx = GenericActionCtx; type DatabaseReader (line 145) | type DatabaseReader = GenericDatabaseReader; type DatabaseWriter (line 156) | type DatabaseWriter = GenericDatabaseWriter; FILE: convex/betterAuth/auth.ts function normalizeExpiresAt (line 80) | function normalizeExpiresAt(value: number | Date | null | undefined) { function syncDiscordAccountAvatarFromHook (line 86) | async function syncDiscordAccountAvatarFromHook( FILE: convex/convex-env.d.ts type ProcessEnv (line 2) | interface ProcessEnv { type Process (line 6) | interface Process { FILE: convex/courseContributorBackfill.ts constant DEFAULT_BATCH_SIZE (line 9) | const DEFAULT_BATCH_SIZE = 10; constant MAX_BATCH_SIZE (line 10) | const MAX_BATCH_SIZE = 25; function normalizeBatchSize (line 12) | function normalizeBatchSize(value: number | undefined) { function json (line 20) | function json(data: unknown, status = 200) { function requireCourseContributorBackfillSecret (line 27) | async function requireCourseContributorBackfillSecret(req: Request) { FILE: convex/discordAvatarSync.ts type AdapterWhere (line 11) | type AdapterWhere = Array<{ type AuthAccountRow (line 17) | type AuthAccountRow = { type PaginatedAdapterResponse (line 28) | type PaginatedAdapterResponse = { type BackfillArgs (line 34) | type BackfillArgs = { type BackfillResult (line 40) | type BackfillResult = { constant DEFAULT_BATCH_SIZE (line 54) | const DEFAULT_BATCH_SIZE = 25; constant MAX_BATCH_SIZE (line 55) | const MAX_BATCH_SIZE = 100; function json (line 57) | function json(data: unknown, status = 200) { function requireDiscordAvatarSyncSecret (line 64) | async function requireDiscordAvatarSyncSecret(req: Request) { function normalizeBatchSize (line 97) | function normalizeBatchSize(value: number | undefined) { function dedupeAccounts (line 105) | function dedupeAccounts(accounts: AuthAccountRow[]) { function findManyPage (line 119) | async function findManyPage( function runDiscordAvatarBackfill (line 133) | async function runDiscordAvatarBackfill( FILE: convex/discordBot.ts type Role (line 4) | type Role = "user" | "contributor" | "admin"; function json (line 6) | function json(data: unknown, status = 200) { function requireDiscordSyncSecret (line 13) | async function requireDiscordSyncSecret(req: Request) { type CombineKind (line 46) | type CombineKind = "users" | "publicStories" | "approvals"; type StoriesRoleSyncStatus (line 47) | type StoriesRoleSyncStatus = function parseStoriesRoleSyncStatus (line 55) | function parseStoriesRoleSyncStatus( function parseNumItems (line 71) | function parseNumItems(value: unknown) { function parseKind (line 76) | function parseKind(value: unknown): CombineKind | null { FILE: convex/discordData.ts type AdapterWhere (line 32) | type AdapterWhere = Array<{ type BetterAuthModel (line 37) | type BetterAuthModel = "user" | "account"; type AuthUserRow (line 39) | type AuthUserRow = { type AuthAccountRow (line 46) | type AuthAccountRow = { type PaginatedAdapterResponse (line 51) | type PaginatedAdapterResponse = { function findManyAll (line 57) | async function findManyAll( function chunk (line 81) | function chunk(items: T[], size: number): T[][] { function getContributorAndAdminUsers (line 89) | async function getContributorAndAdminUsers(ctx: QueryCtx) { FILE: convex/editorRead.ts type LanguageDoc (line 7) | type LanguageDoc = Doc<"languages">; type CourseDoc (line 8) | type CourseDoc = Doc<"courses">; type StoryDoc (line 9) | type StoryDoc = Doc<"stories">; type AvatarDoc (line 10) | type AvatarDoc = Doc<"avatars">; type AvatarMappingDoc (line 11) | type AvatarMappingDoc = Doc<"avatar_mappings">; function toNumber (line 36) | function toNumber(value: unknown): number | undefined { function toLanguage (line 45) | function toLanguage(language: LanguageDoc) { function toCourse (line 59) | function toCourse( function getCourseByIdentifier (line 88) | async function getCourseByIdentifier(ctx: QueryCtx, identifier: string) { function getUserNameByLegacyId (line 105) | async function getUserNameByLegacyId(ctx: QueryCtx, legacyIds: number[]) { function getUserNameByAuthDocId (line 128) | async function getUserNameByAuthDocId(ctx: QueryCtx, authDocIds: string[... function buildAvatarRows (line 174) | async function buildAvatarRows( FILE: convex/editorSideEffects.ts constant CONTENT_REPOSITORY (line 8) | const CONTENT_REPOSITORY = "rgerum/unofficial-duolingo-stories-content"; function toBase64Utf8 (line 12) | function toBase64Utf8(value: string) { function getOctokit (line 22) | function getOctokit() { function uploadWithDiffToGithub (line 31) | async function uploadWithDiffToGithub(args: { function getPosthogClient (line 91) | function getPosthogClient() { FILE: convex/landing.ts type LandingCourseItem (line 52) | type LandingCourseItem = { type LandingGroup (line 65) | type LandingGroup = { FILE: convex/languageWrite.ts function toLegacyLanguageResponse (line 6) | function toLegacyLanguageResponse(row: { function getLanguageByLegacyId (line 37) | async function getLanguageByLegacyId( function getLanguageByShort (line 47) | async function getLanguageByShort(ctx: MutationCtx, short?: string | nul... function getAvatarByLegacyId (line 55) | async function getAvatarByLegacyId(ctx: MutationCtx, legacyAvatarId: num... FILE: convex/lib/authorization.ts type AuthCtx (line 3) | type AuthCtx = MutationCtx | QueryCtx; type RoleIdentity (line 5) | type RoleIdentity = { function getIdentity (line 10) | async function getIdentity(ctx: AuthCtx) { function getRole (line 14) | async function getRole(ctx: AuthCtx) { function requireAdmin (line 19) | async function requireAdmin(ctx: AuthCtx) { function requireContributorOrAdmin (line 26) | async function requireContributorOrAdmin(ctx: AuthCtx) { function requireSessionLegacyUserId (line 33) | async function requireSessionLegacyUserId(ctx: AuthCtx) { function getSessionLegacyUserId (line 52) | async function getSessionLegacyUserId(ctx: AuthCtx) { FILE: convex/lib/courseContributors.ts type ContributorCtx (line 6) | type ContributorCtx = QueryCtx | MutationCtx; type AdapterWhere (line 8) | type AdapterWhere = Array<{ type AuthUserRow (line 14) | type AuthUserRow = { type AuthAccountRow (line 21) | type AuthAccountRow = { type PaginatedAdapterResponse (line 26) | type PaginatedAdapterResponse = { type CourseContributor (line 39) | type CourseContributor = { function findManyAll (line 48) | async function findManyAll( function getUsersByLegacyId (line 72) | async function getUsersByLegacyId( function getRankedCourseContributors (line 136) | async function getRankedCourseContributors( function partitionCourseContributors (line 181) | function partitionCourseContributors(contributors: CourseContributor[]) { FILE: convex/lib/courseCounts.ts function recomputeCoursePublishedCount (line 4) | async function recomputeCoursePublishedCount( FILE: convex/lib/discordAvatarSync.ts type DiscordAccountRecord (line 1) | type DiscordAccountRecord = { type DiscordTokenResponse (line 11) | type DiscordTokenResponse = { type DiscordUserResponse (line 18) | type DiscordUserResponse = { type DiscordAvatarSyncResult (line 24) | type DiscordAvatarSyncResult = function getDiscordCredentials (line 38) | function getDiscordCredentials() { function getDiscordBotToken (line 53) | function getDiscordBotToken() { function fetchDiscordUserWithOAuth (line 62) | async function fetchDiscordUserWithOAuth( function fetchDiscordUserById (line 83) | async function fetchDiscordUserById( function refreshDiscordAccessToken (line 110) | async function refreshDiscordAccessToken(refreshToken: string) { function buildDiscordAvatarUrl (line 139) | function buildDiscordAvatarUrl(user: DiscordUserResponse) { function tryFetchDiscordUserWithBot (line 160) | async function tryFetchDiscordUserWithBot(account: DiscordAccountRecord) { function syncDiscordAvatarFromAccount (line 169) | async function syncDiscordAvatarFromAccount( FILE: convex/lib/phpbb.ts function md5Hex (line 5) | function md5Hex(content: string): string { function md5Bytes (line 9) | function md5Bytes(input: Uint8Array): Uint8Array { function bytesToHex (line 17) | function bytesToHex(bytes: Uint8Array): string { function concatBytes (line 25) | function concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array { function phpbbHash (line 35) | function phpbbHash(password: string): string { function hashCryptPrivate (line 43) | function hashCryptPrivate(password: string, setting: string): string { function hashEncode64 (line 74) | function hashEncode64(input: Uint8Array | string, count: number): string { function hashGensaltPrivate (line 113) | function hashGensaltPrivate( function phpbbCheckHash (line 124) | function phpbbCheckHash(password: string, hash: string): boolean { FILE: convex/lib/publicStoryContent.ts type RecordValue (line 4) | type RecordValue = Record; function isRecord (line 6) | function isRecord(value: unknown): value is RecordValue { function sanitizeConvexValue (line 10) | function sanitizeConvexValue(value: unknown): unknown { function compactAudio (line 27) | function compactAudio(value: unknown): unknown { function compactStoryValue (line 41) | function compactStoryValue( function toPublicStoryJson (line 73) | function toPublicStoryJson(json: unknown): unknown { function upsertPublicStoryContent (line 77) | async function upsertPublicStoryContent( function getPublicStoryJson (line 104) | async function getPublicStoryJson( FILE: convex/storyApproval.ts function recomputeCourseContributors (line 21) | async function recomputeCourseContributors( FILE: convex/storyDone.ts function getDoneStoryIdsForCourseIdAndUser (line 125) | async function getDoneStoryIdsForCourseIdAndUser( function upsertStoryDoneState (line 218) | async function upsertStoryDoneState( function getNextStepForCourse (line 250) | async function getNextStepForCourse( function upsertCourseActivity (line 338) | async function upsertCourseActivity( function getCurrentIdentityLegacyUserId (line 366) | async function getCurrentIdentityLegacyUserId( FILE: convex/storyRead.ts function nonEmptyString (line 49) | function nonEmptyString(value: unknown) { FILE: discord_roles/audio_cleanup.py function move (line 14) | def move(source, target): FILE: discord_roles/blame.py function decode_git_stdout (line 8) | def decode_git_stdout(result): function get_commits_per_file (line 14) | def get_commits_per_file(filename): function get_author_percentages (line 20) | def get_author_percentages(filename, ignore_rev=None): function parse_blame_porcelain (line 44) | def parse_blame_porcelain(output, base_file): function get_files_since_commit (line 86) | def get_files_since_commit(commit): function get_new_file_list (line 93) | def get_new_file_list(): function update_repo (line 102) | def update_repo(): function update_output_csv (line 111) | def update_output_csv(): FILE: discord_roles/combine.py function fetch_combine_resource (line 19) | def fetch_combine_resource(kind, *, cursor=None, num_items=200, since_da... function fetch_contributor_users (line 54) | def fetch_contributor_users(): function fetch_public_story_ids (line 86) | def fetch_public_story_ids(): function load_approval_cache (line 110) | def load_approval_cache(): function save_approval_cache (line 130) | def save_approval_cache(data): function update_approval_cache (line 142) | def update_approval_cache(): function get_user_to_discord_mapping (line 200) | def get_user_to_discord_mapping(): function get_user_approval_count (line 208) | def get_user_approval_count(): function join_and_group_data (line 244) | def join_and_group_data(): function get_milestone_grouped (line 274) | def get_milestone_grouped(): function get_stories_role_sync_rows (line 283) | def get_stories_role_sync_rows(): function get_milestone_grouped_debug_missing_links (line 311) | def get_milestone_grouped_debug_missing_links(): function get_milestone_grouped2 (line 334) | def get_milestone_grouped2(): FILE: discord_roles/discord_bot.py function sync_stories_role_status (line 23) | def sync_stories_role_status(snapshots): function get_snapshot_row (line 54) | def get_snapshot_row(row, *, sync_status, assigned_stories_count=None, l... function set_user_roles (line 69) | def set_user_roles(sync_rows): FILE: discord_roles/discord_reacting_bot.py function sync_user_role (line 8) | def sync_user_role(discord_id, write=None): class MyClient (line 45) | class MyClient(discord.Client): method on_ready (line 46) | async def on_ready(self): method on_message (line 49) | async def on_message(self, message): method _is_contributor_request_channel (line 75) | def _is_contributor_request_channel(self, channel): method _get_first_message_if_match (line 82) | async def _get_first_message_if_match(self, channel, message_id): method check_reaction (line 90) | async def check_reaction(self, reaction): method on_raw_reaction_add (line 112) | async def on_raw_reaction_add(self, reaction): method on_raw_reaction_remove (line 143) | async def on_raw_reaction_remove(self, reaction): method on_member_update (line 163) | async def on_member_update(self, before, after): method log (line 212) | async def log(self, message): FILE: discord_roles/env_utils.py function load_env_file (line 4) | def load_env_file(path: Path) -> dict[str, str]: FILE: import_tools/app.py function hello_world (line 9) | def hello_world(): function login (line 16) | def login(): function getfiles (line 23) | def getfiles(): FILE: import_tools/greasmonkey.js function fetch_post (line 8) | function fetch_post(url, data) { function getStories (line 24) | async function getStories(learningLanguage, fromLanguage) { FILE: next.config.js method rewrites (line 11) | async rewrites() { FILE: public/darklight.js function get_current_theme (line 1) | function get_current_theme() { function load (line 19) | function load() { FILE: public/docs/search.js function getPageData (line 4) | async function getPageData(page) { function search (line 47) | async function search() { function display_search (line 75) | function display_search(do_show) { function toggle (line 88) | function toggle(value) { function init (line 100) | function init() { FILE: scripts/backfill-course-contributors.ts constant CONVEX_SITE_URL (line 5) | const CONVEX_SITE_URL = constant COURSE_CONTRIBUTOR_BACKFILL_SECRET (line 10) | const COURSE_CONTRIBUTOR_BACKFILL_SECRET = constant BATCH_SIZE (line 12) | const BATCH_SIZE = parsePositiveNumber( constant BATCH_DELAY_MS (line 16) | const BATCH_DELAY_MS = parsePositiveNumber( constant DRY_RUN (line 20) | const DRY_RUN = parseBooleanEnv( type BackfillResult (line 37) | type BackfillResult = { function parsePositiveNumber (line 48) | function parsePositiveNumber(value: string | undefined, fallback: number) { function parseBooleanEnv (line 58) | function parseBooleanEnv(value: string | undefined, defaultValue: boolea... function sleep (line 66) | function sleep(ms: number) { function runBatch (line 70) | async function runBatch(baseUrl: string, cursor: string | null) { function main (line 101) | async function main() { FILE: scripts/backfill-discord-avatars.ts constant CONVEX_SITE_URL (line 5) | const CONVEX_SITE_URL = constant DISCORD_AVATAR_SYNC_SECRET (line 10) | const DISCORD_AVATAR_SYNC_SECRET = process.env.DISCORD_AVATAR_SYNC_SECRET; constant TOTAL_LIMIT (line 11) | const TOTAL_LIMIT = parseOptionalNumber(process.env.DISCORD_AVATAR_SYNC_... constant BATCH_SIZE (line 12) | const BATCH_SIZE = parsePositiveNumber( constant BATCH_DELAY_MS (line 16) | const BATCH_DELAY_MS = parsePositiveNumber( constant DRY_RUN (line 20) | const DRY_RUN = parseBooleanEnv(process.env.DISCORD_AVATAR_SYNC_DRY_RUN,... type BackfillResult (line 34) | type BackfillResult = { function parseOptionalNumber (line 48) | function parseOptionalNumber(value: string | undefined) { function parsePositiveNumber (line 58) | function parsePositiveNumber(value: string | undefined, fallback: number) { function parseBooleanEnv (line 68) | function parseBooleanEnv(value: string | undefined, defaultValue: boolea... function sleep (line 76) | function sleep(ms: number) { function runBatch (line 80) | async function runBatch( function main (line 115) | async function main() { FILE: scripts/find-missing-story-images.ts constant CONVEX_URL (line 8) | const CONVEX_URL = process.env.NEXT_PUBLIC_CONVEX_URL || process.env.CON... constant CONCURRENCY (line 9) | const CONCURRENCY = Number(process.env.STORY_IMAGE_AUDIT_CONCURRENCY ?? ... constant PUBLISHED_ONLY (line 10) | const PUBLISHED_ONLY = parseBooleanEnv( type StorySummary (line 27) | type StorySummary = { type Finding (line 36) | type Finding = { function mapWithConcurrency (line 44) | async function mapWithConcurrency( function parseBooleanEnv (line 69) | function parseBooleanEnv(value: string | undefined, defaultValue: boolea... function getAllStories (line 77) | async function getAllStories(): Promise { function main (line 105) | async function main() { FILE: src/app/(stories)/(main)/EditorCommandPaletteClient.tsx type SessionUser (line 6) | type SessionUser = { function EditorCommandPaletteClient (line 10) | function EditorCommandPaletteClient() { FILE: src/app/(stories)/(main)/[course_id]/course_page_client.tsx function SetTitle (line 12) | function SetTitle({ children }: { children: React.ReactNode }) { function SetGrid (line 20) | function SetGrid({ function About (line 41) | function About({ about }: { about: string }) { function Contributors (line 51) | function Contributors({ function NoNativeWarning (line 90) | function NoNativeWarning() { function CoursePageClient (line 112) | function CoursePageClient({ FILE: src/app/(stories)/(main)/[course_id]/not-found.tsx function NotFound (line 4) | function NotFound() { FILE: src/app/(stories)/(main)/[course_id]/page.tsx function generateMetadata (line 11) | async function generateMetadata( function generateStaticParams (line 56) | async function generateStaticParams() { function Page (line 68) | async function Page({ FILE: src/app/(stories)/(main)/[course_id]/story_button.tsx type StoryData (line 6) | interface StoryData { function StoryButton (line 14) | function StoryButton({ FILE: src/app/(stories)/(main)/course-dropdown.tsx function LanguageButtonSmall (line 15) | function LanguageButtonSmall({ course }: { course?: CourseData }) { function CourseDropdown (line 37) | function CourseDropdown() { FILE: src/app/(stories)/(main)/course_list.tsx type LandingGroupData (line 11) | interface LandingGroupData { function RenderCourseGroups (line 20) | function RenderCourseGroups({ groups }: { groups: LandingGroupData[] }) { function CourseList (line 51) | function CourseList({ FILE: src/app/(stories)/(main)/faq/page.tsx function Page (line 12) | async function Page() { FILE: src/app/(stories)/(main)/footer_links.tsx function FooterLinks (line 4) | async function FooterLinks({}) { FILE: src/app/(stories)/(main)/get_course_data.ts type CourseData (line 5) | interface CourseData { function get_course_data (line 20) | async function get_course_data() { function get_course (line 24) | async function get_course(short: string) { FILE: src/app/(stories)/(main)/header.tsx function Header (line 1) | function Header({ children }: { children: React.ReactNode }) { FILE: src/app/(stories)/(main)/icons.tsx function Icons (line 11) | function Icons() { FILE: src/app/(stories)/(main)/landing_stats_client.tsx function LandingStatsText (line 6) | function LandingStatsText({ function LandingStatsClientPreloaded (line 27) | function LandingStatsClientPreloaded({ function LandingStatsClientQuery (line 36) | function LandingStatsClientQuery() { function LandingStatsClient (line 41) | function LandingStatsClient({ FILE: src/app/(stories)/(main)/language_button.tsx type LandingCourseButtonData (line 6) | interface LandingCourseButtonData { function LanguageButton (line 18) | function LanguageButton({ FILE: src/app/(stories)/(main)/layout.tsx function Layout (line 35) | function Layout({ children }: { children: React.ReactNode }) { FILE: src/app/(stories)/(main)/not-found.tsx function NotFound (line 4) | function NotFound() { FILE: src/app/(stories)/(main)/page.tsx function Page (line 10) | async function Page({}) { FILE: src/app/(stories)/(main)/privacy_policy/page.tsx function Page (line 13) | async function Page() { FILE: src/app/(stories)/(main)/profile/actions.ts constant STORY_PREFERENCE_COOKIE_MAX_AGE (line 8) | const STORY_PREFERENCE_COOKIE_MAX_AGE = 60 * 60 * 24 * 365; function setHideStoryQuestionsPreference (line 10) | async function setHideStoryQuestionsPreference(hideQuestions: boolean) { function deleteCurrentUserAccount (line 25) | async function deleteCurrentUserAccount() { FILE: src/app/(stories)/(main)/profile/data.ts type ProfileData (line 10) | interface ProfileData { function getProfileData (line 20) | async function getProfileData() { FILE: src/app/(stories)/(main)/profile/page.tsx function Page (line 12) | async function Page() { FILE: src/app/(stories)/(main)/profile/profile.tsx function roleBadgeTone (line 31) | function roleBadgeTone(role: string) { function StatusText (line 39) | function StatusText({ function SettingRow (line 65) | function SettingRow({ function LinkedAccountRow (line 101) | function LinkedAccountRow({ function ProfileAvatar (line 164) | function ProfileAvatar({ function Profile (line 198) | function Profile({ providers }: { providers: ProfileData }) { FILE: src/app/(stories)/learn/page.tsx function Page (line 17) | async function Page() { FILE: src/app/(stories)/learn/welcome.tsx function Page (line 9) | function Page() { FILE: src/app/(stories)/story/[story_id]/auto_play/page.tsx function generateMetadata (line 7) | async function generateMetadata({ function Page (line 35) | async function Page({ FILE: src/app/(stories)/story/[story_id]/auto_play/story_wrapper.tsx function StoryWrapper (line 8) | function StoryWrapper({ storyId }: { storyId: number }) { FILE: src/app/(stories)/story/[story_id]/getStory.ts function get_story (line 4) | async function get_story(story_id: number) { type StoryData (line 10) | type StoryData = NonNullable>>; FILE: src/app/(stories)/story/[story_id]/loading.tsx function Loading (line 6) | function Loading() { FILE: src/app/(stories)/story/[story_id]/not-found.tsx function NotFound (line 4) | function NotFound() { FILE: src/app/(stories)/story/[story_id]/page.tsx function generateMetadata (line 27) | async function generateMetadata({ function Page (line 55) | async function Page({ FILE: src/app/(stories)/story/[story_id]/script/page.tsx function generateMetadata (line 10) | async function generateMetadata({ function getNavigationMode (line 31) | async function getNavigationMode() { function Page (line 42) | async function Page({ FILE: src/app/(stories)/story/[story_id]/script/story_wrapper.tsx function StoryWrapper (line 7) | function StoryWrapper({ FILE: src/app/(stories)/story/[story_id]/story_wrapper.tsx function StoryWrapper (line 18) | function StoryWrapper({ FILE: src/app/(stories)/story/[story_id]/test/page.tsx function Page (line 5) | async function Page({ FILE: src/app/(stories)/story/[story_id]/test/story_wrapper.tsx function StoryWrapper (line 8) | function StoryWrapper({ storyId }: { storyId: number }) { FILE: src/app/(stories)/story/layout.tsx function Layout (line 21) | function Layout({ children }: { children: React.ReactNode }) { FILE: src/app/admin/AdminDialogTrigger.tsx type AdminDialogTriggerProps (line 10) | interface AdminDialogTriggerProps { function AdminDialogTrigger (line 17) | function AdminDialogTrigger({ FILE: src/app/admin/AdminHeader.tsx function AdminButton (line 12) | function AdminButton({ function AdminHeader (line 34) | async function AdminHeader() { FILE: src/app/admin/FlagName.tsx function FlagName (line 4) | function FlagName({ FILE: src/app/admin/courses/courses.tsx type CourseProps (line 20) | interface CourseProps { type AdminLanguageProps (line 33) | interface AdminLanguageProps { function InputLanguage (line 50) | function InputLanguage({ function EditCourse (line 143) | function EditCourse({ function TableRow (line 324) | function TableRow({ function CourseList (line 436) | function CourseList({ FILE: src/app/admin/courses/page.tsx function Page (line 3) | function Page() { FILE: src/app/admin/courses/page_client.tsx function CourseListClient (line 8) | function CourseListClient() { FILE: src/app/admin/edit_dialog.tsx function Content (line 16) | function Content({ children }: { children: React.ReactNode }) { function DialogTitle (line 42) | function DialogTitle({ function DialogDescription (line 49) | function DialogDescription({ function Fieldset (line 65) | function Fieldset({ function Label (line 80) | function Label({ function InputArea (line 126) | function InputArea({ function InputText (line 141) | function InputText({ function InputTextArea (line 164) | function InputTextArea({ function InputBool (line 187) | function InputBool({ FILE: src/app/admin/languages/language_list.tsx type Language (line 19) | interface Language { type EditLanguageProps (line 29) | interface EditLanguageProps { function EditLanguage (line 37) | function EditLanguage({ type TableRowProps (line 184) | interface TableRowProps { function TableRow (line 191) | function TableRow({ type LanguageListProps (line 266) | interface LanguageListProps { function LanguageList (line 270) | function LanguageList({ all_languages }: LanguageListProps) { FILE: src/app/admin/languages/page.tsx function Page (line 3) | function Page() { FILE: src/app/admin/languages/page_client.tsx function LanguageListClient (line 8) | function LanguageListClient() { FILE: src/app/admin/layout.tsx function Layout (line 4) | async function Layout({ FILE: src/app/admin/page.tsx function Page (line 1) | function Page({}) { FILE: src/app/admin/story/[story_id]/actions.ts function requireAdmin (line 7) | async function requireAdmin() { function togglePublished (line 14) | async function togglePublished( function removeApproval (line 26) | async function removeApproval( FILE: src/app/admin/story/[story_id]/page.tsx function Page (line 3) | async function Page({ FILE: src/app/admin/story/[story_id]/story_display.tsx function StoryDisplay (line 19) | function StoryDisplay({ storyId }: { storyId: number }) { FILE: src/app/admin/story/page.tsx function Page (line 8) | function Page() { FILE: src/app/admin/users/[user_id]/actions.ts function setUserActivatedAction (line 25) | async function setUserActivatedAction(input: unknown) { function setUserWriteAction (line 34) | async function setUserWriteAction(input: unknown) { function setUserDeleteAction (line 43) | async function setUserDeleteAction(input: unknown) { FILE: src/app/admin/users/[user_id]/page.tsx function user_properties (line 7) | async function user_properties(id: string) { function Page (line 34) | async function Page({ FILE: src/app/admin/users/[user_id]/schema.ts type AdminUser (line 29) | type AdminUser = z.infer; FILE: src/app/admin/users/[user_id]/user_display.tsx function setUserActivated (line 19) | async function setUserActivated(data: { function setUserWrite (line 26) | async function setUserWrite(data: { id: number; write: 0 | 1 | boolean }) { function setUserDelete (line 30) | async function setUserDelete(data: { id: number }) { function Activate (line 34) | function Activate({ user }: { user: AdminUser }) { function Write (line 54) | function Write({ user }: { user: AdminUser }) { function UserDisplay (line 74) | function UserDisplay({ user }: { user: AdminUser }) { FILE: src/app/admin/users/page.tsx constant LOAD_STEP (line 5) | const LOAD_STEP = 50; function normalizeQuery (line 7) | function normalizeQuery(value: string | string[] | undefined) { type FilterValue (line 13) | type FilterValue = "all" | "yes" | "no"; type RoleFilterValue (line 14) | type RoleFilterValue = "all" | "user" | "contributor" | "admin"; function normalizeFilter (line 16) | function normalizeFilter(value: string | string[] | undefined): FilterVa... function normalizeRoleFilter (line 22) | function normalizeRoleFilter( function Page (line 31) | async function Page({ FILE: src/app/admin/users/user_list.tsx type AdminUserList (line 24) | type AdminUserList = AdminUser & { admin?: boolean; rowKey?: string }; type FilterValue (line 26) | type FilterValue = "all" | "yes" | "no"; type RoleFilterValue (line 27) | type RoleFilterValue = "all" | "user" | "contributor" | "admin"; type UserListProps (line 29) | interface UserListProps { type AdminFilters (line 39) | type AdminFilters = { type PendingAction (line 44) | type PendingAction = "search" | "filters" | "loadMore" | null; function formatRegistered (line 46) | function formatRegistered(value: Date | string | undefined) { function buildQueryString (line 59) | function buildQueryString(query: string, limit: number, filters: AdminFi... function getRoleLabel (line 76) | function getRoleLabel(user: AdminUserList) { function getStoriesRoleTitle (line 82) | function getStoriesRoleTitle(user: AdminUserList) { function ActivatedStatus (line 106) | function ActivatedStatus({ activated }: { activated: boolean | undefined... function DiscordAvatar (line 128) | function DiscordAvatar({ user }: { user: AdminUserList }) { function UserList (line 168) | function UserList({ FILE: src/app/api/og-course/route.tsx function get_flag_id (line 6) | function get_flag_id(iso: string | null): number { function GET (line 64) | async function GET(request: NextRequest) { FILE: src/app/api/og-story/route.tsx function GET (line 5) | async function GET(request: NextRequest) { FILE: src/app/api/og/route.tsx function GET (line 5) | async function GET(_request: NextRequest) { FILE: src/app/audio/_lib/audio/azure_tts.ts function get_raw (line 6) | function get_raw(text: string): string { function synthesizeSpeechAzure (line 20) | async function synthesizeSpeechAzure( function getVoices (line 103) | async function getVoices(): Promise { function isValidVoice (line 127) | function isValidVoice(voice: string): boolean { FILE: src/app/audio/_lib/audio/elevenlabs.ts type GenerateResult (line 14) | interface GenerateResult { function generate (line 19) | async function generate( function synthesizeSpeechElevenLabs (line 111) | async function synthesizeSpeechElevenLabs( function getUserInfo (line 171) | async function getUserInfo(): Promise { function isValidVoice (line 184) | async function isValidVoice(voiceId: string): Promise { function getVoices (line 202) | async function getVoices(): Promise { FILE: src/app/audio/_lib/audio/google.ts function synthesizeSpeechGoogle (line 6) | async function synthesizeSpeechGoogle( type MarkData (line 83) | interface MarkData { function add_marks (line 90) | function add_marks(text: string): [string, MarkData[]] { type GoogleVoice (line 113) | interface GoogleVoice { function getVoices (line 119) | async function getVoices(): Promise { function isValidVoice (line 151) | function isValidVoice(voice: string): boolean { FILE: src/app/audio/_lib/audio/polly.ts function synthesizeSpeechCall (line 24) | async function synthesizeSpeechCall( function streamToString (line 42) | function streamToString(stream: Readable): Promise { function streamToBuffer (line 51) | function streamToBuffer(stream: Readable): Promise { function streamToBase64 (line 60) | async function streamToBase64(stream: Readable): Promise { function synthesizeSpeechPolly (line 76) | async function synthesizeSpeechPolly( function getVoices (line 159) | async function getVoices(): Promise { function isValidVoice (line 189) | function isValidVoice(voice: string): boolean { function getVoiceData (line 193) | async function getVoiceData(voice: string): Promise { function exists (line 22) | async function exists(filename: string): Promise { function POST (line 34) | async function POST(req: NextRequest) { FILE: src/app/audio/elevenlabs_quota/page.tsx function Page (line 3) | async function Page() { FILE: src/app/audio/upload/route.ts function mkdir (line 7) | async function mkdir(folderName: string): Promise { function exists (line 20) | async function exists(filename: string): Promise { function POST (line 32) | async function POST(req: NextRequest) { FILE: src/app/audio/voices/route.ts function GET (line 8) | async function GET(_req: NextRequest) { FILE: src/app/auth/admin/layout.tsx function Layout (line 5) | async function Layout({ FILE: src/app/auth/admin/page.tsx function Page (line 6) | function Page({}) { FILE: src/app/auth/editor/layout.tsx type LayoutProps (line 5) | interface LayoutProps { function Layout (line 9) | async function Layout({ children }: LayoutProps) { FILE: src/app/auth/editor/page.tsx function Page (line 8) | function Page() { FILE: src/app/auth/layout.tsx function Layout (line 22) | function Layout({ children }: { children: React.ReactNode }) { FILE: src/app/auth/register/page.tsx function Page (line 6) | async function Page({}) { FILE: src/app/auth/register/register.tsx function Register (line 18) | function Register() { FILE: src/app/auth/reset_pw/page.tsx function Page (line 6) | async function Page({ FILE: src/app/auth/reset_pw/reset_pw.tsx function ResetPassword (line 17) | function ResetPassword() { FILE: src/app/auth/signin/login_options.tsx constant PENDING_SIGNIN_STORAGE_KEY (line 20) | const PENDING_SIGNIN_STORAGE_KEY = "posthog_pending_signin"; function LoginOptions (line 22) | function LoginOptions(props: { FILE: src/app/auth/signin/page.tsx type ProviderProps (line 6) | interface ProviderProps { function Page (line 17) | async function Page({ FILE: src/app/dev/story-footer-button-test/page.tsx function Page (line 102) | function Page() { FILE: src/app/docs/[[...slug]]/doc_data.ts function getPageData (line 6) | async function getPageData(path: string) { type DocData (line 25) | interface DocData { FILE: src/app/docs/[[...slug]]/page.tsx function generateStaticParams (line 28) | async function generateStaticParams() { function generateMetadata (line 41) | async function generateMetadata({ function save_tag (line 55) | function save_tag(tag: string) { function CustomMDX (line 91) | function CustomMDX(props: { source: string }) { function SlugToPath (line 100) | function SlugToPath(slug: string[]) { type Heading (line 110) | interface Heading { function getHeadings (line 116) | function getHeadings(title: string, body: string) { function Page (line 127) | async function Page({ FILE: src/app/docs/layout.tsx function Layout (line 12) | async function Layout({ FILE: src/app/docs/loading.tsx function Loading (line 8) | function Loading() { FILE: src/app/editor/(course)/course/[course_id]/import/[from_id]/import_list.tsx function ImportList (line 10) | function ImportList({ function pad (line 136) | function pad(x: number) { FILE: src/app/editor/(course)/course/[course_id]/import/[from_id]/page.tsx function generateMetadata (line 8) | async function generateMetadata({ function Page (line 27) | async function Page({ FILE: src/app/editor/(course)/course/[course_id]/import/[from_id]/page_client.tsx function ImportPageClient (line 12) | function ImportPageClient({ FILE: src/app/editor/(course)/course/[course_id]/localization/page.tsx function getCanonicalLocalizationPath (line 8) | function getCanonicalLocalizationPath(courseShort: string) { function generateMetadata (line 12) | async function generateMetadata({ function Page (line 32) | async function Page({ FILE: src/app/editor/(course)/course/[course_id]/localization/page_client.tsx function CourseLocalizationPageClient (line 12) | function CourseLocalizationPageClient({ FILE: src/app/editor/(course)/course/[course_id]/page.tsx function generateMetadata (line 7) | async function generateMetadata({ function Page (line 26) | async function Page({ FILE: src/app/editor/(course)/course/[course_id]/page_client.tsx function CourseEditorPageClient (line 13) | function CourseEditorPageClient({ FILE: src/app/editor/(course)/course/[course_id]/story/[story]/audio-cutter/page.tsx function Page (line 4) | async function Page({ FILE: src/app/editor/(course)/course/[course_id]/story/[story]/audio-cutter/page_client.tsx function AudioCutterPageClient (line 43) | function AudioCutterPageClient({ type LanguageData (line 428) | type LanguageData = { type UploadedSegment (line 434) | type UploadedSegment = AudioCutterPreparedSegment & { function getElementAudio (line 438) | function getElementAudio( function getAudioCutterTranscriptItems (line 446) | function getAudioCutterTranscriptItems(elements: StoryElement[]) { function stripAudioPathPrefix (line 491) | function stripAudioPathPrefix(filename: string) { function uploadAudioFile (line 499) | async function uploadAudioFile(file: File, storyId: number) { function applyAudioUpdatesToText (line 540) | function applyAudioUpdatesToText( function toConvexValue (line 581) | function toConvexValue(value: unknown): unknown { function StoryNavButton (line 594) | function StoryNavButton({ function ChevronIcon (line 638) | function ChevronIcon({ direction }: { direction: "left" | "right" }) { FILE: src/app/editor/(course)/course/[course_id]/story/[story]/layout.tsx function Layout (line 3) | function Layout({ children }: { children: React.ReactNode }) { FILE: src/app/editor/(course)/course/[course_id]/story/[story]/page.tsx function getCanonicalStoryEditorPath (line 8) | function getCanonicalStoryEditorPath(courseShort: string, storyId: numbe... function generateMetadata (line 12) | async function generateMetadata({ function Page (line 36) | async function Page({ FILE: src/app/editor/(course)/course/[course_id]/voices/edit/page.tsx function getCanonicalVoicesEditPath (line 8) | function getCanonicalVoicesEditPath(courseShort: string) { function generateMetadata (line 12) | async function generateMetadata({ function Page (line 32) | async function Page({ FILE: src/app/editor/(course)/course/[course_id]/voices/edit/page_client.tsx function CourseVoicesEditPageClient (line 17) | function CourseVoicesEditPageClient({ FILE: src/app/editor/(course)/course/[course_id]/voices/page.tsx function getCanonicalVoicesPath (line 8) | function getCanonicalVoicesPath(courseShort: string) { function generateMetadata (line 12) | async function generateMetadata({ function Page (line 32) | async function Page({ FILE: src/app/editor/(course)/course/[course_id]/voices/page_client.tsx function CourseVoicesPageClient (line 16) | function CourseVoicesPageClient({ FILE: src/app/editor/(course)/course_list.tsx type CourseListProps (line 11) | interface CourseListProps { function CourseList (line 17) | function CourseList({ FILE: src/app/editor/(course)/course_view_memory.ts constant COURSE_SCROLL_KEY_PREFIX (line 3) | const COURSE_SCROLL_KEY_PREFIX = "editor-course-scroll:"; constant COURSE_FILTER_KEY_PREFIX (line 4) | const COURSE_FILTER_KEY_PREFIX = "editor-course-filter:"; constant COURSE_SCROLL_CONTAINER_SELECTOR (line 5) | const COURSE_SCROLL_CONTAINER_SELECTOR = constant COURSE_FILTER_VALUES (line 7) | const COURSE_FILTER_VALUES = [ type CourseFilterValue (line 15) | type CourseFilterValue = (typeof COURSE_FILTER_VALUES)[number]; function getCourseScrollKey (line 17) | function getCourseScrollKey(courseIdentifier: string) { function getCourseFilterKey (line 21) | function getCourseFilterKey(courseIdentifier: string) { function getCourseScrollContainer (line 25) | function getCourseScrollContainer() { function rememberCourseScrollPosition (line 31) | function rememberCourseScrollPosition(courseIdentifier: string) { function readCourseScrollPosition (line 43) | function readCourseScrollPosition(courseIdentifier: string) { function rememberCourseFilter (line 56) | function rememberCourseFilter( function readCourseFilter (line 65) | function readCourseFilter( function restoreCourseScrollPosition (line 78) | function restoreCourseScrollPosition( function isCourseFilterValue (line 125) | function isCourseFilterValue(value: string): value is CourseFilterValue { FILE: src/app/editor/(course)/edit_list.tsx type StoryState (line 28) | type StoryState = "draft" | "feedback" | "finished" | "published"; type StoryFilter (line 29) | type StoryFilter = "all" | StoryState; constant STORY_FILTER_ORDER (line 31) | const STORY_FILTER_ORDER: StoryFilter[] = [ function EditList (line 39) | function EditList({ function getStoryState (line 396) | function getStoryState(story: Pick { function Page (line 13) | async function Page({}) { FILE: src/app/editor/(course)/swipe.tsx type SwiperSideBarProps (line 9) | interface SwiperSideBarProps { function SwiperSideBar (line 13) | function SwiperSideBar({ children }: SwiperSideBarProps) { FILE: src/app/editor/(course)/types.ts type CourseProps (line 1) | type CourseProps = { type ContributorSummaryProps (line 21) | type ContributorSummaryProps = { type DetailedCourseProps (line 28) | type DetailedCourseProps = Omit< type StoryListDataProps (line 36) | type StoryListDataProps = { type CourseImportProps (line 53) | type CourseImportProps = { FILE: src/app/editor/_components/breadcrumbs.tsx type BreadcrumbLanguage (line 6) | interface BreadcrumbLanguage { type BreadcrumbStoryData (line 11) | interface BreadcrumbStoryData { type BreadcrumbPartData (line 16) | interface BreadcrumbPartData { function MyLink (line 25) | function MyLink({ function BreadcrumbPart (line 44) | function BreadcrumbPart({ function Breadcrumbs (line 121) | function Breadcrumbs({ path }: { path: BreadcrumbPartData[] }) { FILE: src/app/editor/_components/editor_command_palette.tsx type PaletteSection (line 45) | type PaletteSection = "root" | "editor" | "admin" | "public"; type AdminListSection (line 46) | type AdminListSection = "courses" | "languages"; type EditorStoryState (line 47) | type EditorStoryState = "draft" | "feedback" | "finished" | "published"; type PaletteIcon (line 48) | type PaletteIcon = type PublicCourseListItem (line 63) | type PublicCourseListItem = { type PublicCourseStory (line 74) | type PublicCourseStory = { type PublicCoursePageData (line 82) | type PublicCoursePageData = { type AdminLanguageItem (line 91) | type AdminLanguageItem = { type AdminCourseItem (line 101) | type AdminCourseItem = { type PaletteFlag (line 114) | type PaletteFlag = { type AdminCourseData (line 120) | type AdminCourseData = { type PaletteItem (line 125) | type PaletteItem = { function EditorCommandPalette (line 161) | function EditorCommandPalette({ function openPaletteInstant (line 1390) | function openPaletteInstant( function resetPaletteState (line 1437) | function resetPaletteState( function getInitialSection (line 1459) | function getInitialSection({ function getCourseIdentifier (line 1480) | function getCourseIdentifier(course: CourseProps) { function getCourseKey (line 1484) | function getCourseKey(course: CourseProps) { function getPublicCourseKey (line 1488) | function getPublicCourseKey(course: PublicCourseListItem) { function matchesCourseSearch (line 1492) | function matchesCourseSearch(course: CourseProps, normalizedQuery: strin... function matchesPublicCourseSearch (line 1513) | function matchesPublicCourseSearch( function matchesPaletteSearch (line 1535) | function matchesPaletteSearch(item: PaletteItem, normalizedQuery: string) { function appendRankedPaletteItems (line 1548) | function appendRankedPaletteItems( function getPaletteSearchScore (line 1570) | function getPaletteSearchScore(item: PaletteItem, normalizedQuery: strin... function getEmptyState (line 1594) | function getEmptyState( function getEditorStoryState (line 1641) | function getEditorStoryState( function getEditorStoryStateLabel (line 1650) | function getEditorStoryStateLabel(state: EditorStoryState) { function PaletteSectionHeading (line 1657) | function PaletteSectionHeading({ function PaletteListItem (line 1677) | function PaletteListItem({ function getPaletteItemIcon (line 1881) | function getPaletteItemIcon(icon: PaletteIcon | undefined) { FILE: src/app/editor/_components/header_context.tsx type EditorHeaderSlotName (line 6) | type EditorHeaderSlotName = "breadcrumbs" | "actions"; type EditorHeaderContextValue (line 8) | type EditorHeaderContextValue = { function EditorHeaderProvider (line 16) | function EditorHeaderProvider({ function useEditorHeaderContext (line 53) | function useEditorHeaderContext() { function useEditorHeaderSlotRef (line 61) | function useEditorHeaderSlotRef(slot: EditorHeaderSlotName) { function EditorHeaderPortal (line 72) | function EditorHeaderPortal({ function EditorHeaderBreadcrumbs (line 87) | function EditorHeaderBreadcrumbs({ function EditorHeaderActions (line 95) | function EditorHeaderActions({ FILE: src/app/editor/_components/header_shell.tsx function EditorHeaderShell (line 8) | function EditorHeaderShell() { FILE: src/app/editor/_components/page_layout.tsx function EditorPageLayout (line 6) | function EditorPageLayout({ FILE: src/app/editor/_components/story_editor_preferences.tsx constant EDITOR_STORY_PREFERENCES_STORAGE_KEY (line 5) | const EDITOR_STORY_PREFERENCES_STORAGE_KEY = "editor_story_preferences"; type StoryEditorPreferencesValue (line 7) | type StoryEditorPreferencesValue = { function readInitialPreferences (line 17) | function readInitialPreferences() { function StoryEditorPreferencesProvider (line 52) | function StoryEditorPreferencesProvider({ function useStoryEditorPreferences (line 93) | function useStoryEditorPreferences() { FILE: src/app/editor/editor_button.tsx function EditorButton (line 4) | function EditorButton({ FILE: src/app/editor/language/[language]/language_editor.tsx type PlayFn (line 25) | type PlayFn = ( function LanguageEditor (line 31) | function LanguageEditor({ function Layout (line 92) | function Layout({ type AvatarData (line 177) | interface AvatarData { function Avatar (line 185) | function Avatar(props: { type PlayButtonProps (line 325) | interface PlayButtonProps { function PlayButton (line 331) | function PlayButton(props: PlayButtonProps) { function SpeakerEntry (line 377) | function SpeakerEntry(props: { function AvatarNames (line 434) | function AvatarNames({ FILE: src/app/editor/language/[language]/layout.tsx function Layout (line 4) | function Layout({ children }: { children: React.ReactNode }) { FILE: src/app/editor/language/[language]/page.tsx function getCanonicalVoicesPath (line 7) | function getCanonicalVoicesPath(courseShort: string) { function generateMetadata (line 11) | async function generateMetadata({ function Page (line 44) | async function Page({ FILE: src/app/editor/language/[language]/page_client.tsx function LanguageEditorPageClient (line 6) | function LanguageEditorPageClient({ FILE: src/app/editor/language/[language]/tts_edit/page.tsx function getCanonicalVoicesEditPath (line 8) | function getCanonicalVoicesEditPath(courseShort: string) { function generateMetadata (line 12) | async function generateMetadata({ function Page (line 45) | async function Page({ FILE: src/app/editor/language/[language]/tts_edit/page_client.tsx function LanguageTtsEditorPageClient (line 10) | function LanguageTtsEditorPageClient({ FILE: src/app/editor/language/[language]/tts_edit/tts_edit.tsx function Tts_edit (line 55) | function Tts_edit({ FILE: src/app/editor/language/[language]/types.ts type AvatarNamesType (line 1) | type AvatarNamesType = { type SpeakersType (line 10) | type SpeakersType = { type LanguageType (line 19) | type LanguageType = { type CourseStudType (line 31) | type CourseStudType = { FILE: src/app/editor/layout.tsx function Layout (line 7) | async function Layout({ FILE: src/app/editor/localization/[language]/layout.tsx function Layout (line 4) | function Layout({ children }: { children: React.ReactNode }) { FILE: src/app/editor/localization/[language]/localization_editor.tsx type LanguageType (line 11) | type LanguageType = { type CourseType (line 18) | type CourseType = { type LocalizationRow (line 22) | type LocalizationRow = { function LocalizationEditor (line 28) | function LocalizationEditor({ function Layout (line 78) | function Layout({ function ListLocalizations (line 115) | function ListLocalizations({ FILE: src/app/editor/localization/[language]/page.tsx type LanguageType (line 6) | interface LanguageType { type CourseType (line 13) | interface CourseType { type PageProps (line 19) | interface PageProps { function getCanonicalLocalizationPath (line 23) | function getCanonicalLocalizationPath(courseShort: string) { function get_language (line 27) | async function get_language(id: string) { function generateMetadata (line 39) | async function generateMetadata({ params }: PageProps) { function Page (line 63) | async function Page({ params }: PageProps) { FILE: src/app/editor/localization/[language]/page_client.tsx function LocalizationPageClient (line 6) | function LocalizationPageClient({ FILE: src/app/editor/localization/[language]/text_edit.tsx type TextEditProps (line 4) | interface TextEditProps { function TextEdit (line 10) | function TextEdit({ FILE: src/app/editor/story/[story]/audio-cutter-dialog.tsx constant DEFAULT_WAVEFORM_ZOOM (line 36) | const DEFAULT_WAVEFORM_ZOOM = 180; constant MIN_WAVEFORM_ZOOM (line 37) | const MIN_WAVEFORM_ZOOM = 24; constant MAX_WAVEFORM_ZOOM (line 38) | const MAX_WAVEFORM_ZOOM = 420; constant WAVEFORM_ZOOM_STEP (line 39) | const WAVEFORM_ZOOM_STEP = 24; constant DEFAULT_SEGMENT_LENGTH_SECONDS (line 40) | const DEFAULT_SEGMENT_LENGTH_SECONDS = 1.8; constant MIN_SEGMENT_LENGTH_SECONDS (line 41) | const MIN_SEGMENT_LENGTH_SECONDS = 0.25; constant MIN_PERSISTED_NEW_SEGMENT_SECONDS (line 42) | const MIN_PERSISTED_NEW_SEGMENT_SECONDS = 0.1; constant WAVEFORM_TO_TRANSCRIPT_SYNC_LOCK_MS (line 43) | const WAVEFORM_TO_TRANSCRIPT_SYNC_LOCK_MS = 700; constant SILENCE_WINDOW_SECONDS (line 44) | const SILENCE_WINDOW_SECONDS = 0.02; constant DEFAULT_DETECTION_MIN_SILENCE_SECONDS (line 45) | const DEFAULT_DETECTION_MIN_SILENCE_SECONDS = 1; constant DEFAULT_DETECTION_START_BUFFER_SECONDS (line 46) | const DEFAULT_DETECTION_START_BUFFER_SECONDS = 0.04; constant DEFAULT_DETECTION_END_BUFFER_SECONDS (line 47) | const DEFAULT_DETECTION_END_BUFFER_SECONDS = 0.04; constant DEFAULT_MAX_INTERNAL_SILENCE_SECONDS (line 48) | const DEFAULT_MAX_INTERNAL_SILENCE_SECONDS = 0.3; constant DETECTION_SETTINGS_STORAGE_KEY (line 49) | const DETECTION_SETTINGS_STORAGE_KEY = "audio-cutter-detection-settings-... constant SHRINK_WRAP_STABILITY_EPSILON_SECONDS (line 50) | const SHRINK_WRAP_STABILITY_EPSILON_SECONDS = 0.01; constant MP3_BITRATE_KBPS (line 51) | const MP3_BITRATE_KBPS = 128; constant MP3_SAMPLE_BLOCK_SIZE (line 52) | const MP3_SAMPLE_BLOCK_SIZE = 1152; constant MIN_WORD_MARK_GAP_MS (line 53) | const MIN_WORD_MARK_GAP_MS = 20; constant SEGMENT_COLOR (line 54) | const SEGMENT_COLOR = "rgba(28,176,246,0.2)"; constant SEGMENT_BORDER_COLOR (line 55) | const SEGMENT_BORDER_COLOR = "rgba(15,95,131,0.4)"; constant SEGMENT_ACTIVE_BORDER_COLOR (line 56) | const SEGMENT_ACTIVE_BORDER_COLOR = "rgba(28,176,246,0.95)"; type TimeRange (line 62) | type TimeRange = { type Segment (line 67) | type Segment = { type MergePreview (line 75) | type MergePreview = { type SegmentDraft (line 80) | type SegmentDraft = { type AudioSilenceAnalysis (line 86) | type AudioSilenceAnalysis = { type CachedAudioSegmentation (line 98) | type CachedAudioSegmentation = { type DetectionSettings (line 103) | type DetectionSettings = { type SegmentRegion (line 110) | type SegmentRegion = { type RegionsPlugin (line 128) | type RegionsPlugin = { type SegmentedPlaybackState (line 154) | type SegmentedPlaybackState = { constant EMPTY_REGIONS_PLUGIN (line 160) | const EMPTY_REGIONS_PLUGIN: RegionsPlugin = { function sortSegments (line 175) | function sortSegments(segments: Segment[]) { function clamp (line 179) | function clamp(value: number, min: number, max: number) { function formatSeconds (line 183) | function formatSeconds(value: number) { function getFileBaseName (line 191) | function getFileBaseName(filename: string) { function getErrorMessage (line 196) | function getErrorMessage(error: unknown, fallback: string) { function waitForNextAnimationFrame (line 200) | function waitForNextAnimationFrame() { function createSegmentId (line 206) | function createSegmentId() { function getWaveformScrollElement (line 210) | function getWaveformScrollElement( function isEditableTarget (line 225) | function isEditableTarget(target: EventTarget | null) { function renderTextWithHighlightedWord (line 237) | function renderTextWithHighlightedWord( function getSegmentsFromPlugin (line 280) | function getSegmentsFromPlugin(plugin: RegionsPlugin) { function getOverlappingRegion (line 291) | function getOverlappingRegion( function overlapsSegment (line 313) | function overlapsSegment( function sortRanges (line 322) | function sortRanges(ranges: TimeRange[]) { function normalizeRanges (line 326) | function normalizeRanges( function getTotalRangeDuration (line 349) | function getTotalRangeDuration(ranges: TimeRange[] | undefined) { function getKeepRangeEnd (line 356) | function getKeepRangeEnd( function getEffectiveSegmentDuration (line 364) | function getEffectiveSegmentDuration(segment: { function getKeepRanges (line 375) | function getKeepRanges(bounds: TimeRange, skipRanges: TimeRange[] | unde... function mapPlayableOffsetToAbsoluteTime (line 402) | function mapPlayableOffsetToAbsoluteTime( function clampTimeToKeepRanges (line 420) | function clampTimeToKeepRanges(timeSeconds: number, keepRanges: TimeRang... function getTranscriptWordTokens (line 445) | function getTranscriptWordTokens(text: string) { function getApproximateWordMarks (line 455) | function getApproximateWordMarks(text: string, segment: Segment): AudioM... function getApproximateWordPlaybackRange (line 495) | function getApproximateWordPlaybackRange( function applyWordMarkTimeOverrides (line 523) | function applyWordMarkTimeOverrides( function getActiveWordMarkIndex (line 586) | function getActiveWordMarkIndex( function getKeypointsFromWordMarks (line 623) | function getKeypointsFromWordMarks(marks: AudioMark[]) { function sanitizeDetectionSettings (line 640) | function sanitizeDetectionSettings( function getDetectionSettingsCacheKey (line 668) | function getDetectionSettingsCacheKey(settings: DetectionSettings) { function loadPersistedDetectionSettings (line 677) | function loadPersistedDetectionSettings() { function analyzeAudioSilence (line 691) | function analyzeAudioSilence( function detectSpeechSegmentsFromAnalysis (line 746) | function detectSpeechSegmentsFromAnalysis({ function getSegmentSkipRangesFromAnalysis (line 827) | function getSegmentSkipRangesFromAnalysis( function getCachedAudioSegmentation (line 903) | function getCachedAudioSegmentation( function getShrinkWrappedSegment (line 926) | function getShrinkWrappedSegment( function syncRegionSkipMarkers (line 1011) | function syncRegionSkipMarkers(regionElement: HTMLElement, segment: Segm... function syncRegionWordMarkers (line 1056) | function syncRegionWordMarkers( function createIconSvg (line 1108) | function createIconSvg(path: string) { function createIconButton (line 1127) | function createIconButton({ function createRegionContent (line 1162) | function createRegionContent({ function detectSpeechSegments (line 1249) | function detectSpeechSegments( function float32ToInt16Sample (line 1256) | function float32ToInt16Sample(sample: number) { function toPlainArrayBuffer (line 1263) | function toPlainArrayBuffer(view: Uint8Array | Int8Array) { function audioBufferToWavBlob (line 1271) | function audioBufferToWavBlob(buffer: AudioBuffer) { function encodeSegmentAsMp3 (line 1331) | async function encodeSegmentAsMp3( function AudioCutterDialog (line 1415) | function AudioCutterDialog({ FILE: src/app/editor/story/[story]/audio-cutter-storage.ts type AudioCutterTranscriptItem (line 6) | type AudioCutterTranscriptItem = Pick< type AudioCutterPreparedSegment (line 19) | type AudioCutterPreparedSegment = { type StoredAudioCutterTranscript (line 27) | type StoredAudioCutterTranscript = { type StoredAudioCutterOutput (line 32) | type StoredAudioCutterOutput = { constant AUDIO_CUTTER_DB_NAME (line 41) | const AUDIO_CUTTER_DB_NAME = "audio-cutter"; constant AUDIO_CUTTER_OUTPUT_STORE (line 42) | const AUDIO_CUTTER_OUTPUT_STORE = "output-files"; function getTranscriptStorageKey (line 44) | function getTranscriptStorageKey(storyId: number) { function getOutputStorageKey (line 48) | function getOutputStorageKey(storyId: number) { function parseStoredAudioCutterOutput (line 52) | function parseStoredAudioCutterOutput(raw: string | null) { function getIndexedDb (line 62) | function getIndexedDb() { function openAudioCutterDb (line 70) | function openAudioCutterDb() { function requestToPromise (line 91) | function requestToPromise(request: IDBRequest) { function transactionToPromise (line 102) | function transactionToPromise(transaction: IDBTransaction) { function deleteStoredOutputBlobs (line 116) | async function deleteStoredOutputBlobs(blobKeys: string[]) { function storeAudioCutterTranscript (line 138) | function storeAudioCutterTranscript( function loadAudioCutterTranscript (line 155) | function loadAudioCutterTranscript(storyId: number) { function storeAudioCutterOutput (line 169) | async function storeAudioCutterOutput(storyId: number, files: File[]) { function consumeAudioCutterOutput (line 216) | async function consumeAudioCutterOutput(storyId: number) { FILE: src/app/editor/story/[story]/bulk-audio-editor.tsx constant PUBLIC_BLOB_BASE_URL (line 35) | const PUBLIC_BLOB_BASE_URL = constant DEFAULT_WAVEFORM_ZOOM (line 37) | const DEFAULT_WAVEFORM_ZOOM = 420; constant MIN_WAVEFORM_ZOOM (line 38) | const MIN_WAVEFORM_ZOOM = 40; constant MAX_WAVEFORM_ZOOM (line 39) | const MAX_WAVEFORM_ZOOM = 640; constant WAVEFORM_ZOOM_STEP (line 40) | const WAVEFORM_ZOOM_STEP = 40; constant ZIP_MIME_TYPES (line 41) | const ZIP_MIME_TYPES = new Set([ constant AUDIO_EXTENSIONS (line 46) | const AUDIO_EXTENSIONS = new Set([".mp3", ".wav", ".m4a", ".ogg", ".aac"]); type BulkAudioEditorDraft (line 48) | type BulkAudioEditorDraft = { type BulkAudioEditorItem (line 58) | type BulkAudioEditorItem = { type BulkAudioEditorUpdate (line 71) | type BulkAudioEditorUpdate = { type Region (line 79) | interface Region { type RegionsPlugin (line 86) | interface RegionsPlugin { type Part (line 101) | interface Part { function cumulativeSums (line 106) | function cumulativeSums(values: number[]): number[] { function stripAudioPathPrefix (line 116) | function stripAudioPathPrefix(filename: string) { function getPublicAudioUrl (line 124) | function getPublicAudioUrl(filename: string) { function isZipFile (line 132) | function isZipFile(file: File) { function getFileExtension (line 138) | function getFileExtension(filename: string) { function getAudioMimeType (line 143) | function getAudioMimeType(filename: string) { function isAudioFilename (line 153) | function isAudioFilename(filename: string) { function timingTextFromKeypoints (line 157) | function timingTextFromKeypoints( function createDraft (line 171) | function createDraft(item: BulkAudioEditorItem): BulkAudioEditorDraft { function createDraftMap (line 183) | function createDraftMap(items: BulkAudioEditorItem[]) { function revokeDraftUrls (line 187) | function revokeDraftUrls(drafts: Record) { function getLeadingNumber (line 193) | function getLeadingNumber(filename: string) { function isChanged (line 203) | function isChanged(item: BulkAudioEditorItem, draft: BulkAudioEditorDraf... function uploadAudioFile (line 214) | async function uploadAudioFile(file: File, storyId: number) { function expandUploadFiles (line 240) | async function expandUploadFiles(files: File[]) { function rowLabel (line 266) | function rowLabel(item: BulkAudioEditorItem) { function statusLabel (line 270) | function statusLabel(item: BulkAudioEditorItem, draft: BulkAudioEditorDr... function getParts (line 277) | function getParts(text: string) { function getAutoRegionStarts (line 292) | function getAutoRegionStarts(parts: Part[], duration: number) { function timingTextFromStarts (line 314) | function timingTextFromStarts(parts: Part[], starts: number[]) { function getWordPlaybackSegments (line 332) | function getWordPlaybackSegments( function BulkAudioRow (line 357) | function BulkAudioRow({ function BulkAudioEditor (line 852) | function BulkAudioEditor({ FILE: src/app/editor/story/[story]/editor_state.ts type AudioInsertLinesType (line 10) | type AudioInsertLinesType = ReturnType[2]; type EditorStateType (line 12) | type EditorStateType = { FILE: src/app/editor/story/[story]/header.tsx type StoryNavigationTarget (line 7) | type StoryNavigationTarget = { type Window (line 13) | interface Window { type HeaderProps (line 19) | type HeaderProps = { function StoryEditorHeader (line 37) | function StoryEditorHeader({ function StoryEditorHeaderLoading (line 165) | function StoryEditorHeaderLoading() { function SaveStatus (line 220) | function SaveStatus({ lastSavedAt }: { lastSavedAt: number }) { function StoryNavButton (line 231) | function StoryNavButton({ function ChevronIcon (line 277) | function ChevronIcon({ direction }: { direction: "left" | "right" }) { FILE: src/app/editor/story/[story]/layout.tsx function Layout (line 4) | function Layout({ children }: { children: React.ReactNode }) { FILE: src/app/editor/story/[story]/page.tsx function getCanonicalStoryEditorPath (line 7) | function getCanonicalStoryEditorPath(courseShort: string, storyId: numbe... function generateMetadata (line 11) | async function generateMetadata({ function Page (line 34) | async function Page({ FILE: src/app/editor/story/[story]/page_client.tsx function StoryEditorPageClient (line 17) | function StoryEditorPageClient({ FILE: src/app/editor/story/[story]/sound-recorder.tsx type Region (line 13) | interface Region { type RegionsPlugin (line 19) | interface RegionsPlugin { type SoundRecorderProps (line 29) | interface SoundRecorderProps { type Part (line 42) | interface Part { function cumulativeSums (line 47) | function cumulativeSums(values: number[]): number[] { function uploadAudio (line 57) | async function uploadAudio( function SoundRecorder (line 81) | function SoundRecorder({ FILE: src/app/editor/story/[story]/types.ts type StoryData (line 1) | type StoryData = { type StoryEditorPageData (line 16) | type StoryEditorPageData = { type Avatar (line 21) | type Avatar = { FILE: src/app/editor/story/[story]/v2/editor_v2.tsx type StoryNavigation (line 39) | type StoryNavigation = { type LanguageData (line 50) | type LanguageData = { function getMax (line 64) | function getMax(list: T[], callback: (obj: T) => number) { function normalizeDocText (line 73) | function normalizeDocText(text: string): string { function scrollEditorLineIntoView (line 77) | function scrollEditorLineIntoView(view: EditorView, lineNumber: number) { function getElementAudio (line 107) | function getElementAudio( function getBulkAudioEditorItems (line 115) | function getBulkAudioEditorItems( function EditorV2 (line 164) | function EditorV2({ FILE: src/app/editor/story/[story]/v2/use_story_editor_model.ts type LanguageLike (line 12) | type LanguageLike = { type ImageLike (line 18) | type ImageLike = { type UseStoryEditorModelArgs (line 24) | type UseStoryEditorModelArgs = { function normalizeDocText (line 34) | function normalizeDocText(text: string): string { function toConvexValue (line 38) | function toConvexValue(value: unknown): unknown { type EditorModel (line 51) | type EditorModel = { function useStoryEditorModel (line 77) | function useStoryEditorModel({ FILE: src/app/layout.tsx function RootLayout (line 15) | function RootLayout({ FILE: src/app/not-found.tsx function NotFound (line 4) | function NotFound() { FILE: src/components/CheckButton/CheckButton.tsx function CheckButton (line 4) | function CheckButton({ type }: { type: string }) { FILE: src/components/ContributorList.tsx type ContributorProfile (line 6) | type ContributorProfile = { type ContributorInput (line 13) | type ContributorInput = function normalizeContributor (line 23) | function normalizeContributor( function ContributorAvatar (line 52) | function ContributorAvatar({ function ContributorList (line 89) | function ContributorList({ FILE: src/components/Docs/CustomMDXServer/CustomMDXServer.tsx function CustomMDXServer (line 7) | async function CustomMDXServer({ source }: { source: string }) { FILE: src/components/Docs/CustomMDXServer/process_mdx.ts type TreeNode (line 14) | interface TreeNode { function process_mdx (line 24) | async function process_mdx( FILE: src/components/Docs/MdxTree/MdxTree.tsx function startsLowerCase (line 16) | function startsLowerCase(tagName: string) { function node_to_string (line 22) | function node_to_string(children: any) { function save_tag (line 30) | function save_tag(tag: string) { function Video (line 39) | function Video({ function getTreeLeaveID (line 132) | function getTreeLeaveID(i: any, index: number) { function toCamelCase (line 141) | function toCamelCase(cssProperty: string) { function MdxTreeRoot (line 151) | function MdxTreeRoot({ function MdxTree (line 174) | function MdxTree({ FILE: src/components/Docs/docsClasses.ts function docsPageLinkClass (line 30) | function docsPageLinkClass(active: boolean) { function docsSearchResultClass (line 84) | function docsSearchResultClass(type: "main" | "sub") { FILE: src/components/DocsBreadCrumbNav/DocsBreadCrumbNav.tsx function DocsBreadCrumbNav (line 11) | function DocsBreadCrumbNav({ FILE: src/components/DocsHeader/DocsHeader.tsx function DocsHeader (line 16) | function DocsHeader() { FILE: src/components/DocsNavigation/DocsNavigation.tsx function DocsNavigation (line 22) | function DocsNavigation({ function NavigationContent (line 63) | function NavigationContent({ function PageLink (line 99) | function PageLink({ FILE: src/components/DocsNavigationBackdrop/DocsNavigationBackdrop.tsx function DocsNavigationBackdrop (line 9) | function DocsNavigationBackdrop({ children }: { children: React.ReactNod... FILE: src/components/DocsSearchModal/DocsSearchModal.tsx function getPageData (line 18) | async function getPageData(path: string) { type Page (line 83) | type Page = function loadAll (line 99) | async function loadAll() { function DocsSearchModal (line 118) | function DocsSearchModal({ FILE: src/components/EditorSSMLDisplay/EditorSSMLDisplay.tsx type EditorSSMLDisplayProps (line 15) | interface EditorSSMLDisplayProps { function EditorSSMLDisplay (line 24) | function EditorSSMLDisplay({ FILE: src/components/FadeGlideIn/FadeGlideIn.tsx function FadeGlideIn (line 5) | function FadeGlideIn({ FILE: src/components/LocalisationProvider/LocalisationProvider.tsx function LocalisationProvider (line 6) | async function LocalisationProvider({ FILE: src/components/LocalisationProvider/LocalisationProviderContext.tsx function useLocalisation (line 7) | function useLocalisation() { function LocalisationProviderInner (line 13) | function LocalisationProviderInner({ FILE: src/components/NavigationModeProvider/NavigationModeProvider.tsx function useNavigationMode (line 9) | function useNavigationMode() { function NavigationModeProvider (line 13) | function NavigationModeProvider({ FILE: src/components/PlayAudio/PlayAudio.tsx function PlayAudio (line 4) | function PlayAudio({ FILE: src/components/ProgressBar/ProgressBar.tsx function ProgressBar (line 3) | function ProgressBar({ FILE: src/components/StoryAutoPlay/StoryAutoPlay.tsx type StoryAutoPlayProps (line 15) | interface StoryAutoPlayProps { constant BLOB_PUBLIC_BASE (line 26) | const BLOB_PUBLIC_BASE = constant FETCH_RETRIES (line 28) | const FETCH_RETRIES = 2; constant LARGE_MERGE_SEGMENT_THRESHOLD (line 29) | const LARGE_MERGE_SEGMENT_THRESHOLD = 60; type AutoPlayableElement (line 48) | type AutoPlayableElement = StoryElementHeader | StoryElementLine; type TimelineSegment (line 50) | type TimelineSegment = { type TimelineMeta (line 57) | type TimelineMeta = { function getParts (line 64) | function getParts(story: StoryType) { function toAbsoluteAudioUrl (line 78) | function toAbsoluteAudioUrl(url: string): string | null { function getElementAudioUrl (line 84) | function getElementAudioUrl(element: AutoPlayableElement): string | null { function getElementKeypoints (line 93) | function getElementKeypoints( function clearHints (line 103) | function clearHints(element: StoryElement): StoryElement { function findSegmentIndexByTime (line 137) | function findSegmentIndexByTime(meta: TimelineMeta[], time: number): num... function formatTime (line 145) | function formatTime(seconds: number): string { function fetchArrayBufferWithRetry (line 152) | async function fetchArrayBufferWithRetry(url: string): Promise() { function useScrollLinking (line 123) | function useScrollLinking( FILE: src/components/editor/story/syntax_parser_new.ts type IpaReplacement (line 29) | type IpaReplacement = InlineTtsReplacement; function generateHintMap (line 31) | function generateHintMap( function hintsShift (line 156) | function hintsShift(content: ContentWithHints, pos: number): void { function getButtons (line 165) | function getButtons(content: ContentWithHints): [string[], number[]] { function regexIndexOf (line 194) | function regexIndexOf( function removeDoubleBrackets (line 202) | function removeDoubleBrackets( function getHideRanges (line 217) | function getHideRanges(content: ContentWithHints): HideRange[] { function shuffleArray (line 243) | function shuffleArray(selectablePhrases: string[]): [number[], string[]] { function split_lines (line 262) | function split_lines(text: string) { function processBlockData (line 283) | function processBlockData(line_iter: LineIterator, story: StoryWithMeta) { function splitTextTokens (line 353) | function splitTextTokens(text: string, keep_tilde = true) { function splitTextTokens2 (line 365) | function splitTextTokens2(text: string, keep_tilde = true) { function getInputStringText (line 374) | function getInputStringText(text: string) { function speaker_text_trans (line 381) | function speaker_text_trans( function line_to_audio (line 501) | function line_to_audio( function get_avatar (line 546) | function get_avatar( type Speaker (line 561) | type Speaker = { function getText (line 572) | function getText( function pushStoryErrorData (line 616) | function pushStoryErrorData( function toErrorMessage (line 648) | function toErrorMessage(error: unknown) { function safeSpeakerTextTrans (line 653) | function safeSpeakerTextTrans( function getAnswers (line 682) | function getAnswers( function pointToPhraseButtons (line 722) | function pointToPhraseButtons(line: string) { function processBlockHeader (line 773) | function processBlockHeader( function processBlockLine (line 809) | function processBlockLine( function processBlockMultipleChoice (line 846) | function processBlockMultipleChoice( function processBlockSelectPhrase (line 883) | function processBlockSelectPhrase( function processBlockContinuation (line 954) | function processBlockContinuation( function processBlockArrange (line 1030) | function processBlockArrange( function processBlockPointToPhrase (line 1103) | function processBlockPointToPhrase( function processBlockMatch (line 1168) | function processBlockMatch( function line_iterator (line 1241) | function line_iterator(lines: LineTuple[]) { type LineIterator (line 1255) | type LineIterator = ReturnType; type StoryWithMeta (line 1257) | type StoryWithMeta = StoryType & { type StoryType (line 1260) | type StoryType = { type Meta (line 1265) | type Meta = { type AvatarOverwrites (line 1291) | type AvatarOverwrites = { type StoryLanguages (line 1298) | type StoryLanguages = { type TranscribeData (line 1303) | type TranscribeData = string; type LineTuple (line 1305) | type LineTuple = [number, string]; function isBlockHeaderLine (line 1307) | function isBlockHeaderLine(line: string | undefined) { function consumeUnknownBlock (line 1311) | function consumeUnknownBlock( function skipToNextBlock (line 1329) | function skipToNextBlock(line_iter: LineIterator) { function processStoryFile (line 1343) | function processStoryFile( FILE: src/components/editor/story/syntax_parser_types.ts type Audio (line 1) | type Audio = { type HintMapItem (line 16) | interface HintMapItem { type HintMapResult (line 22) | interface HintMapResult { type ContentWithHints (line 32) | interface ContentWithHints { type HideRange (line 38) | interface HideRange { type LineElementCharacter (line 43) | type LineElementCharacter = { type LineElementProse (line 50) | type LineElementProse = { type LineElementTitle (line 54) | type LineElementTitle = { type LineElement (line 58) | type LineElement = type StoryElementHeader (line 63) | type StoryElementHeader = { type StoryElementLine (line 79) | type StoryElementLine = { type StoryElementMultipleChoice (line 94) | type StoryElementMultipleChoice = { type StoryElementChallengePrompt (line 112) | type StoryElementChallengePrompt = { type StoryElementSelectPhrase (line 128) | type StoryElementSelectPhrase = { type StoryElementArrange (line 140) | type StoryElementArrange = { type StoryElementPointToPhrase (line 153) | type StoryElementPointToPhrase = { type StoryElementMatch (line 172) | type StoryElementMatch = { type StoryElementError (line 190) | type StoryElementError = { type StoryElement (line 209) | type StoryElement = FILE: src/components/icons.tsx function IconDiscord (line 1) | function IconDiscord() { function IconGithub (line 32) | function IconGithub() { function IconOpenCollective (line 50) | function IconOpenCollective() { function IconInstagram (line 73) | function IconInstagram() { function IconTwitter (line 91) | function IconTwitter() { function IconFacebook (line 109) | function IconFacebook() { function IconGoogle (line 129) | function IconGoogle() { function IconPlayStore (line 159) | function IconPlayStore() { function GetIcon (line 177) | function GetIcon({ name }: { name: string }) { FILE: src/components/layout/legal.tsx function Legal (line 4) | function Legal({ language_name }: { language_name?: string }) { FILE: src/components/login/LoggedInButtonWrappedClient.tsx function LoggedInButtonWrappedClient (line 7) | function LoggedInButtonWrappedClient(props: { FILE: src/components/login/loggedinbutton.tsx function themeToLightOrDark (line 19) | function themeToLightOrDark( function get_current_theme (line 27) | function get_current_theme(): "light" | "dark" | undefined { function useDarkLight (line 53) | function useDarkLight() { function LogInButton (line 76) | function LogInButton() { function LoggedInButton (line 85) | function LoggedInButton({ FILE: src/components/providers/ConvexClientProvider.tsx function ConvexClientProvider (line 8) | function ConvexClientProvider({ FILE: src/components/providers/PostHogUserIdentifier.tsx constant PENDING_SIGNIN_STORAGE_KEY (line 8) | const PENDING_SIGNIN_STORAGE_KEY = "posthog_pending_signin"; type SessionUser (line 10) | type SessionUser = { type PendingSignInPayload (line 18) | type PendingSignInPayload = { function PostHogUserIdentifier (line 23) | function PostHogUserIdentifier() { FILE: src/components/ui/badge.tsx function Badge (line 4) | function Badge({ FILE: src/components/ui/button.tsx type ButtonVariant (line 4) | type ButtonVariant = type ButtonSize (line 14) | type ButtonSize = "default" | "sm" | "lg"; type ButtonProps (line 16) | type ButtonProps = { function resolveVariant (line 23) | function resolveVariant({ function buttonRootClassName (line 37) | function buttonRootClassName({ function buttonInnerClassName (line 73) | function buttonInnerClassName({ FILE: src/components/ui/dialog.tsx function Dialog (line 9) | function Dialog({ function DialogTrigger (line 15) | function DialogTrigger({ function DialogPortal (line 21) | function DialogPortal({ function DialogClose (line 27) | function DialogClose({ function DialogOverlay (line 33) | function DialogOverlay({ function DialogContent (line 57) | function DialogContent({ function DialogHeader (line 107) | function DialogHeader({ className, ...props }: React.ComponentProps<"div... function DialogFooter (line 117) | function DialogFooter({ function DialogTitle (line 142) | function DialogTitle({ function DialogDescription (line 155) | function DialogDescription({ FILE: src/components/ui/flag.tsx function Flag (line 4) | function Flag(props: { FILE: src/components/ui/input.tsx type InputProps (line 4) | type InputProps = { FILE: src/components/ui/kbd.tsx function Kbd (line 3) | function Kbd({ className, ...props }: React.ComponentProps<"kbd">) { function KbdGroup (line 18) | function KbdGroup({ className, ...props }: React.ComponentProps<"div">) { FILE: src/components/ui/language-flag.tsx type FlagProps (line 9) | type FlagProps = ComponentProps; type LanguageFlagEntry (line 11) | type LanguageFlagEntry = { function useLanguageFlag (line 18) | function useLanguageFlag(languageId?: Id<"languages"> | string) { function LanguageFlag (line 29) | function LanguageFlag({ FILE: src/components/ui/shadcn/dropdown-menu.tsx function DropdownMenu (line 8) | function DropdownMenu({ function DropdownMenuTrigger (line 14) | function DropdownMenuTrigger({ function DropdownMenuPortal (line 25) | function DropdownMenuPortal({ function DropdownMenuContent (line 33) | function DropdownMenuContent({ function DropdownMenuItem (line 53) | function DropdownMenuItem({ function DropdownMenuSeparator (line 73) | function DropdownMenuSeparator({ FILE: src/components/ui/sheet.tsx function Sheet (line 9) | function Sheet(props: React.ComponentProps) { function SheetTrigger (line 13) | function SheetTrigger( function SheetClose (line 19) | function SheetClose(props: React.ComponentProps; function get_localisation_func (line 6) | function get_localisation_func(data: Record) { function insetWithNewlines (line 23) | function insetWithNewlines(text: string) { function replaceLinks (line 39) | function replaceLinks(text: string, links: string[]) { function replaceTags (line 55) | function replaceTags(text: string, tags: Record) { FILE: src/lib/hooks.ts function useInput (line 3) | function useInput( FILE: src/lib/is-typing-target.ts function isTypingTarget (line 1) | function isTypingTarget( FILE: src/lib/lamejs-compat.ts type LamejsEncoder (line 1) | type LamejsEncoder = { type LamejsModule (line 6) | type LamejsModule = { type CjsModuleNamespace (line 14) | type CjsModuleNamespace = { type LamejsDependencyLoader (line 18) | type LamejsDependencyLoader = readonly [ constant LAMEJS_GLOBAL_DEPENDENCIES (line 23) | const LAMEJS_GLOBAL_DEPENDENCIES: readonly LamejsDependencyLoader[] = [ function unwrapCjsModule (line 40) | function unwrapCjsModule(module: unknown) { function exposeLamejsGlobals (line 44) | async function exposeLamejsGlobals() { function getLamejsModule (line 50) | async function getLamejsModule() { FILE: src/lib/posthog-server.ts type PostHogLike (line 9) | type PostHogLike = Pick; function getPostHogClient (line 11) | function getPostHogClient(): PostHogLike { function shutdownPostHog (line 27) | async function shutdownPostHog() { FILE: src/lib/posthog-user.ts type PostHogUser (line 6) | type PostHogUser = { function identifyPostHogUser (line 14) | function identifyPostHogUser(user: PostHogUser | null | undefined) { function getCurrentPostHogUser (line 35) | async function getCurrentPostHogUser() { function resetPostHogUser (line 45) | function resetPostHogUser() { FILE: src/lib/shuffle.ts function setSeed (line 7) | function setSeed(seed: number) { function randomSeeded (line 11) | function randomSeeded() { function shuffle (line 16) | function shuffle(a: T[]): T[] { FILE: src/lib/sound-effects.ts constant SOUND_EFFECT_URLS (line 1) | const SOUND_EFFECT_URLS = { type SoundEffectName (line 7) | type SoundEffectName = keyof typeof SOUND_EFFECT_URLS; function playSoundEffect (line 11) | function playSoundEffect(name: SoundEffectName) { FILE: src/lib/story-preferences.ts constant HIDE_STORY_QUESTIONS_COOKIE (line 1) | const HIDE_STORY_QUESTIONS_COOKIE = "hide_story_questions"; function isStoryQuestionsDisabled (line 3) | function isStoryQuestionsDisabled( FILE: src/lib/story-search.ts type StorySearchable (line 1) | type StorySearchable = { type StorySearchState (line 9) | type StorySearchState = "draft" | "feedback" | "finished" | "published"; type ParsedStorySearch (line 11) | type ParsedStorySearch = { type StorySearchOptions (line 18) | type StorySearchOptions = { function parseStorySearch (line 22) | function parseStorySearch( function matchesStorySearch (line 115) | function matchesStorySearch( function formatStorySetLabel (line 160) | function formatStorySetLabel( function splitStatusTokens (line 166) | function splitStatusTokens(searchQuery: string): { function normalizeStorySearchStateToken (line 193) | function normalizeStorySearchStateToken( function matchesStatusPrefix (line 261) | function matchesStatusPrefix(rawStatus: string, acceptedValues: string[]) { function getStorySearchState (line 265) | function getStorySearchState( FILE: src/lib/userInterface.ts type AuthUser (line 6) | type AuthUser = { type AppUser (line 17) | type AppUser = Omit & { function getUser (line 41) | async function getUser( function requireAdmin (line 71) | async function requireAdmin() { type RoleLike (line 77) | type RoleLike = function isAdmin (line 86) | function isAdmin(user: RoleLike) { function isContributor (line 93) | function isContributor(user: RoleLike) { FILE: src/lib/utils.ts function cn (line 4) | function cn(...inputs: ClassValue[]) { FILE: src/types/lamejs.d.ts class Mp3Encoder (line 2) | class Mp3Encoder {