├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── something-else.md └── workflows │ └── ts.yml ├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── compiler.xml ├── dictionaries │ └── andym.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jsLibraryMappings.xml ├── jsLinters │ └── eslint.xml ├── markdown.xml ├── metabook.iml ├── misc.xml ├── modules.xml ├── prettier.xml ├── scopes │ └── source_files.xml ├── vcs.xml └── watcherTasks.xml ├── .node-version ├── .vscode ├── settings.json └── tasks.json ├── LICENSE ├── LICENSE-AGPL-3.0-or-later ├── LICENSE-Apache-2.0 ├── LICENSE-BUSL-1.1 ├── NOTICE ├── Readme.md ├── bun.lockb ├── design ├── reveal answer - scale.origami ├── reveal answer and advance question - fade.origami ├── starburst-icon-iOS.svg ├── starburst-icon-iOS_1024x1024.png ├── starburst-icon-iOS_20x20.png ├── starburst-icon-iOS_20x20@2x.png ├── starburst-icon-iOS_20x20@3x.png ├── starburst-icon-iOS_29x29.png ├── starburst-icon-iOS_29x29@2x.png ├── starburst-icon-iOS_29x29@3x.png ├── starburst-icon-iOS_40x40.png ├── starburst-icon-iOS_40x40@2x.png ├── starburst-icon-iOS_40x40@3x.png ├── starburst-icon-iOS_60x60@2x.png ├── starburst-icon-iOS_60x60@3x.png ├── starburst-icon-iOS_76x76.png ├── starburst-icon-iOS_76x76@2x.png ├── starburst-icon-iOS_83-5x83-5@2x.png ├── starburst-icon-macOS_1024x1024.png ├── starburst-icon-macOS_128x128.png ├── starburst-icon-macOS_128x128@2x.png ├── starburst-icon-macOS_16x16.png ├── starburst-icon-macOS_16x16@2x.png ├── starburst-icon-macOS_256x256.png ├── starburst-icon-macOS_256x256@2x.png ├── starburst-icon-macOS_32x32.png ├── starburst-icon-macOS_32x32@2x.png ├── starburst-icon-macOS_512x512.png ├── starburst-icon-macOS_512x512@2x.png ├── starburst-icon.fig ├── starburst-icon.md └── starburst-icon.svg ├── package.json └── packages ├── .eslintignore ├── .eslintrc.js ├── .prettierrc.js ├── anki-import ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── __fixtures__ │ │ ├── testAnkiData.ts │ │ ├── testCollection.colpkg │ │ └── withTestAnkiCollection.ts │ ├── ankiPkg │ │ ├── ankiAttachmentReference.ts │ │ ├── ankiCollection.test.ts │ │ ├── ankiCollection.ts │ │ ├── ankiDBTypes.ts │ │ ├── index.ts │ │ ├── parseAnkiField.test.ts │ │ ├── parseAnkiField.ts │ │ ├── splitAnkiDBNoteFields.test.ts │ │ └── splitAnkiDBNoteFields.ts │ ├── convertAnkiID.ts │ ├── importPlan.test.ts │ ├── importPlan.ts │ ├── index.ts │ ├── modelMapping.test.ts │ ├── modelMapping.ts │ ├── noteMapping.test.ts │ └── noteMapping.ts └── tsconfig.json ├── api-client ├── .gitignore ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── apiConfig.ts │ ├── index.ts │ ├── orbitAPIClient.ts │ ├── requestManager.test.ts │ ├── requestManager.ts │ └── util │ │ ├── fetch.native.ts │ │ ├── fetch.ts │ │ └── mockAPIValiation.ts └── tsconfig.json ├── api ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── genericHTTPAPI.ts │ ├── index.ts │ ├── orbitAPI.ts │ ├── orbitAPISchema.json │ ├── util │ │ └── requiredSpec.ts │ └── validation │ │ ├── ajvAPIValidator.test.ts │ │ ├── ajvAPIValidator.ts │ │ ├── apiValidator.ts │ │ └── orbitAPIValidator.ts └── tsconfig.json ├── app ├── .firebaserc ├── .gitignore ├── LICENSE ├── LICENSE-AGPL-3.0-or-later ├── LICENSE-BUSL-1.1 ├── Readme.md ├── app-assets │ └── starburst-icon.png ├── app.json ├── assets ├── babel.config.js ├── expoPlugin │ ├── expoPlugin.js │ ├── ios │ │ ├── AppDelegate+Intents.m │ │ ├── AppDelegate+KeyHandling.m │ │ ├── IngestEventEmitter.h │ │ ├── IngestEventEmitter.m │ │ ├── IngestEventHandler.h │ │ ├── IngestEventHandler.m │ │ ├── Intents.intentdefinition │ │ ├── ORSQLImageURLLoader.h │ │ ├── ORSQLImageURLLoader.m │ │ ├── ORWidgetReloadBridge.m │ │ └── ORWidgetReloadBridge.swift │ ├── util.js │ ├── withCatalystSupport.js │ ├── withIngestIntent.js │ ├── withReactNativeKeyEventSupport.js │ ├── withSQLImageURLLoader.js │ └── withWidgetPluginFixes.js ├── firebase.json ├── metro.config.js ├── package.json ├── public │ ├── browserCompatibility.js │ └── index.html ├── scripts │ ├── buildWidget.ts │ ├── deploy_web.sh │ └── generate_browser_compatibility_regex.sh ├── serviceConfig.js ├── src │ ├── ReviewSessionContainer.tsx │ ├── app │ │ ├── (auth) │ │ │ ├── _layout.tsx │ │ │ ├── embed.tsx │ │ │ ├── login.tsx │ │ │ ├── review.tsx │ │ │ └── settings.tsx │ │ ├── (index) │ │ │ ├── _layout.tsx │ │ │ ├── _layout.web.tsx │ │ │ ├── index.tsx │ │ │ └── index.web.tsx │ │ ├── _layout.tsx │ │ ├── download.tsx │ │ ├── learnMore.tsx │ │ └── terms.tsx │ ├── authentication │ │ ├── authContext.ts │ │ ├── authenticationClient.ts │ │ ├── firebaseAuthenticationClient.ts │ │ ├── index.ts │ │ ├── isBrowserStorageAvailable.native.ts │ │ ├── isBrowserStorageAvailable.ts │ │ └── loginTokenBroadcastChannel.ts │ ├── embedded │ │ ├── EmbeddedBanner.tsx │ │ ├── OnboardingModal.web.tsx │ │ ├── TestModeBanner.tsx │ │ ├── embeddedNetworkQueue.ts │ │ ├── ipc │ │ │ ├── sendUpdatedReviewItemToHost.ts │ │ │ └── useEmbeddedHostState.ts │ │ ├── markingActions.ts │ │ ├── useEmbeddedAuthenticationState.ts │ │ ├── useRemoteTaskStates.ts │ │ └── util │ │ │ ├── findItemsToRetry.test.ts │ │ │ ├── findItemsToRetry.ts │ │ │ ├── getEmbeddedColorPalette.ts │ │ │ └── getEmbeddedScreenConfigurationFromURL.ts │ ├── errorReporting.ts │ ├── homeRedirect │ │ ├── homeRedirect.tsx │ │ └── homeRedirect.web.tsx │ ├── index.js │ ├── infoPage │ │ ├── InfoPage.tsx │ │ ├── InfoPage.web.tsx │ │ └── InfoPageShared.tsx │ ├── model2 │ │ ├── databaseManager.ts │ │ ├── orbitStoreFactory.ts │ │ └── orbitStoreFactory.web.ts │ ├── reviewSession │ │ ├── LoadingScreen.tsx │ │ └── ReviewSession.tsx │ ├── reviewSessionManager.ts │ ├── signIn │ │ └── SignInForm.tsx │ ├── util │ │ ├── firebase.ts │ │ ├── firebaseAuth.ts │ │ ├── firebaseAuth.web.ts │ │ ├── intents │ │ │ ├── IntentHandler.ts │ │ │ ├── IntentHandler.web.ts │ │ │ └── handleIngestEvent.ts │ │ ├── shims.ts │ │ ├── shims.web.ts │ │ ├── task.ts │ │ ├── useAPIClient.tsx │ │ ├── useAsyncResult.ts │ │ ├── useByrefCallback.ts │ │ ├── usePageViewTracking.ts │ │ └── usePageViewTracking.web.ts │ └── widget.ts ├── targets │ └── widgets │ │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── App-Icon-20x20@1x.png │ │ │ ├── App-Icon-20x20@2x.png │ │ │ ├── App-Icon-20x20@3x.png │ │ │ ├── App-Icon-29x29@1x.png │ │ │ ├── App-Icon-29x29@2x.png │ │ │ ├── App-Icon-29x29@3x.png │ │ │ ├── App-Icon-40x40@1x.png │ │ │ ├── App-Icon-40x40@2x.png │ │ │ ├── App-Icon-40x40@3x.png │ │ │ ├── App-Icon-60x60@2x.png │ │ │ ├── App-Icon-60x60@3x.png │ │ │ ├── App-Icon-76x76@1x.png │ │ │ ├── App-Icon-76x76@2x.png │ │ │ ├── App-Icon-83.5x83.5@2x.png │ │ │ ├── Contents.json │ │ │ └── ItunesArtwork@2x.png │ │ ├── Contents.json │ │ ├── WidgetBackground.colorset │ │ │ └── Contents.json │ │ ├── check-center.imageset │ │ │ ├── Contents.json │ │ │ └── check-center.svg │ │ ├── cross-center.imageset │ │ │ ├── Contents.json │ │ │ └── cross-center.svg │ │ ├── reveal-accent-center.imageset │ │ │ ├── Contents.json │ │ │ └── reveal-accent-center.svg │ │ └── reveal-center.imageset │ │ │ ├── Contents.json │ │ │ └── reveal-center.svg │ │ ├── Bridge.swift │ │ ├── Colors.swift │ │ ├── Fonts.swift │ │ ├── Info.plist │ │ ├── OrbitTask.swift │ │ ├── OrbitWidgetBundle.swift │ │ ├── PrivacyInfo.xcprivacy │ │ ├── Widget.swift │ │ ├── expo-target.config.json │ │ └── generated.entitlements └── tsconfig.json ├── babel.config.js ├── backend ├── .firebaserc ├── .gitignore ├── LICENSE ├── LICENSE-AGPL-3.0-or-later ├── LICENSE-BUSL-1.1 ├── Readme.md ├── babel.config.cjs ├── bigQuerySchemas │ ├── events.json │ ├── pageViews.json │ ├── sessionNotifications.json │ └── userEvents.json ├── emulator-data │ ├── auth_export │ │ ├── accounts.json │ │ └── config.json │ ├── firebase-export-metadata.json │ └── firestore_export │ │ ├── all_namespaces │ │ └── all_kinds │ │ │ ├── all_namespaces_all_kinds.export_metadata │ │ │ └── output-0 │ │ └── firestore_export.overall_export_metadata ├── firebase-storage-cors.json ├── firebase.json ├── firestore.indexes.json ├── firestore.rules ├── jest.config.cjs ├── package.json ├── scripts │ ├── deployShared.js │ ├── postdeploy.js │ └── predeploy.js ├── src │ ├── @types │ │ └── isbot-fast │ │ │ └── index.d.ts │ ├── __tests__ │ │ ├── emulators.ts │ │ ├── firebaseTesting.ts │ │ └── integration │ │ │ ├── attachments.test.ts │ │ │ ├── auth.test.ts │ │ │ ├── events.test.ts │ │ │ ├── updateNotificationSettings.test.ts │ │ │ └── utils │ │ │ └── fetchRoute.ts │ ├── api.ts │ ├── api │ │ ├── attachments.ts │ │ ├── events.ts │ │ ├── internal │ │ │ ├── auth │ │ │ │ ├── consumeAccessCode.ts │ │ │ │ ├── createLoginToken.ts │ │ │ │ ├── personalAccessTokens.ts │ │ │ │ ├── refreshSessionCookie.ts │ │ │ │ └── sessionCookie.ts │ │ │ └── recordPageView.ts │ │ ├── internalSpec.ts │ │ ├── tasks.ts │ │ └── util │ │ │ ├── authenticateRequest.ts │ │ │ ├── corsHandler.ts │ │ │ ├── putAndLogEvents.ts │ │ │ └── typedRouter.ts │ ├── attachments.test.ts │ ├── attachments.ts │ ├── db │ │ ├── firebaseAccountData.ts │ │ ├── firebaseAuth.ts │ │ ├── firestore.ts │ │ ├── firestoreDatabaseBackend.test.ts │ │ ├── firestoreDatabaseBackend.ts │ │ ├── index.ts │ │ ├── orderedID.test.ts │ │ ├── orderedID.ts │ │ ├── userMetadata.ts │ │ └── withFirebaseFields.ts │ ├── email │ │ ├── dummy.ts │ │ ├── index.ts │ │ ├── mailjet.ts │ │ └── types.ts │ ├── fileStorageService │ │ ├── fileStorageService.ts │ │ ├── googleCloudFileStorageService.ts │ │ ├── index.ts │ │ ├── localFileStorageService.test.ts │ │ └── localFileStorageService.ts │ ├── firebaseApp.ts │ ├── firebaseFunctions │ │ ├── api.ts │ │ ├── notifier │ │ │ ├── index.ts │ │ │ ├── notificationScheduler.ts │ │ │ └── processUserNotificationSubscriber.ts │ │ ├── onUserCreate.ts │ │ └── updateNotificationSettings.ts │ ├── index.ts │ ├── logging │ │ ├── bigQuery.ts │ │ ├── dummy.ts │ │ ├── index.ts │ │ └── interface.ts │ ├── notifications │ │ ├── __fixtures__ │ │ │ └── generateDueTasks.ts │ │ ├── index.ts │ │ ├── processUserNotification.test.ts │ │ ├── processUserNotification.ts │ │ ├── reviewSessionEmails.ts │ │ ├── reviewSessionScheduling.test.ts │ │ ├── reviewSessionScheduling.ts │ │ ├── shouldEvaluateUserForNotification.test.ts │ │ └── shouldEvaluateUserForNotification.ts │ ├── serviceConfig.ts │ └── util │ │ ├── isRunningInEmulator.ts │ │ └── isRunningInTest.ts ├── storage.rules └── tsconfig.json ├── core ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── __tests__ │ │ └── testTasks.ts │ ├── colorPaletteName.ts │ ├── entities │ │ ├── attachmentReference.ts │ │ ├── task.ts │ │ └── util │ │ │ └── parseClozeMarkup.ts │ ├── entity.ts │ ├── event.ts │ ├── eventReducer.ts │ ├── eventReducers │ │ ├── attachmentReducers.ts │ │ ├── taskReducers.test.ts │ │ └── taskReducers.ts │ ├── generateUniqueID.test.ts │ ├── generateUniqueID.ts │ ├── index.ts │ ├── reviewQueue.test.ts │ ├── reviewQueue.ts │ ├── scheduler.ts │ ├── schedulers │ │ ├── spacedRepetitionScheduler.test.ts │ │ └── spacedRepetitionScheduler.ts │ └── util │ │ ├── crypto.native.ts │ │ ├── crypto.ts │ │ └── crypto.web.ts └── tsconfig.json ├── docs ├── .firebaserc ├── .gitignore ├── 404.html ├── LICENSE ├── Readme.md ├── firebase.json ├── index.html ├── package.json ├── test.html └── toffoli.png ├── embedded-support ├── LICENSE ├── Readme.md ├── package.json ├── src │ ├── embeddedScreenInterface.ts │ ├── index.ts │ └── ipc.ts └── tsconfig.json ├── ingester ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── bin │ │ └── run.ts │ ├── index.ts │ ├── ingest.test.ts │ ├── ingest.ts │ ├── ingestible.json │ ├── ingestible.ts │ ├── validateIngestible.test.ts │ └── validateIngestible.ts └── tsconfig.json ├── interpreter ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── bin │ │ ├── migrateNoteSync.ts │ │ └── run.ts │ ├── hasher │ │ ├── CryptoBase64Hasher.test.ts │ │ ├── CryptoBase64Hasher.ts │ │ └── hasher.ts │ ├── interpreter.ts │ └── interpreters │ │ ├── index.ts │ │ └── markdown │ │ ├── MarkdownInterpreter.test.ts │ │ ├── MarkdownInterpreter.ts │ │ ├── __snapshots__ │ │ └── MarkdownInterpreter.test.ts.snap │ │ ├── markdown.test.ts │ │ ├── markdown.ts │ │ ├── plugins │ │ ├── bearIDPlugin.test.ts │ │ ├── bearIDPlugin.ts │ │ ├── clozePromptPlugin.test.ts │ │ ├── clozePromptPlugin.ts │ │ ├── qaPromptPlugin.test.ts │ │ └── qaPromptPlugin.ts │ │ └── utils │ │ ├── getNoteTitle.test.ts │ │ ├── getNoteTitle.ts │ │ ├── getStableBearID.test.ts │ │ └── getStableBearID.ts └── tsconfig.json ├── jest.config.js ├── sample-data ├── LICENSE ├── Readme.md ├── package.json ├── src │ ├── index.ts │ ├── testClozeSpec.ts │ ├── testQASpec.ts │ └── testTasks.ts └── tsconfig.json ├── store-fs ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── attachmentStoreFS.ts │ ├── database.test.ts │ ├── index.ts │ ├── orbitStoreFS.test.ts │ ├── orbitStoreFS.ts │ ├── orbitStoreInMemory.ts │ ├── sqlite.test.ts │ ├── sqlite.ts │ ├── sqlite │ │ ├── binding.native.ts │ │ ├── binding.ts │ │ ├── metadata.ts │ │ ├── migration.ts │ │ ├── migrations │ │ │ ├── 20210612111147_createMetadataTable.ts │ │ │ ├── 20210612112129_initialSchema.ts │ │ │ ├── 20211019170802_createAttachmentsTable.ts │ │ │ ├── 20230726103155_derived_taskComponents_whenNotDeleted.ts │ │ │ ├── index.ts │ │ │ └── migrationType.ts │ │ ├── tables.ts │ │ └── types.ts │ └── util │ │ └── getPathForAttachment.ts └── tsconfig.json ├── store-shared ├── LICENSE ├── Readme.md ├── package.json ├── src │ ├── attachmentStore.ts │ ├── database.ts │ ├── databaseBackend.ts │ ├── databaseQuery.ts │ ├── databaseTests.ts │ ├── encodeDataURL.ts │ ├── index.ts │ ├── orbitStore.ts │ └── validation │ │ ├── AjvEventsValidator.ts │ │ ├── events.json │ │ └── eventsValidator.ts └── tsconfig.json ├── store-web ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── attachmentStoreWeb.test.ts │ ├── attachmentStoreWeb.ts │ ├── database.test.ts │ ├── dexie │ │ ├── dexie.ts │ │ └── tables.ts │ ├── index.ts │ ├── indexedDB.test.ts │ ├── indexedDB.ts │ └── orbitStoreWeb.ts └── tsconfig.json ├── sync ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── jest.config.cjs ├── package.json ├── src │ ├── APISyncAdapter.ts │ ├── bin │ │ └── run.ts │ ├── index.ts │ ├── orbitStoreSyncAdapter.ts │ ├── sync.test.ts │ ├── sync.ts │ └── syncAdapter.ts └── tsconfig.json ├── tsconfig.base.json ├── tsconfig.json ├── ui ├── .gitignore ├── .storybook │ ├── main.cjs │ └── preview.cjs ├── LICENSE ├── Readme.md ├── assets │ ├── fonts │ │ ├── .gitignore │ │ ├── KaTeX_AMS-Regular.ttf │ │ ├── KaTeX_AMS-Regular.woff │ │ ├── KaTeX_AMS-Regular.woff2 │ │ ├── KaTeX_Caligraphic-Bold.ttf │ │ ├── KaTeX_Caligraphic-Bold.woff │ │ ├── KaTeX_Caligraphic-Bold.woff2 │ │ ├── KaTeX_Caligraphic-Regular.ttf │ │ ├── KaTeX_Caligraphic-Regular.woff │ │ ├── KaTeX_Caligraphic-Regular.woff2 │ │ ├── KaTeX_Fraktur-Bold.ttf │ │ ├── KaTeX_Fraktur-Bold.woff │ │ ├── KaTeX_Fraktur-Bold.woff2 │ │ ├── KaTeX_Fraktur-Regular.ttf │ │ ├── KaTeX_Fraktur-Regular.woff │ │ ├── KaTeX_Fraktur-Regular.woff2 │ │ ├── KaTeX_Main-Bold.ttf │ │ ├── KaTeX_Main-Bold.woff │ │ ├── KaTeX_Main-Bold.woff2 │ │ ├── KaTeX_Main-BoldItalic.ttf │ │ ├── KaTeX_Main-BoldItalic.woff │ │ ├── KaTeX_Main-BoldItalic.woff2 │ │ ├── KaTeX_Main-Italic.ttf │ │ ├── KaTeX_Main-Italic.woff │ │ ├── KaTeX_Main-Italic.woff2 │ │ ├── KaTeX_Main-Regular.ttf │ │ ├── KaTeX_Main-Regular.woff │ │ ├── KaTeX_Main-Regular.woff2 │ │ ├── KaTeX_Math-BoldItalic.ttf │ │ ├── KaTeX_Math-BoldItalic.woff │ │ ├── KaTeX_Math-BoldItalic.woff2 │ │ ├── KaTeX_Math-Italic.ttf │ │ ├── KaTeX_Math-Italic.woff │ │ ├── KaTeX_Math-Italic.woff2 │ │ ├── KaTeX_SansSerif-Bold.ttf │ │ ├── KaTeX_SansSerif-Bold.woff │ │ ├── KaTeX_SansSerif-Bold.woff2 │ │ ├── KaTeX_SansSerif-Italic.ttf │ │ ├── KaTeX_SansSerif-Italic.woff │ │ ├── KaTeX_SansSerif-Italic.woff2 │ │ ├── KaTeX_SansSerif-Regular.ttf │ │ ├── KaTeX_SansSerif-Regular.woff │ │ ├── KaTeX_SansSerif-Regular.woff2 │ │ ├── KaTeX_Script-Regular.ttf │ │ ├── KaTeX_Script-Regular.woff │ │ ├── KaTeX_Script-Regular.woff2 │ │ ├── KaTeX_Size1-Regular.ttf │ │ ├── KaTeX_Size1-Regular.woff │ │ ├── KaTeX_Size1-Regular.woff2 │ │ ├── KaTeX_Size2-Regular.ttf │ │ ├── KaTeX_Size2-Regular.woff │ │ ├── KaTeX_Size2-Regular.woff2 │ │ ├── KaTeX_Size3-Regular.ttf │ │ ├── KaTeX_Size3-Regular.woff │ │ ├── KaTeX_Size3-Regular.woff2 │ │ ├── KaTeX_Size4-Regular.ttf │ │ ├── KaTeX_Size4-Regular.woff │ │ ├── KaTeX_Size4-Regular.woff2 │ │ ├── KaTeX_Typewriter-Regular.ttf │ │ ├── KaTeX_Typewriter-Regular.woff │ │ └── KaTeX_Typewriter-Regular.woff2 │ ├── icons │ │ ├── check-BL.png │ │ ├── check-BL.svg │ │ ├── check-BL@2x.png │ │ ├── check-BL@3x.png │ │ ├── check-BR.png │ │ ├── check-BR.svg │ │ ├── check-BR@2x.png │ │ ├── check-BR@3x.png │ │ ├── check-TL.png │ │ ├── check-TL.svg │ │ ├── check-TL@2x.png │ │ ├── check-TL@3x.png │ │ ├── check-TR.png │ │ ├── check-TR.svg │ │ ├── check-TR@2x.png │ │ ├── check-TR@3x.png │ │ ├── check-center.png │ │ ├── check-center.svg │ │ ├── check-center@2x.png │ │ ├── check-center@3x.png │ │ ├── cross-BL.png │ │ ├── cross-BL.svg │ │ ├── cross-BL@2x.png │ │ ├── cross-BL@3x.png │ │ ├── cross-BR.png │ │ ├── cross-BR.svg │ │ ├── cross-BR@2x.png │ │ ├── cross-BR@3x.png │ │ ├── cross-TL.png │ │ ├── cross-TL.svg │ │ ├── cross-TL@2x.png │ │ ├── cross-TL@3x.png │ │ ├── cross-TR.png │ │ ├── cross-TR.svg │ │ ├── cross-TR@2x.png │ │ ├── cross-TR@3x.png │ │ ├── cross-center.png │ │ ├── cross-center.svg │ │ ├── cross-center@2x.png │ │ ├── cross-center@3x.png │ │ ├── dots-center.png │ │ ├── dots-center.svg │ │ ├── dots-center@2x.png │ │ ├── dots-center@3x.png │ │ ├── doubleRight-TL.png │ │ ├── doubleRight-TL.svg │ │ ├── doubleRight-TL@2x.png │ │ ├── doubleRight-TL@3x.png │ │ ├── doubleRight-center.png │ │ ├── doubleRight-center.svg │ │ ├── doubleRight-center@2x.png │ │ ├── doubleRight-center@3x.png │ │ ├── left-center.png │ │ ├── left-center.svg │ │ ├── left-center@2x.png │ │ ├── left-center@3x.png │ │ ├── list-center.png │ │ ├── list-center.svg │ │ ├── list-center@2x.png │ │ ├── list-center@3x.png │ │ ├── reveal-accent-bottom.png │ │ ├── reveal-accent-bottom.svg │ │ ├── reveal-accent-bottom@2x.png │ │ ├── reveal-accent-bottom@3x.png │ │ ├── reveal-accent-center.png │ │ ├── reveal-accent-center.svg │ │ ├── reveal-accent-center@2x.png │ │ ├── reveal-accent-center@3x.png │ │ ├── reveal-accent-top.png │ │ ├── reveal-accent-top.svg │ │ ├── reveal-accent-top@2x.png │ │ ├── reveal-accent-top@3x.png │ │ ├── reveal-bottom.png │ │ ├── reveal-bottom.svg │ │ ├── reveal-bottom@2x.png │ │ ├── reveal-bottom@3x.png │ │ ├── reveal-center.png │ │ ├── reveal-center.svg │ │ ├── reveal-center@2x.png │ │ ├── reveal-center@3x.png │ │ ├── reveal-top.png │ │ ├── reveal-top.svg │ │ ├── reveal-top@2x.png │ │ ├── reveal-top@3x.png │ │ ├── right-BL.png │ │ ├── right-BL.svg │ │ ├── right-BL@2x.png │ │ ├── right-BL@3x.png │ │ ├── right-BR.png │ │ ├── right-BR.svg │ │ ├── right-BR@2x.png │ │ ├── right-BR@3x.png │ │ ├── right-TL.png │ │ ├── right-TL.svg │ │ ├── right-TL@2x.png │ │ ├── right-TL@3x.png │ │ ├── right-TR.png │ │ ├── right-TR.svg │ │ ├── right-TR@2x.png │ │ ├── right-TR@3x.png │ │ ├── right-center.png │ │ ├── right-center.svg │ │ ├── right-center@2x.png │ │ └── right-center@3x.png │ ├── katex.css │ ├── learnMore │ │ ├── starburst-red.svg │ │ └── starburst.svg │ └── logo │ │ ├── 16.png │ │ ├── 16.svg │ │ ├── 16@2x.png │ │ ├── 16@3x.png │ │ ├── 24.png │ │ ├── 24.svg │ │ ├── 24@2x.png │ │ ├── 24@3x.png │ │ ├── 32.png │ │ ├── 32.svg │ │ ├── 32@2x.png │ │ └── 32@3x.png ├── babel.config.cjs ├── package.json ├── src │ ├── @types │ │ └── markdown-it-texmath │ │ │ └── index.d.ts │ ├── components │ │ ├── Button.stories.tsx │ │ ├── Button.tsx │ │ ├── Card.stories.tsx │ │ ├── Card.tsx │ │ ├── ContinueWithUser.stories.tsx │ │ ├── ContinueWithUser.tsx │ │ ├── DebugGrid.stories.tsx │ │ ├── DebugGrid.tsx │ │ ├── FadeView.stories.tsx │ │ ├── FadeView.tsx │ │ ├── Hoverable.tsx │ │ ├── Icon.stories.tsx │ │ ├── Icon.tsx │ │ ├── Icon.web.tsx │ │ ├── IconShared.ts │ │ ├── Link.tsx │ │ ├── Logo.stories.tsx │ │ ├── Logo.tsx │ │ ├── Logo.web.tsx │ │ ├── LogoShared.ts │ │ ├── Menu.stories.tsx │ │ ├── Menu.tsx │ │ ├── PromptFieldRenderer.tsx │ │ ├── PromptFieldRenderer │ │ │ ├── clozeHighlightPlugin.tsx │ │ │ ├── markdown.ts │ │ │ ├── markdownLatexSupport.tsx │ │ │ └── markdownLatexSupport.web.tsx │ │ ├── ReviewArea.stories.tsx │ │ ├── ReviewArea.tsx │ │ ├── ReviewButtonBar.tsx │ │ ├── ReviewStarburst.stories.tsx │ │ ├── ReviewStarburst.tsx │ │ ├── SawtoothPattern.tsx │ │ ├── Spacer.tsx │ │ ├── Starburst.stories.tsx │ │ ├── Starburst.tsx │ │ ├── StarburstLegend.tsx │ │ ├── TextInput.stories.tsx │ │ ├── TextInput.tsx │ │ ├── __fixtures__ │ │ │ ├── colorPaletteArgType.ts │ │ │ └── generateReviewItem.ts │ │ └── hooks │ │ │ ├── useKey.ts │ │ │ ├── useLayout.ts │ │ │ ├── usePrevious.ts │ │ │ ├── useTransitioningValue.stories.tsx │ │ │ ├── useTransitioningValue.ts │ │ │ └── useWeakRef.ts │ ├── index.ts │ ├── reviewAreaItem.ts │ ├── styles │ │ ├── colors.stories.tsx │ │ ├── colors.ts │ │ ├── index.ts │ │ ├── layout.ts │ │ ├── type.stories.tsx │ │ └── type.ts │ └── util │ │ ├── Size.ts │ │ ├── clamp.ts │ │ ├── generateIntervalSequence.ts │ │ ├── lerp.ts │ │ └── unreachableCaseError.ts └── tsconfig.json └── web-component ├── .firebaserc ├── .gitignore ├── LICENSE ├── Readme.md ├── babel.config.cjs ├── firebase.json ├── jest.config.cjs ├── package.json ├── scripts ├── bundleDev.ts ├── bundleProd.ts ├── bundleShared.ts └── tsconfig.json ├── src ├── OrbitPromptElement.ts ├── OrbitReviewAreaElement.ts ├── extractItems.test.ts ├── extractItems.ts ├── index.ts └── metadataMonitor.ts ├── test ├── index.html └── orbit-web-component.js └── tsconfig.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.lockb binary diff=lockb 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: quantumcountry 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 🛑 11 | 12 | Please read the "Contributing" section of the project README before continuing. We don't have the capacity to engage with feature requests without preliminary conversation unless you're already a well-known contributor. 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/something-else.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Something else 3 | about: Something else on your mind? 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 🛑 11 | 12 | Please read the "Contributing" section of the project README before continuing. We don't currently have the capacity to engage with most new issues from new collaborators. 13 | 14 | If you'd like to discuss something about Orbit, you can try [emailing Andy](mailto:andy@andymatuschak.org). 15 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/dictionaries/andym.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/jsLinters/eslint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/markdown.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/prettier.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 20 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "jest.pathToJest": "bun run test" 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "npm", 6 | "script": "build", 7 | "problemMatcher": [ 8 | "$tsc" 9 | ], 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | }, 14 | "label": "npm: build", 15 | "detail": "tsc -b packages/tsconfig.base.json" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 Andy Matuschak. 2 | 3 | All sources in this repository, except those in the subtrees packages/app and packages/backend, and all compiled distribution binaries, are licensed under Apache 2.0 (see LICENSE.Apache-2.0 for text). 4 | 5 | Sources in packages/app and packages/backend are licensed under AGPL 3.0+ or BUSL 1.1 (your choice; see LICENSE.AGPL-3.0-or-later and LICENSE.BUSL1.1 for respective texts). 6 | 7 | See discussion in Readme.md for more background. 8 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Orbit 2 | Copyright 2020 Andy Matuschak 3 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/bun.lockb -------------------------------------------------------------------------------- /design/reveal answer - scale.origami: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/reveal answer - scale.origami -------------------------------------------------------------------------------- /design/reveal answer and advance question - fade.origami: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/reveal answer and advance question - fade.origami -------------------------------------------------------------------------------- /design/starburst-icon-iOS_1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_1024x1024.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_20x20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_20x20.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_20x20@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_20x20@3x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_29x29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_29x29.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_29x29@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_29x29@3x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_40x40.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_40x40@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_40x40@3x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_60x60@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_60x60@3x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_76x76.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_76x76@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-iOS_83-5x83-5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-iOS_83-5x83-5@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_1024x1024.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_128x128.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_128x128@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_16x16.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_16x16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_16x16@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_256x256.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_256x256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_256x256@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_32x32.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_32x32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_32x32@2x.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_512x512.png -------------------------------------------------------------------------------- /design/starburst-icon-macOS_512x512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon-macOS_512x512@2x.png -------------------------------------------------------------------------------- /design/starburst-icon.fig: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/design/starburst-icon.fig -------------------------------------------------------------------------------- /design/starburst-icon.md: -------------------------------------------------------------------------------- 1 | The "canonical" starburst used as the app icon is currently taken from the Starburst Sandbox in the UI Storybook. Probably we'll want to tune it by hand at some point, but this'll do for now. The settings: 2 | 3 | * Line count: 18 4 | * Random seed: seed111111111111111111111111 5 | * Line min: 0.25 6 | * Liune max: 0.95 7 | * Size: 120 8 | * Use composition: yes 9 | * Color palette index: 0 10 | * All colors: black 11 | * Extra rotation degrees: 10 12 | * Scale: 1.0 13 | * Translate X/Y: 0 14 | * Thickness: 4 15 | 16 | Then I copy/paste the SVG into Figma, matte it onto "brand red" (#ED3749), and export. 17 | -------------------------------------------------------------------------------- /packages/.eslintignore: -------------------------------------------------------------------------------- 1 | web-component/build/**/* 2 | web-component/test/**/* 3 | web-component/orbit-web-component-prod.js* 4 | app/index.js 5 | app/expoPlugin/**/* 6 | app/.expo/**/* 7 | app/web-build/**/* 8 | */dist/**/* 9 | -------------------------------------------------------------------------------- /packages/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: "all", 3 | }; 4 | -------------------------------------------------------------------------------- /packages/anki-import/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/anki-import 2 | 3 | This module implements a non-production-ready import process for Anki `.apkg` files into Orbit. It's implemented as a library; see `cli/importAnkiCollection.ts` for an example usage. A production client of this library should inform the user of potential lossiness during the transformation (and should probably be integrated into `app`). 4 | 5 | ``` 6 | Copyright 2020 Andy Matuschak 7 | SPDX-License-Identifier: Apache-2.0 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /packages/anki-import/babel.config.cjs: -------------------------------------------------------------------------------- 1 | // babel.config.js 2 | module.exports = { 3 | presets: [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | targets: { 8 | node: "current", 9 | }, 10 | }, 11 | ], 12 | "@babel/preset-typescript", 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /packages/anki-import/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | transformIgnorePatterns: [], 9 | }; 10 | -------------------------------------------------------------------------------- /packages/anki-import/src/__fixtures__/testCollection.colpkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/anki-import/src/__fixtures__/testCollection.colpkg -------------------------------------------------------------------------------- /packages/anki-import/src/__fixtures__/withTestAnkiCollection.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { 3 | AnkiCollectionDBHandle, 4 | MediaManifest, 5 | readAnkiCollectionPackage, 6 | } from "../ankiPkg/index.js"; 7 | 8 | export default function withTestAnkiCollection( 9 | continuation: ( 10 | handle: AnkiCollectionDBHandle, 11 | mediaManifest: MediaManifest | null, 12 | attachmentIDsToExtractedPaths: { [key: string]: string }, 13 | ) => Promise, 14 | ): Promise { 15 | return readAnkiCollectionPackage( 16 | path.resolve(__dirname, "./testCollection.colpkg"), 17 | continuation, 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /packages/anki-import/src/ankiPkg/ankiAttachmentReference.ts: -------------------------------------------------------------------------------- 1 | export type AnkiAttachmentReference = { 2 | type: "sound" | "image"; 3 | name: string; 4 | }; 5 | -------------------------------------------------------------------------------- /packages/anki-import/src/ankiPkg/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ankiCollection.js"; 2 | export * from "./ankiDBTypes.js"; 3 | export { default as splitAnkiDBNoteFields } from "./splitAnkiDBNoteFields.js"; 4 | -------------------------------------------------------------------------------- /packages/anki-import/src/ankiPkg/splitAnkiDBNoteFields.test.ts: -------------------------------------------------------------------------------- 1 | import splitAnkiDBNoteFields from "./splitAnkiDBNoteFields.js"; 2 | 3 | test("parse Anki DB field with two entries", () => { 4 | // String literal here copied from my database, includes the 0x1f character code. 5 | expect(splitAnkiDBNoteFields("1 lb in kg0.45 kg")).toMatchObject([ 6 | "1 lb in kg", 7 | "0.45 kg", 8 | ]); 9 | }); 10 | 11 | test("parse Anki DB field with one entry", () => { 12 | expect(splitAnkiDBNoteFields("test")).toMatchObject(["test"]); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/anki-import/src/ankiPkg/splitAnkiDBNoteFields.ts: -------------------------------------------------------------------------------- 1 | // Extracts field contents from an Anki collection DB Note.flds column entry 2 | export default function splitAnkiDBNoteFields( 3 | ankiDBNoteFields: string, 4 | ): string[] { 5 | return ankiDBNoteFields.split(String.fromCharCode(31)); 6 | } 7 | -------------------------------------------------------------------------------- /packages/anki-import/src/convertAnkiID.ts: -------------------------------------------------------------------------------- 1 | import { 2 | encodeUUIDBytesToWebSafeBase64ID, 3 | EntityID, 4 | EventID, 5 | } from "@withorbit/core"; 6 | import { parse as uuidParse, v5 as uuidV5 } from "uuid"; 7 | 8 | let _orbitAnkiImportNamespaceUUID: ArrayLike | null = null; 9 | 10 | // Generate a consistent Orbit ID (a v5 instead of v4 UUID) from an Anki ID. 11 | export function convertAnkiID( 12 | input: string, 13 | ): ID { 14 | if (!_orbitAnkiImportNamespaceUUID) { 15 | _orbitAnkiImportNamespaceUUID = uuidParse( 16 | "a430c93f-60dc-4799-b2a6-df402ff941a5", 17 | ); 18 | } 19 | 20 | const bytes = new Uint8Array(16); 21 | uuidV5(input, _orbitAnkiImportNamespaceUUID, bytes); 22 | return encodeUUIDBytesToWebSafeBase64ID(bytes); 23 | } 24 | -------------------------------------------------------------------------------- /packages/anki-import/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createImportPlan } from "./importPlan.js"; 2 | export { readAnkiCollectionPackage } from "./ankiPkg/ankiCollection.js"; 3 | -------------------------------------------------------------------------------- /packages/anki-import/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["node", "jest", "mdast"] 7 | }, 8 | "include": ["./src/**/*.ts"], 9 | "references": [ 10 | { 11 | "path": "../core" 12 | }, 13 | { 14 | "path": "../sample-data" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /packages/api-client/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/api-client 2 | 3 | A simple preliminary implementation of an API client for Orbit. See `@withorbit/api` for the main interface definition, which this library wraps. 4 | 5 | ``` 6 | Copyright 2020 Andy Matuschak 7 | SPDX-License-Identifier: Apache-2.0 8 | ``` 9 | -------------------------------------------------------------------------------- /packages/api-client/babel.config.cjs: -------------------------------------------------------------------------------- 1 | // babel.config.js 2 | module.exports = { 3 | presets: [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | targets: { 8 | node: "current", 9 | }, 10 | }, 11 | ], 12 | "@babel/preset-typescript", 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /packages/api-client/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | transformIgnorePatterns: [], 9 | }; 10 | -------------------------------------------------------------------------------- /packages/api-client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@withorbit/api-client", 3 | "version": "0.0.1", 4 | "license": "Apache-2.0", 5 | "private": true, 6 | "type": "module", 7 | "main": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "sideEffects": false, 10 | "devDependencies": { 11 | "@babel/core": "^7.14.6", 12 | "@babel/preset-env": "^7.14.7", 13 | "@babel/preset-typescript": "^7.14.5", 14 | "@types/jest": "^29.5.5", 15 | "@types/node": "^20.10.4", 16 | "@withorbit/sample-data": "0.0.1", 17 | "babel-jest": "^29.7.0", 18 | "jest": "^29.7.0", 19 | "typescript": "^5.3.3" 20 | }, 21 | "dependencies": { 22 | "@withorbit/api": "0.0.1", 23 | "@withorbit/core": "0.0.1", 24 | "react-native-blob-jsi-helper": "^0.3.1" 25 | }, 26 | "scripts": { 27 | "build": "tsc -b", 28 | "watch": "tsc -w", 29 | "test": "jest --runInBand" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/api-client/src/apiConfig.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export interface APIConfig { 4 | baseURL: string; // no trailing slash 5 | 6 | fetch?: typeof fetch; 7 | } 8 | 9 | export const defaultAPIConfig: APIConfig = { 10 | baseURL: "https://withorbit.com/api", 11 | }; 12 | 13 | export const emulatorAPIConfig: APIConfig = { 14 | ...defaultAPIConfig, 15 | baseURL: "http://127.0.0.1:5001/metabook-system/us-central1/api", 16 | }; 17 | -------------------------------------------------------------------------------- /packages/api-client/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { APIConfig } from "./apiConfig.js"; 2 | export { defaultAPIConfig, emulatorAPIConfig } from "./apiConfig.js"; 3 | 4 | export { OrbitAPIClient as default } from "./orbitAPIClient.js"; 5 | -------------------------------------------------------------------------------- /packages/api-client/src/util/fetch.native.ts: -------------------------------------------------------------------------------- 1 | import { API } from "@withorbit/api"; 2 | import { getArrayBufferForBlob } from "react-native-blob-jsi-helper"; 3 | 4 | export async function getBytesFromBlobLike( 5 | blobLike: API.BlobLike, 6 | ): Promise { 7 | return getArrayBufferForBlob(blobLike as Blob); 8 | } 9 | 10 | export function createBlobFromBuffer( 11 | buffer: Uint8Array, 12 | mimeType: T, 13 | ): API.BlobLike { 14 | return { 15 | type: mimeType, 16 | size: buffer.length, 17 | name: "unknown.txt", 18 | base64: btoa(String.fromCharCode.apply(null, Array.from(buffer))), 19 | } as API.BlobLike; 20 | } 21 | -------------------------------------------------------------------------------- /packages/api-client/src/util/fetch.ts: -------------------------------------------------------------------------------- 1 | import { API } from "@withorbit/api"; 2 | 3 | export async function getBytesFromBlobLike( 4 | blobLike: API.BlobLike, 5 | ): Promise { 6 | if (!blobLike.arrayBuffer) { 7 | throw new Error("Unexpectedly missing implementation of Blob.arrayBuffer"); 8 | } 9 | return new Uint8Array(await blobLike.arrayBuffer()); 10 | } 11 | 12 | export function createBlobFromBuffer( 13 | buffer: Uint8Array, 14 | mimeType: string, 15 | ): Blob { 16 | return new Blob([buffer], { type: mimeType }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/api-client/src/util/mockAPIValiation.ts: -------------------------------------------------------------------------------- 1 | import { APIValidator } from "@withorbit/api"; 2 | 3 | export class MockOrbitAPIValidation implements APIValidator { 4 | validateRequest(): true { 5 | return true; 6 | } 7 | 8 | validateResponse(): true { 9 | return true; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/api-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "lib": ["es2022", "dom", "dom.iterable"], 7 | "types": ["jest", "node"] 8 | }, 9 | "include": ["./src/**/*.ts"], 10 | "references": [ 11 | { 12 | "path": "../core" 13 | }, 14 | { 15 | "path": "../sample-data" 16 | }, 17 | { 18 | "path": "../api" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/api/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/api 2 | 3 | Type-only package specifying Orbit's API surface, used by `api-client` (client-side) and `backend` (to route requests on the server). 4 | 5 | ``` 6 | Copyright 2020 Andy Matuschak 7 | SPDX-License-Identifier: Apache-2.0 8 | ``` 9 | -------------------------------------------------------------------------------- /packages/api/babel.config.cjs: -------------------------------------------------------------------------------- 1 | // babel.config.js 2 | module.exports = { 3 | presets: [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | targets: { 8 | node: "current", 9 | }, 10 | }, 11 | ], 12 | "@babel/preset-typescript", 13 | ], 14 | }; 15 | -------------------------------------------------------------------------------- /packages/api/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | transformIgnorePatterns: [], 9 | }; 10 | -------------------------------------------------------------------------------- /packages/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@withorbit/api", 3 | "version": "0.0.1", 4 | "type": "module", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "files": [ 8 | "dist" 9 | ], 10 | "private": true, 11 | "sideEffects": false, 12 | "scripts": { 13 | "build": "tsc -b", 14 | "test": "jest --runInBand", 15 | "generateSchema": "typescript-json-schema src/orbitAPI.ts ValidatableSpec -o src/orbitAPISchema.json --noExtraProps --required --ignoreErrors --strictNullChecks" 16 | }, 17 | "dependencies": { 18 | "@withorbit/core": "0.0.1", 19 | "ajv": "^8.6.2" 20 | }, 21 | "devDependencies": { 22 | "@types/jest": "^29.5.5", 23 | "@types/node": "^20.10.4", 24 | "babel-jest": "^29.7.0", 25 | "jest": "^29.7.0", 26 | "typescript": "^5.3.3", 27 | "typescript-json-schema": "^0.50.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/api/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as OrbitAPI from "./orbitAPI.js"; 2 | export * as API from "./genericHTTPAPI.js"; 3 | export { OrbitAPIValidator } from "./validation/orbitAPIValidator.js"; 4 | export type { 5 | APIValidator, 6 | APIValidatorError, 7 | } from "./validation/apiValidator.js"; 8 | -------------------------------------------------------------------------------- /packages/api/src/util/requiredSpec.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Converts a nested Spec object with optional HTTP methods and routes to be required. For example: 3 | * ``` 4 | * type Spec = RequiredSpec<{ 5 | * "/hello"?: { 6 | * GET?: { 7 | * query: { name: string }; 8 | * response?: string; 9 | * } 10 | * } 11 | * }> 12 | * // is equivalent too 13 | * type Spec = RequiredSpec<{ 14 | * "/hello": { 15 | * GET: { 16 | * query: { name: string }; 17 | * response: string; 18 | * } 19 | * } 20 | * }> 21 | * ``` 22 | */ 23 | export type RequiredSpec = Required>; 24 | 25 | type NestedRequired = { 26 | [P in keyof T]: Required>; 27 | }; 28 | 29 | type NestedRequiredWithoutRecursion = { 30 | [P in keyof T]: Required; 31 | }; 32 | -------------------------------------------------------------------------------- /packages/api/src/validation/apiValidator.ts: -------------------------------------------------------------------------------- 1 | export type APIValidatorRequest = { 2 | method: string; 3 | path: string; 4 | contentType?: string; 5 | params?: { [key: string]: unknown }; 6 | query?: { [key: string]: unknown }; 7 | body?: unknown; 8 | }; 9 | 10 | export type APIValidatorError = { 11 | errors: { message: string }[]; 12 | }; 13 | 14 | export interface APIValidator { 15 | validateRequest(request: APIValidatorRequest): APIValidatorError | true; 16 | validateResponse( 17 | request: APIValidatorRequest, 18 | response: unknown, 19 | ): APIValidatorError | true; 20 | } 21 | -------------------------------------------------------------------------------- /packages/api/src/validation/orbitAPIValidator.ts: -------------------------------------------------------------------------------- 1 | import { ValidatableSpec } from "../orbitAPI.js"; 2 | import OrbitAPISchema from "../orbitAPISchema.json" assert { type: "json" }; 3 | import { AjvAPIValidator, AjvAPIValidatorConfig } from "./ajvAPIValidator.js"; 4 | 5 | export class OrbitAPIValidator extends AjvAPIValidator { 6 | constructor(config: AjvAPIValidatorConfig) { 7 | super(config, OrbitAPISchema); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["./src/**/*.ts", "./src/**/*.json"], 9 | "references": [ 10 | { 11 | "path": "../core" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /packages/app/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "metabook-system" 4 | }, 5 | "targets": { 6 | "metabook-system": { 7 | "hosting": { 8 | "orbit-app": ["orbit-app"], 9 | "orbit-docs": [ 10 | "orbit-docs" 11 | ], 12 | "orbit-cdn": ["orbit-cdn"] 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/app/.gitignore: -------------------------------------------------------------------------------- 1 | /.expo 2 | /web-build 3 | /public/fonts 4 | /.firebase 5 | 6 | # These native directories should be generated on-demand using expo's Continuous Native Generation feature. 7 | /ios 8 | /android 9 | 10 | # @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb 11 | # The following patterns were generated by expo-cli 12 | 13 | expo-env.d.ts 14 | # @end expo-cli -------------------------------------------------------------------------------- /packages/app/LICENSE: -------------------------------------------------------------------------------- 1 | AGPL-3.0-or-later OR BUSL-1.1 2 | -------------------------------------------------------------------------------- /packages/app/app-assets/starburst-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/app-assets/starburst-icon.png -------------------------------------------------------------------------------- /packages/app/assets: -------------------------------------------------------------------------------- 1 | ../ui/assets -------------------------------------------------------------------------------- /packages/app/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: ["babel-preset-expo"], 5 | plugins: [ 6 | [ 7 | "@babel/plugin-syntax-import-attributes", 8 | // TODO remove when we move to Node 22 and update import assert to import with 9 | { deprecatedAssertSyntax: true }, 10 | ], 11 | ], 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/expoPlugin.js: -------------------------------------------------------------------------------- 1 | const { withPlugins } = require("expo/config-plugins"); 2 | const serviceConfig = require("../serviceConfig"); 3 | const withCatalystSupport = require("./withCatalystSupport"); 4 | const withIngestIntent = require("./withIngestIntent"); 5 | const withReactNativeKeyEventSupport = require("./withReactNativeKeyEventSupport"); 6 | const withSQLImageURLLoader = require("./withSQLImageURLLoader"); 7 | const withWidgetPluginFixes = require("./withWidgetPluginFixes"); 8 | 9 | module.exports = function withOrbitExpoConfigPlugin(config) { 10 | return withPlugins(config, [ 11 | [ 12 | withCatalystSupport, 13 | { developmentTeamID: serviceConfig.appleDevelopmentTeamID }, 14 | ], 15 | withIngestIntent, 16 | withSQLImageURLLoader, 17 | withReactNativeKeyEventSupport, 18 | withWidgetPluginFixes, 19 | ]); 20 | }; 21 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/ios/AppDelegate+Intents.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate+KeyHandling.m 3 | // Orbit 4 | // 5 | // Created by Andy Matuschak on 2023-12-21. 6 | // 7 | 8 | #import 9 | #import "IngestEventHandler.h" 10 | #import "AppDelegate.h" 11 | 12 | @implementation AppDelegate (Intents) 13 | 14 | - (id)application:(UIApplication *)application handlerForIntent:(INIntent *)intent { 15 | if ([intent isKindOfClass:[ShortcutIngestIntent class]]) { 16 | return [[IngestEventHandler alloc] init]; 17 | } 18 | return nil; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/ios/IngestEventEmitter.h: -------------------------------------------------------------------------------- 1 | // 2 | // EventEmitter.h 3 | // Orbit 4 | // 5 | // Created by Ozzie Kirkby on 2022-05-07. 6 | // 7 | 8 | #ifndef EventEmitter_h 9 | #define EventEmitter_h 10 | 11 | #import 12 | #import 13 | 14 | @interface IngestEventEmitter : RCTEventEmitter 15 | 16 | @property(atomic,assign) bool hasListeners; 17 | @property(atomic,copy) void (^completionHandler)(BOOL *result); 18 | 19 | - (void)emitIngestEvent:(NSString *)fileJSON completion:(void (^)(BOOL *result))block; 20 | 21 | @end 22 | 23 | #endif /* EventEmitter_h */ 24 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/ios/IngestEventHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // IngestEventHandler.h 3 | // Orbit 4 | // 5 | // Created by Ozzie Kirkby on 2022-05-08. 6 | // 7 | 8 | #ifndef IngestEventHandler_h 9 | #define IngestEventHandler_h 10 | // Automatically generated file by SiriKit which codify's 11 | // the intent definitions. 12 | #import "ShortcutIngestIntent.h" 13 | 14 | @interface IngestEventHandler : NSObject 15 | 16 | @end 17 | 18 | #endif /* IngestEventHandler_h */ 19 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/ios/ORSQLImageURLLoader.h: -------------------------------------------------------------------------------- 1 | // 2 | // ORSQLImageURLLoader.h 3 | // Orbit 4 | // 5 | // Created by Andy Matuschak on 10/19/21. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface ORSQLImageURLLoader : NSObject 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/ios/ORWidgetReloadBridge.m: -------------------------------------------------------------------------------- 1 | // 2 | // ORWidgetReloadBridge.m 3 | // Orbit 4 | // 5 | // Created by Andy Matuschak on 2024-07-12. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface RCT_EXTERN_MODULE(WidgetReloadBridge, NSObject) 14 | RCT_EXTERN_METHOD(reloadTimelines) 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/ios/ORWidgetReloadBridge.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ORWidgetReloadBridge.swift 3 | // Orbit 4 | // 5 | // Created by Andy Matuschak on 2024-07-12. 6 | // 7 | 8 | import Foundation 9 | import WidgetKit 10 | 11 | @objc(WidgetReloadBridge) class WidgetReloadBridge: NSObject { 12 | @objc public func reloadTimelines() { 13 | WidgetCenter.shared.reloadAllTimelines() 14 | print("Reloading timelines") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/withReactNativeKeyEventSupport.js: -------------------------------------------------------------------------------- 1 | const { withXcodeProject } = require("expo/config-plugins"); 2 | const { addSourceFile, addResourceFile } = require("./util"); 3 | 4 | module.exports = function withReactNativeKeyEventSupport(config) { 5 | return withXcodeProject(config, async (config) => { 6 | addSourceFile(config, "AppDelegate+KeyHandling.m"); 7 | return config; 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /packages/app/expoPlugin/withSQLImageURLLoader.js: -------------------------------------------------------------------------------- 1 | const { withXcodeProject, IOSConfig } = require("expo/config-plugins"); 2 | const { addSourceFile } = require("./util"); 3 | 4 | // Attachments are stored as blobs in the Orbit SQLite database. We use a custom URL to specify images to the React Native tag; this resolver provides the data on demand. 5 | module.exports = function withSQLImageURLLoader(config) { 6 | return withXcodeProject(config, async (config) => { 7 | addSourceFile(config, "ORSQLImageURLLoader.h"); 8 | addSourceFile(config, "ORSQLImageURLLoader.m"); 9 | return config; 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /packages/app/scripts/deploy_web.sh: -------------------------------------------------------------------------------- 1 | export SENTRY_AUTH_TOKEN=$(firebase functions:config:get sentry.auth_token | sed -e "s/\"//g") 2 | export SENTRY_ORG=$(bun -e "import serviceConfig from './serviceConfig.js'; console.log(serviceConfig.sentryOrg)") 3 | export SENTRY_PROJECT=$(bun -e "import serviceConfig from './serviceConfig.js'; console.log(serviceConfig.sentryProject)") 4 | VERSION=$(sentry-cli releases propose-version) 5 | 6 | sentry-cli releases -o "$SENTRY_ORG" new -p "$SENTRY_PROJECT" "$VERSION" 7 | sentry-cli releases -o "$SENTRY_ORG" set-commits --auto "$VERSION" 8 | 9 | bun run build:web 10 | bunx firebase deploy --only hosting 11 | 12 | sentry-cli releases -o "$SENTRY_ORG" files "$VERSION" upload-sourcemaps --no-rewrite ./web-build/static/js 13 | sentry-cli releases -o "$SENTRY_ORG" finalize "$VERSION" 14 | sentry-cli releases -o "$SENTRY_ORG" deploys "$VERSION" new -e production 15 | -------------------------------------------------------------------------------- /packages/app/scripts/generate_browser_compatibility_regex.sh: -------------------------------------------------------------------------------- 1 | SUPPORTED_BROWSER_REGEX="$(npx browserslist-useragent-regexp --allowHigherVersions)" 2 | GENERATED_STR="" 3 | GENERATED_STR+="// DO NOT MODIFY THIS CODE MANUALLY\n" 4 | GENERATED_STR+="// eslint-disable-next-line @typescript-eslint/no-unused-vars\n" 5 | GENERATED_STR+="const supportedBrowserRegex = $SUPPORTED_BROWSER_REGEX;" 6 | 7 | echo $GENERATED_STR > web/browserCompatibility.js -------------------------------------------------------------------------------- /packages/app/serviceConfig.js: -------------------------------------------------------------------------------- 1 | const shouldUseLocalBackend = typeof __DEV__ === "undefined" ? false : __DEV__; 2 | // Uncomment this line (and comment the above) to use the production backend in dev. 3 | // const shouldUseLocalBackend = false; 4 | 5 | module.exports = { 6 | sentryDSN: 7 | "https://7a9cba7e96b54da4bae2c6eb9b8d7b18@o240663.ingest.sentry.io/5306223", 8 | sentryOrg: "andy-matuschak", 9 | sentryProject: "orbit-app", 10 | // Store your auth token securely: firebase functions:config:set sentry.auth_token=SENTRY_AUTH_TOKEN 11 | 12 | httpsAPIBaseURLString: shouldUseLocalBackend 13 | ? "http://127.0.0.1:5001/metabook-system/us-central1/api" 14 | : "https://withorbit.com/api", 15 | shouldUseLocalBackend, 16 | 17 | appleDevelopmentTeamID: "MQ22N839N8", 18 | }; 19 | -------------------------------------------------------------------------------- /packages/app/src/app/(auth)/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { Slot } from "expo-router"; 2 | import React, { useState } from "react"; 3 | import { AuthenticationClientContext } from "../../authentication/authContext.js"; 4 | import * as Authentication from "../../authentication/index.js"; 5 | import { getFirebaseAuth } from "../../util/firebaseAuth.js"; 6 | 7 | export default function RootLayout() { 8 | const [authenticationClient] = useState( 9 | () => new Authentication.FirebaseAuthenticationClient(getFirebaseAuth()), 10 | ); 11 | return ( 12 | 13 | 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/app/src/app/(index)/_layout.tsx: -------------------------------------------------------------------------------- 1 | export { default } from "../(auth)/_layout.js"; 2 | -------------------------------------------------------------------------------- /packages/app/src/app/(index)/_layout.web.tsx: -------------------------------------------------------------------------------- 1 | import { Slot } from "expo-router"; 2 | import React from "react"; 3 | 4 | export default function IndexLayout() { 5 | return ; 6 | } 7 | -------------------------------------------------------------------------------- /packages/app/src/app/(index)/index.tsx: -------------------------------------------------------------------------------- 1 | export { default } from "../(auth)/review.js"; 2 | -------------------------------------------------------------------------------- /packages/app/src/app/(index)/index.web.tsx: -------------------------------------------------------------------------------- 1 | export { default } from "../learnMore.js"; 2 | -------------------------------------------------------------------------------- /packages/app/src/app/_layout.tsx: -------------------------------------------------------------------------------- 1 | import { Slot } from "expo-router"; 2 | import React from "react"; 3 | import { initializeReporter } from "../errorReporting"; 4 | import { initIntentHandlers } from "../util/intents/IntentHandler.js"; 5 | import usePageViewTracking from "../util/usePageViewTracking"; 6 | 7 | initIntentHandlers(); 8 | 9 | export default function RootLayout() { 10 | usePageViewTracking(); 11 | React.useEffect(() => { 12 | initializeReporter(); 13 | }, []); 14 | 15 | return ; 16 | } 17 | -------------------------------------------------------------------------------- /packages/app/src/authentication/index.ts: -------------------------------------------------------------------------------- 1 | export type { AuthenticationClient, UserRecord } from "./authenticationClient.js"; 2 | export { 3 | default as FirebaseAuthenticationClient, 4 | FirebaseOpaqueLoginToken, 5 | FirebaseOpaqueIDToken, 6 | } from "./firebaseAuthenticationClient.js"; 7 | -------------------------------------------------------------------------------- /packages/app/src/authentication/isBrowserStorageAvailable.native.ts: -------------------------------------------------------------------------------- 1 | export default function isSessionStorageAvailable() { 2 | throw new Error("Unimplemented"); 3 | } 4 | -------------------------------------------------------------------------------- /packages/app/src/embedded/TestModeBanner.tsx: -------------------------------------------------------------------------------- 1 | import { styles } from "@withorbit/ui"; 2 | import React from "react"; 3 | import { Text, View } from "react-native"; 4 | 5 | export function TestModeBanner(props: { 6 | colorPalette: styles.colors.ColorPalette; 7 | }) { 8 | /* HACK HACK HACK */ 9 | return ( 10 | 21 | 27 | TEST MODE: Actions will not be saved. 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /packages/app/src/embedded/ipc/sendUpdatedReviewItemToHost.ts: -------------------------------------------------------------------------------- 1 | import { Task } from "@withorbit/core"; 2 | import { 3 | EmbeddedScreenEventType, 4 | EmbeddedScreenTaskUpdateEvent, 5 | } from "@withorbit/embedded-support"; 6 | 7 | export function sendUpdatedReviewItemToHost(task: Task) { 8 | const event: EmbeddedScreenTaskUpdateEvent = { 9 | type: EmbeddedScreenEventType.TaskUpdate, 10 | task, 11 | }; 12 | parent.postMessage(event, "*"); 13 | } 14 | -------------------------------------------------------------------------------- /packages/app/src/embedded/util/getEmbeddedScreenConfigurationFromURL.ts: -------------------------------------------------------------------------------- 1 | import { EmbeddedScreenConfiguration } from "@withorbit/embedded-support"; 2 | import { styles } from "@withorbit/ui"; 3 | 4 | export default function getEmbeddedScreenConfigurationFromURL( 5 | href: string, 6 | ): EmbeddedScreenConfiguration | null { 7 | const url = new URL(href); 8 | const params = new URLSearchParams(url.search); 9 | const tasksString = params.get("i"); 10 | if (tasksString === null) return null; 11 | 12 | const configuration: EmbeddedScreenConfiguration = JSON.parse(tasksString); 13 | // TODO: validate 14 | const colorPaletteName = configuration.embeddedHostMetadata.colorPaletteName; 15 | if (colorPaletteName && !styles.colors.palettes[colorPaletteName]) { 16 | throw new Error(`Unknown color palette name: ${colorPaletteName}`); 17 | } 18 | return configuration; 19 | } 20 | -------------------------------------------------------------------------------- /packages/app/src/errorReporting.ts: -------------------------------------------------------------------------------- 1 | import * as Sentry from "@sentry/react-native"; 2 | import serviceConfig from "../serviceConfig.js"; 3 | 4 | const useSentryInDevelopment = false; 5 | 6 | export function initializeReporter() { 7 | Sentry.init({ 8 | dsn: serviceConfig.sentryDSN, 9 | enabled: useSentryInDevelopment, 10 | debug: __DEV__, 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /packages/app/src/homeRedirect/homeRedirect.tsx: -------------------------------------------------------------------------------- 1 | import { useRouter } from "expo-router"; 2 | 3 | // Expo Router doesn't support platform extensions in its page-based routing. Instead, we have to support some non-route component which has the extensions. 4 | // https://docs.expo.dev/router/advanced/platform-specific-modules/#platform-specific-extensions 5 | export default function Page() { 6 | const router = useRouter(); 7 | router.push("/review"); 8 | } 9 | -------------------------------------------------------------------------------- /packages/app/src/homeRedirect/homeRedirect.web.tsx: -------------------------------------------------------------------------------- 1 | // Expo Router doesn't support platform extensions in its page-based routing. Instead, we have to support some non-route component which has the extensions. 2 | // https://docs.expo.dev/router/advanced/platform-specific-modules/#platform-specific-extensions 3 | export { default } from "../app/learnMore.js"; 4 | -------------------------------------------------------------------------------- /packages/app/src/index.js: -------------------------------------------------------------------------------- 1 | import "./util/shims.js"; 2 | import "expo-router/entry"; 3 | -------------------------------------------------------------------------------- /packages/app/src/infoPage/InfoPage.tsx: -------------------------------------------------------------------------------- 1 | import { InfoPageProps } from "./InfoPageShared.js"; 2 | 3 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 4 | export function InfoPage(props: InfoPageProps): null { 5 | throw new Error("Only implemented on web."); 6 | } 7 | -------------------------------------------------------------------------------- /packages/app/src/model2/orbitStoreFactory.ts: -------------------------------------------------------------------------------- 1 | import { OrbitStore } from "@withorbit/store-shared"; 2 | import OrbitStoreFS from "@withorbit/store-fs"; 3 | 4 | export async function createOrbitStore( 5 | databaseName: string, 6 | ): Promise { 7 | return new OrbitStoreFS(databaseName); 8 | } 9 | 10 | export async function createDefaultOrbitStore(): Promise { 11 | return createOrbitStore("shared.orbitStore"); 12 | } 13 | -------------------------------------------------------------------------------- /packages/app/src/model2/orbitStoreFactory.web.ts: -------------------------------------------------------------------------------- 1 | import { OrbitStore } from "@withorbit/store-shared"; 2 | import OrbitStoreWeb from "@withorbit/store-web"; 3 | 4 | export async function createOrbitStore( 5 | databaseName: string, 6 | ): Promise { 7 | return new OrbitStoreWeb({ databaseName }); 8 | } 9 | 10 | export async function createDefaultOrbitStore(): Promise { 11 | return createOrbitStore("shared.orbitStore"); 12 | } 13 | -------------------------------------------------------------------------------- /packages/app/src/reviewSession/LoadingScreen.tsx: -------------------------------------------------------------------------------- 1 | import { styles } from "@withorbit/ui"; 2 | import React from "react"; 3 | import { ActivityIndicator, View } from "react-native"; 4 | 5 | export function LoadingScreen() { 6 | return ( 7 | 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/app/src/util/firebase.ts: -------------------------------------------------------------------------------- 1 | import { FirebaseApp, initializeApp } from "firebase/app"; 2 | 3 | let _app: FirebaseApp | null; 4 | export function getDefaultFirebaseApp(): FirebaseApp { 5 | if (!_app) { 6 | _app = initializeApp({ 7 | apiKey: "AIzaSyAwlVFBlx4D3s3eSrwOvUyqOKr_DXFmj0c", 8 | authDomain: "metabook-system.firebaseapp.com", 9 | databaseURL: "https://metabook-system.firebaseio.com", 10 | projectId: "metabook-system", 11 | storageBucket: "metabook-system.appspot.com", 12 | messagingSenderId: "748053153064", 13 | appId: "1:748053153064:web:efc2dfbc9ac11d8512bc1d", 14 | }); 15 | } 16 | return _app; 17 | } 18 | -------------------------------------------------------------------------------- /packages/app/src/util/firebaseAuth.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore https://github.com/firebase/firebase-js-sdk/issues/7584 2 | import { getReactNativePersistence } from "@firebase/auth/dist/rn/index.js"; 3 | import { Auth, connectAuthEmulator, initializeAuth } from "firebase/auth"; 4 | import ReactNativeAsyncStorage from "@react-native-async-storage/async-storage"; 5 | import serviceConfig from "../../serviceConfig.js"; 6 | import { getDefaultFirebaseApp } from "./firebase.js"; 7 | 8 | let _auth: Auth | null = null; 9 | export function getFirebaseAuth(): Auth { 10 | if (!_auth) { 11 | _auth = initializeAuth(getDefaultFirebaseApp(), { 12 | persistence: getReactNativePersistence(ReactNativeAsyncStorage), 13 | }); 14 | if (__DEV__ && serviceConfig.shouldUseLocalBackend) { 15 | connectAuthEmulator(_auth, "http://localhost:9099/"); 16 | } 17 | } 18 | return _auth; 19 | } 20 | -------------------------------------------------------------------------------- /packages/app/src/util/firebaseAuth.web.ts: -------------------------------------------------------------------------------- 1 | import { Auth, connectAuthEmulator, getAuth } from "firebase/auth"; 2 | import serviceConfig from "../../serviceConfig.js"; 3 | import { getDefaultFirebaseApp } from "./firebase.js"; 4 | 5 | let _auth: Auth | null = null; 6 | export function getFirebaseAuth(): Auth { 7 | if (!_auth) { 8 | _auth = getAuth(getDefaultFirebaseApp()); 9 | if (__DEV__ && serviceConfig.shouldUseLocalBackend) { 10 | connectAuthEmulator(_auth, "http://localhost:9099/"); 11 | } 12 | } 13 | return _auth; 14 | } 15 | -------------------------------------------------------------------------------- /packages/app/src/util/intents/IntentHandler.ts: -------------------------------------------------------------------------------- 1 | import { NativeEventEmitter, NativeModules } from "react-native"; 2 | import { 3 | handleIngestEventWithDefaultStore, 4 | IngestEventEmitterType, 5 | } from "./handleIngestEvent.js"; 6 | 7 | const { IngestEventEmitter } = NativeModules as { 8 | IngestEventEmitter: IngestEventEmitterType; 9 | }; 10 | 11 | const eventEmitter = new NativeEventEmitter(IngestEventEmitter); 12 | 13 | export function initIntentHandlers() { 14 | eventEmitter.addListener( 15 | "onIngestEvent", 16 | handleIngestEventWithDefaultStore(IngestEventEmitter), 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/app/src/util/intents/IntentHandler.web.ts: -------------------------------------------------------------------------------- 1 | export function initIntentHandlers() { 2 | // no-op on web 3 | } 4 | -------------------------------------------------------------------------------- /packages/app/src/util/shims.ts: -------------------------------------------------------------------------------- 1 | import { getRandomValues, randomUUID } from "expo-crypto"; 2 | // @ts-ignore 3 | global.crypto ||= {}; 4 | // @ts-ignore 5 | global.crypto.getRandomValues = getRandomValues; 6 | // @ts-ignore 7 | global.crypto.randomUUID = randomUUID; 8 | 9 | import { shim as shimBase64 } from "react-native-quick-base64"; 10 | shimBase64(); // add btoa to globals for @withorbit/core 11 | -------------------------------------------------------------------------------- /packages/app/src/util/shims.web.ts: -------------------------------------------------------------------------------- 1 | // no-op 2 | -------------------------------------------------------------------------------- /packages/app/src/util/useAPIClient.tsx: -------------------------------------------------------------------------------- 1 | import OrbitAPIClient from "@withorbit/api-client"; 2 | import React from "react"; 3 | import serviceConfig from "../../serviceConfig.js"; 4 | import { AuthenticationClient } from "../authentication/index.js"; 5 | 6 | export function useAPIClient( 7 | authenticationClient: AuthenticationClient, 8 | ): OrbitAPIClient { 9 | return React.useMemo( 10 | () => 11 | new OrbitAPIClient( 12 | async () => ({ 13 | idToken: (await authenticationClient.getCurrentIDToken()) as string, 14 | }), 15 | { baseURL: serviceConfig.httpsAPIBaseURLString }, 16 | ), 17 | [authenticationClient], 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /packages/app/src/util/useAsyncResult.ts: -------------------------------------------------------------------------------- 1 | import { useWeakRef } from "@withorbit/ui"; 2 | import React from "react"; 3 | 4 | export function useAsyncResult(initializer: () => Promise): T | null { 5 | const [result, setResult] = React.useState(null); 6 | const isCancelled = React.useRef(false); 7 | 8 | // We don't re-run the initializer if it changes. 9 | const weakInitializer = useWeakRef(initializer); 10 | React.useEffect(() => { 11 | weakInitializer.current().then((result) => { 12 | if (!isCancelled.current) { 13 | setResult(result); 14 | } 15 | }); 16 | 17 | return () => { 18 | isCancelled.current = true; 19 | }; 20 | }, [weakInitializer]); 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /packages/app/src/util/useByrefCallback.ts: -------------------------------------------------------------------------------- 1 | import { useWeakRef } from "@withorbit/ui"; 2 | import { useCallback } from "react"; 3 | 4 | // Returns a fixed function reference which calls the most recent value of `callback`. Useful for avoiding excess dependencies or recomputations in React hooks around callbacks. 5 | export default function useByrefCallback( 6 | callback: (...args: Args) => Result, 7 | ): (...args: Args) => Result { 8 | const callbackRef = useWeakRef(callback); 9 | return useCallback( 10 | (...args: Args) => { 11 | return callbackRef.current(...args); 12 | }, 13 | [callbackRef], 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /packages/app/src/util/usePageViewTracking.ts: -------------------------------------------------------------------------------- 1 | export default function usePageViewTracking() { 2 | // Only implemented for web. 3 | return; 4 | } 5 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/app/targets/widgets/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/WidgetBackground.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/check-center.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "check-center.svg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | }, 21 | "properties" : { 22 | "template-rendering-intent" : "template" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/check-center.imageset/check-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/cross-center.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "cross-center.svg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | }, 21 | "properties" : { 22 | "template-rendering-intent" : "template" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/reveal-accent-center.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "reveal-accent-center.svg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | }, 21 | "properties" : { 22 | "template-rendering-intent" : "template" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/reveal-accent-center.imageset/reveal-accent-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/reveal-center.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "reveal-center.svg", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | }, 21 | "properties" : { 22 | "template-rendering-intent" : "template" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/Assets.xcassets/reveal-center.imageset/reveal-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/OrbitWidgetBundle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OrbitWidgetBundle.swift 3 | // OrbitWidget 4 | // 5 | // Created by Andy Matuschak on 2024-06-26. 6 | // 7 | 8 | import SwiftUI 9 | import WidgetKit 10 | 11 | @main 12 | struct OrbitWidgetBundle: WidgetBundle { 13 | var body: some Widget { 14 | OrbitHomeScreen() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/expo-target.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "widget", 3 | "name": "OrbitWidget", 4 | "icon": "../../app-assets/starburst-icon.png", 5 | "entitlements": { 6 | "com.apple.security.application-groups": ["group.com.withorbit.native"] 7 | }, 8 | "deploymentTarget": "18.0" 9 | } 10 | -------------------------------------------------------------------------------- /packages/app/targets/widgets/generated.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.withorbit.native 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /packages/backend/.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "metabook-system" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/backend/.gitignore: -------------------------------------------------------------------------------- 1 | .runtimeconfig.json 2 | -------------------------------------------------------------------------------- /packages/backend/LICENSE: -------------------------------------------------------------------------------- 1 | AGPL-3.0-or-later OR BUSL-1.1 2 | -------------------------------------------------------------------------------- /packages/backend/babel.config.cjs: -------------------------------------------------------------------------------- 1 | // babel.config.js 2 | module.exports = { 3 | presets: [ 4 | [ 5 | "@babel/preset-env", 6 | { 7 | targets: { 8 | node: "current", 9 | }, 10 | }, 11 | ], 12 | "@babel/preset-typescript", 13 | ], 14 | plugins: [ 15 | [ 16 | "@babel/plugin-syntax-import-attributes", 17 | // TODO remove when we move to Node 22 and update import assert to import with 18 | { deprecatedAssertSyntax: true }, 19 | ], 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /packages/backend/bigQuerySchemas/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "mode": "REQUIRED", 4 | "name": "userID", 5 | "type": "STRING" 6 | }, 7 | { 8 | "mode": "REQUIRED", 9 | "name": "id", 10 | "type": "STRING" 11 | }, 12 | { 13 | "mode": "REQUIRED", 14 | "name": "entityID", 15 | "type": "STRING" 16 | }, 17 | { 18 | "mode": "REQUIRED", 19 | "name": "type", 20 | "type": "STRING" 21 | }, 22 | { 23 | "mode": "REQUIRED", 24 | "name": "timestamp", 25 | "type": "TIMESTAMP" 26 | }, 27 | { 28 | "mode": "REQUIRED", 29 | "name": "dataJSON", 30 | "type": "STRING" 31 | }, 32 | { 33 | "mode": "REQUIRED", 34 | "name": "entityJSON", 35 | "type": "STRING" 36 | } 37 | ] 38 | -------------------------------------------------------------------------------- /packages/backend/bigQuerySchemas/userEvents.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "mode": "REQUIRED", 4 | "name": "timestamp", 5 | "type": "TIMESTAMP" 6 | }, 7 | { 8 | "mode": "REQUIRED", 9 | "name": "userID", 10 | "type": "STRING" 11 | }, 12 | { 13 | "mode": "REQUIRED", 14 | "name": "eventName", 15 | "type": "STRING" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /packages/backend/emulator-data/auth_export/accounts.json: -------------------------------------------------------------------------------- 1 | {"kind":"identitytoolkit#DownloadAccountResponse","users":[{"localId":"WvLvv9uDtFha1jVTyxObVl00gPFN","createdAt":"1615510792970","lastLoginAt":"1615510792970","displayName":"Test User","photoUrl":"","emailVerified":false,"email":"test@test.com","salt":"fakeSaltUStXd0I6orYCUZTjBL7d","passwordHash":"fakeHash:salt=fakeSaltUStXd0I6orYCUZTjBL7d:password=testtest","passwordUpdatedAt":1615510792970,"validSince":"1615510792","providerUserInfo":[{"providerId":"password","email":"test@test.com","federatedId":"test@test.com","rawId":"test@test.com","displayName":"Test User","photoUrl":""}]}]} -------------------------------------------------------------------------------- /packages/backend/emulator-data/auth_export/config.json: -------------------------------------------------------------------------------- 1 | {"signIn":{"allowDuplicateEmails":false}} -------------------------------------------------------------------------------- /packages/backend/emulator-data/firebase-export-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "9.6.1", 3 | "firestore": { 4 | "version": "1.11.12", 5 | "path": "firestore_export", 6 | "metadata_file": "firestore_export/firestore_export.overall_export_metadata" 7 | }, 8 | "auth": { 9 | "version": "9.6.1", 10 | "path": "auth_export" 11 | } 12 | } -------------------------------------------------------------------------------- /packages/backend/emulator-data/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/backend/emulator-data/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata -------------------------------------------------------------------------------- /packages/backend/emulator-data/firestore_export/all_namespaces/all_kinds/output-0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/backend/emulator-data/firestore_export/all_namespaces/all_kinds/output-0 -------------------------------------------------------------------------------- /packages/backend/emulator-data/firestore_export/firestore_export.overall_export_metadata: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/backend/emulator-data/firestore_export/firestore_export.overall_export_metadata -------------------------------------------------------------------------------- /packages/backend/firebase-storage-cors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "origin": ["*"], 4 | "method": ["GET"], 5 | "maxAgeSeconds": 3600 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /packages/backend/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "firestore": { 3 | "rules": "firestore.rules", 4 | "indexes": "firestore.indexes.json" 5 | }, 6 | "functions": { 7 | "source": "." 8 | }, 9 | "emulators": { 10 | "firestore": { 11 | "port": 8080 12 | }, 13 | "auth": { 14 | "port": 9099 15 | }, 16 | "functions": { 17 | "port": 5001 18 | }, 19 | "pubsub": { 20 | "port": 8085 21 | }, 22 | "storage": { 23 | "port": 9199 24 | }, 25 | "ui": { 26 | "enabled": true 27 | } 28 | }, 29 | "storage": { 30 | "rules": "storage.rules" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/backend/firestore.indexes.json: -------------------------------------------------------------------------------- 1 | { 2 | "indexes": [ 3 | { 4 | "collectionGroup": "taskStates", 5 | "queryScope": "COLLECTION", 6 | "fields": [ 7 | { 8 | "fieldPath": "taskMetadata.isDeleted", 9 | "order": "ASCENDING" 10 | }, 11 | { 12 | "fieldPath": "dueTimestampMillis", 13 | "order": "ASCENDING" 14 | } 15 | ] 16 | } 17 | ], 18 | "fieldOverrides": [] 19 | } 20 | -------------------------------------------------------------------------------- /packages/backend/firestore.rules: -------------------------------------------------------------------------------- 1 | service cloud.firestore { 2 | match /databases/{database}/documents { 3 | match /data/{document=**} { 4 | allow read; 5 | } 6 | match /users/{user} { 7 | match /{document=**} { 8 | allow read, write: if request.auth != null && (request.auth.uid == user || (request.auth.token != null && "admin" in request.auth.token && request.auth.token.admin == true)); 9 | } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /packages/backend/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | globals: { 3 | Uint8Array: Uint8Array, // use Node's implementation; https://github.com/facebook/jest/issues/4422 4 | }, 5 | moduleNameMapper: { 6 | "^(\\.{1,2}/.*)\\.js$": "$1", 7 | }, 8 | testEnvironment: "node", 9 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 10 | testPathIgnorePatterns: ["dist", "node_modules"], 11 | transformIgnorePatterns: ["is-typedarray"], 12 | }; 13 | -------------------------------------------------------------------------------- /packages/backend/scripts/deployShared.js: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | 3 | export const packageRoot = path.join(import.meta.dir, ".."); 4 | export const firebaseJSONPath = path.join(packageRoot, "firebase.json"); 5 | export const isolatedFolderName = "isolate"; 6 | export const isolatedPath = path.join(packageRoot, isolatedFolderName); 7 | -------------------------------------------------------------------------------- /packages/backend/scripts/postdeploy.js: -------------------------------------------------------------------------------- 1 | // See predeploy.js for more details. 2 | import fs from "fs"; 3 | import { firebaseJSONPath, isolatedPath } from "./deployShared.js"; 4 | import { execSync } from "child_process"; 5 | 6 | // Restore the firebase configuration file. 7 | fs.renameSync(`${firebaseJSONPath}.bak`, firebaseJSONPath); 8 | 9 | // We also need to remove the isolated package directory. 10 | fs.rmSync(isolatedPath, { recursive: true, force: true }); 11 | 12 | // Git status should be clean again. 13 | const gitStatus = execSync("git status --porcelain").toString(); 14 | if (gitStatus !== "") { 15 | throw new Error( 16 | "git status is not clean after cleaning up deployment... unexpected!", 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/backend/src/@types/isbot-fast/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "isbot-fast" { 2 | function isBot(userAgent: string): boolean; 3 | export default isBot; 4 | } 5 | -------------------------------------------------------------------------------- /packages/backend/src/__tests__/emulators.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import { LocalFileStorageService } from "../fileStorageService/localFileStorageService.js"; 3 | import { clearFirestoreData } from "./firebaseTesting.js"; 4 | 5 | export async function resetLocalEmulators() { 6 | await clearFirestoreData(); 7 | await resetLocalFileServiceData(); 8 | } 9 | 10 | export async function resetLocalFileServiceData() { 11 | await fs.promises 12 | .rm(LocalFileStorageService.getTestStorageLocation(), { 13 | recursive: true, 14 | force: true, 15 | }) 16 | .catch(() => { 17 | return; 18 | }); // it's OK if this fails: it might not exist yet. 19 | await fs.promises.mkdir(LocalFileStorageService.getTestStorageLocation(), { 20 | recursive: true, 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /packages/backend/src/api/internal/auth/consumeAccessCode.ts: -------------------------------------------------------------------------------- 1 | import { sharedServerDatabase } from "../../../db/index.js"; 2 | import { InternalAPISpec } from "../../internalSpec.js"; 3 | import { authenticatedRequestHandler } from "../../util/authenticateRequest.js"; 4 | import { CachePolicy, TypedRouteHandler } from "../../util/typedRouter.js"; 5 | 6 | export const consumeAccessCode: TypedRouteHandler< 7 | InternalAPISpec, 8 | "/internal/auth/consumeAccessCode", 9 | "GET" 10 | > = authenticatedRequestHandler(async (request, userID) => { 11 | const loginToken = 12 | await sharedServerDatabase().auth.createCustomLoginToken(userID); 13 | 14 | return { 15 | status: 200, 16 | text: loginToken, 17 | cachePolicy: CachePolicy.NoStore, 18 | }; 19 | }); 20 | -------------------------------------------------------------------------------- /packages/backend/src/api/internal/auth/personalAccessTokens.ts: -------------------------------------------------------------------------------- 1 | import { sharedServerDatabase } from "../../../db/index.js"; 2 | import { InternalAPISpec } from "../../internalSpec.js"; 3 | import { authenticatedRequestHandler } from "../../util/authenticateRequest.js"; 4 | import { CachePolicy, TypedRouteHandler } from "../../util/typedRouter.js"; 5 | 6 | export const personalAccessTokens: TypedRouteHandler< 7 | InternalAPISpec, 8 | "/internal/auth/personalAccessTokens", 9 | "POST" 10 | > = authenticatedRequestHandler(async (request, userID) => { 11 | const token = 12 | await sharedServerDatabase().auth.createPersonalAccessToken(userID); 13 | return { 14 | status: 200, 15 | cachePolicy: CachePolicy.NoStore, 16 | json: { 17 | token, 18 | }, 19 | }; 20 | }); 21 | -------------------------------------------------------------------------------- /packages/backend/src/api/internal/auth/sessionCookie.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | 3 | export const sessionCookieName = "__session"; // mandated by Firebase hosting, c.f. https://firebase.google.com/docs/hosting/manage-cache#using_cookies 4 | export function getSessionCookieOptions( 5 | expirationDate: Date, 6 | ): express.CookieOptions { 7 | return { 8 | domain: "withorbit.com", 9 | path: "/", 10 | secure: true, 11 | httpOnly: true, 12 | sameSite: "none", // Our use in an embedded context requires a "none" same-site setting, since these are considered "unsafe" requests. 13 | expires: expirationDate, 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /packages/backend/src/api/internalSpec.ts: -------------------------------------------------------------------------------- 1 | export type InternalAPISpec = { 2 | "/internal/auth/consumeAccessCode": { 3 | GET: { 4 | response: string; 5 | }; 6 | }; 7 | "/internal/auth/personalAccessTokens": { 8 | POST: { 9 | response: { token: string }; 10 | }; 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /packages/backend/src/api/util/corsHandler.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cors from "cors"; 3 | 4 | const corsHandler: express.RequestHandler = cors({ 5 | origin: [ 6 | /\.withorbit.com$/, 7 | /^https?:\/\/localhost(:\d+)?$/, 8 | // HACK for fall 2022 prototype 9 | "https://orbit-app--fall-2022-yzhqe6jr.web.app", 10 | "https://orbit-mk.vercel.app", 11 | ], 12 | }); 13 | export default corsHandler; 14 | -------------------------------------------------------------------------------- /packages/backend/src/api/util/putAndLogEvents.ts: -------------------------------------------------------------------------------- 1 | import { Event } from "@withorbit/core"; 2 | import { sharedServerDatabase } from "../../db/index.js"; 3 | import { sharedLoggingService } from "../../logging/index.js"; 4 | 5 | export async function putAndLogEvents( 6 | userID: string, 7 | events: Event[], 8 | ): Promise { 9 | const db = sharedServerDatabase().getUserDatabase(userID); 10 | const eventRecords = await db.putEvents(events); 11 | 12 | for (const { event, entity } of eventRecords) { 13 | sharedLoggingService.logEvent({ 14 | userID, 15 | event, 16 | entity, 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/backend/src/db/firestore.ts: -------------------------------------------------------------------------------- 1 | import { getFirestore } from "firebase-admin/firestore"; 2 | import type { Firestore } from "firebase-admin/firestore"; 3 | import { getApp } from "../firebaseApp.js"; 4 | 5 | let _database: Firestore | null = null; 6 | 7 | export function getDatabase(): Firestore { 8 | if (!_database) { 9 | _database = getFirestore(getApp()); 10 | } 11 | return _database; 12 | } 13 | -------------------------------------------------------------------------------- /packages/backend/src/db/userMetadata.ts: -------------------------------------------------------------------------------- 1 | export interface UserMetadata { 2 | registrationTimestampMillis: number; 3 | activeTaskCount?: number; 4 | 5 | sessionNotificationState?: SessionNotificationState; 6 | isUnsubscribedFromSessionNotifications?: boolean; 7 | snoozeSessionNotificationsUntilTimestampMillis?: number; 8 | 9 | coreMigrationTimestampMillis?: number; 10 | } 11 | 12 | export interface SessionNotificationState { 13 | firstNotificationTimestampMillis: number; 14 | lastNotificationTimestampMillis: number; 15 | sentNotificationCount: number; 16 | } 17 | -------------------------------------------------------------------------------- /packages/backend/src/db/withFirebaseFields.ts: -------------------------------------------------------------------------------- 1 | import { FieldValue } from "firebase-admin/firestore"; 2 | 3 | export type WithFirebaseFields = { 4 | [K in keyof T]: 5 | | T[K] 6 | | (T[K] extends Record 7 | ? WithFirebaseFields 8 | : FieldValue); 9 | }; 10 | -------------------------------------------------------------------------------- /packages/backend/src/email/dummy.ts: -------------------------------------------------------------------------------- 1 | import { EmailService, EmailSpec } from "./types.js"; 2 | 3 | export const dummyEmailService: EmailService = { 4 | async sendEmail( 5 | recipientEmailAddress: string, 6 | spec: EmailSpec, 7 | ): Promise { 8 | console.log(`[Email service]: 9 | To: ${recipientEmailAddress} 10 | Subject: ${spec.subject} 11 | Plaintext: 12 | ${spec.text} 13 | 14 | HTML: 15 | ${spec.html} 16 | 17 | =========`); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/backend/src/email/index.ts: -------------------------------------------------------------------------------- 1 | import serviceConfig from "../serviceConfig.js"; 2 | import { isRunningInEmulator } from "../util/isRunningInEmulator.js"; 3 | import { dummyEmailService } from "./dummy.js"; 4 | import MailjetEmailService from "./mailjet.js"; 5 | import { EmailService } from "./types.js"; 6 | 7 | let _sharedEmailService: EmailService | null = null; 8 | export default function getDefaultEmailService(): EmailService { 9 | if (!_sharedEmailService) { 10 | _sharedEmailService = isRunningInEmulator 11 | ? dummyEmailService 12 | : new MailjetEmailService( 13 | serviceConfig.mailjet.apiKey, 14 | serviceConfig.mailjet.secretKey, 15 | ); 16 | } 17 | return _sharedEmailService; 18 | } 19 | -------------------------------------------------------------------------------- /packages/backend/src/email/types.ts: -------------------------------------------------------------------------------- 1 | export interface EmailService { 2 | sendEmail(recipientEmailAddress: string, spec: EmailSpec): Promise; 3 | } 4 | 5 | export interface EmailSpec { 6 | subject: string; 7 | text: string; 8 | html?: string; 9 | } 10 | -------------------------------------------------------------------------------- /packages/backend/src/fileStorageService/fileStorageService.ts: -------------------------------------------------------------------------------- 1 | export interface FileStorageService { 2 | fileExists(subpath: string): Promise; 3 | storeFile(subpath: string, data: Uint8Array, mimeType: string): Promise; 4 | formatURL(subpath: string): string; 5 | resolveFile(subpath: string): Promise; 6 | getMIMEType(subpath: string): Promise; 7 | copyFile(fromSubpath: string, toSubpath: string): Promise; 8 | } 9 | 10 | export type FileStorageResolution = { data: Uint8Array; mimeType: string }; 11 | -------------------------------------------------------------------------------- /packages/backend/src/fileStorageService/index.ts: -------------------------------------------------------------------------------- 1 | import { FileStorageService } from "./fileStorageService.js"; 2 | import { GoogleCloudFileStorageService } from "./googleCloudFileStorageService.js"; 3 | 4 | let _sharedFileStorageService: FileStorageService | null; 5 | export function sharedFileStorageService(): FileStorageService { 6 | if (!_sharedFileStorageService) { 7 | _sharedFileStorageService = new GoogleCloudFileStorageService(); 8 | } 9 | return _sharedFileStorageService; 10 | } 11 | -------------------------------------------------------------------------------- /packages/backend/src/firebaseApp.ts: -------------------------------------------------------------------------------- 1 | import { App, initializeApp } from "firebase-admin/app"; 2 | 3 | let _app: App | null = null; 4 | export function getApp(): App { 5 | if (!_app) { 6 | _app = initializeApp(); 7 | } 8 | return _app; 9 | } 10 | -------------------------------------------------------------------------------- /packages/backend/src/firebaseFunctions/api.ts: -------------------------------------------------------------------------------- 1 | import functions from "firebase-functions"; 2 | import { createAPIApp } from "../api.js"; 3 | 4 | export const api = functions 5 | .runWith({ memory: "1GB" }) 6 | .https.onRequest(createAPIApp()); 7 | -------------------------------------------------------------------------------- /packages/backend/src/firebaseFunctions/notifier/index.ts: -------------------------------------------------------------------------------- 1 | export { notificationScheduler } from "./notificationScheduler.js"; 2 | export { processUserNotificationSubscriber } from "./processUserNotificationSubscriber.js"; 3 | -------------------------------------------------------------------------------- /packages/backend/src/index.ts: -------------------------------------------------------------------------------- 1 | // Each function exported by this module corresponds to a Firebase cloud function. Firebase will provision cloud functions accordingly. 2 | export { default as onUserCreate } from "./firebaseFunctions/onUserCreate.js"; 3 | export { updateNotificationSettings } from "./firebaseFunctions/updateNotificationSettings.js"; 4 | 5 | export { api } from "./firebaseFunctions/api.js"; 6 | 7 | export * from "./firebaseFunctions/notifier/index.js"; 8 | -------------------------------------------------------------------------------- /packages/backend/src/logging/dummy.ts: -------------------------------------------------------------------------------- 1 | import { LoggingService } from "./interface.js"; 2 | 3 | function createTracer(name: string) { 4 | return (...args: unknown[]) => { 5 | console.log("[Logging service]: ", name, ...args); 6 | }; 7 | } 8 | 9 | export const dummyLoggingService = new Proxy( 10 | {}, 11 | { 12 | get: function (_target, prop) { 13 | return createTracer(prop.toString()); 14 | }, 15 | }, 16 | ) as LoggingService; 17 | -------------------------------------------------------------------------------- /packages/backend/src/logging/index.ts: -------------------------------------------------------------------------------- 1 | import { isRunningInEmulator } from "../util/isRunningInEmulator.js"; 2 | import { bigQueryLoggingService } from "./bigQuery.js"; 3 | import { dummyLoggingService } from "./dummy.js"; 4 | import { LoggingService } from "./interface.js"; 5 | 6 | let sharedLoggingService: LoggingService = isRunningInEmulator 7 | ? dummyLoggingService 8 | : bigQueryLoggingService; 9 | export { sharedLoggingService }; 10 | 11 | // i.e. for tests 12 | export function _overrideSharedLoggingService(loggingService: LoggingService) { 13 | sharedLoggingService = loggingService; 14 | } 15 | -------------------------------------------------------------------------------- /packages/backend/src/notifications/__fixtures__/generateDueTasks.ts: -------------------------------------------------------------------------------- 1 | import { generateUniqueID, Task } from "@withorbit/core"; 2 | import { createTestTask } from "@withorbit/sample-data"; 3 | import * as dateFns from "date-fns"; 4 | 5 | export function generateDueTasks( 6 | baseTimestampMillis: number, 7 | count: number, 8 | dueInDays: number, 9 | intervalDays: number, 10 | ): Task[] { 11 | const output: Task[] = []; 12 | for (let i = 0; i < count; i++) { 13 | output.push( 14 | createTestTask({ 15 | id: generateUniqueID(), 16 | dueTimestampMillis: dateFns 17 | .addDays(baseTimestampMillis, dueInDays) 18 | .valueOf(), 19 | intervalMillis: intervalDays * 1000 * 60 * 60 * 24, 20 | }), 21 | ); 22 | } 23 | return output; 24 | } 25 | -------------------------------------------------------------------------------- /packages/backend/src/notifications/index.ts: -------------------------------------------------------------------------------- 1 | export { processUserNotification } from "./processUserNotification.js"; 2 | -------------------------------------------------------------------------------- /packages/backend/src/util/isRunningInEmulator.ts: -------------------------------------------------------------------------------- 1 | export const isRunningInEmulator = !!process.env.FUNCTIONS_EMULATOR; 2 | -------------------------------------------------------------------------------- /packages/backend/src/util/isRunningInTest.ts: -------------------------------------------------------------------------------- 1 | export const isRunningInTest = process.env.JEST_WORKER_ID !== undefined; 2 | -------------------------------------------------------------------------------- /packages/backend/storage.rules: -------------------------------------------------------------------------------- 1 | rules_version = '2'; 2 | service firebase.storage { 3 | match /b/{bucket}/o { 4 | match /{allPaths=**} { 5 | // All access through admin SDK via APIs 6 | allow read, write: if false; 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "baseUrl": "./src", 5 | "outDir": "./dist", 6 | "rootDir": "./src", 7 | "lib": ["dom", "es2019"], 8 | "types": ["jest", "node"], 9 | "target": "es2019" 10 | }, 11 | "include": ["src/**/*"], 12 | "references": [ 13 | { 14 | "path": "../core" 15 | }, 16 | { 17 | "path": "../sample-data" 18 | }, 19 | { 20 | "path": "../api" 21 | }, 22 | { 23 | "path": "../store-shared" 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/core 2 | 3 | This package defines Orbit's core data structures, like `Event` and `Task`. It also defines some convenience functionality used by many other components. 4 | 5 | To support offline-first workflows, Orbit is built using an event sourcing model, meaning that events (like "remembered this task") are the source of truth. These events are combined with an "event reducer" to compute the state of an object at any given time. 6 | 7 | This package runs on Node.js, browser, and React Native environments. 8 | 9 | * To build: `bun run build` 10 | * To run tests: `bun run test` 11 | 12 | ``` 13 | Copyright 2020 Andy Matuschak 14 | SPDX-License-Identifier: Apache-2.0 15 | ``` 16 | -------------------------------------------------------------------------------- /packages/core/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /packages/core/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@withorbit/core", 3 | "version": "0.0.1", 4 | "license": "Apache-2.0", 5 | "private": true, 6 | "type": "module", 7 | "main": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": "./dist/index.js", 10 | "files": [ 11 | "dist" 12 | ], 13 | "sideEffects": false, 14 | "scripts": { 15 | "build": "tsc -b", 16 | "test": "jest" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.14.6", 20 | "@babel/preset-env": "^7.14.7", 21 | "@babel/preset-typescript": "^7.14.5", 22 | "@types/jest": "^29.5.5", 23 | "@types/node": "^20.10.4", 24 | "babel-jest": "^29.7.0", 25 | "jest": "^29.7.0", 26 | "typescript": "^5.3.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/src/colorPaletteName.ts: -------------------------------------------------------------------------------- 1 | // A bit awkward: these definitions are "really" in @withorbit/ui, but we don't want @withorbit/core to depend on @withorbit/ui. So we define just the names as a type here, and use a type constraint to make sure that the definitions in @withorbit/ui don't differ from this. 2 | export type ColorPaletteName = 3 | | "red" 4 | | "orange" 5 | | "brown" 6 | | "yellow" 7 | | "lime" 8 | | "green" 9 | | "turquoise" 10 | | "cyan" 11 | | "blue" 12 | | "violet" 13 | | "purple" 14 | | "pink"; 15 | -------------------------------------------------------------------------------- /packages/core/src/eventReducers/attachmentReducers.ts: -------------------------------------------------------------------------------- 1 | import { AttachmentReference } from "../entities/attachmentReference.js"; 2 | import { EntityType } from "../entity.js"; 3 | import { AttachmentIngestEvent } from "../event.js"; 4 | 5 | export function attachmentIngestEventReducer( 6 | oldAttachment: AttachmentReference | null, 7 | event: AttachmentIngestEvent, 8 | ): AttachmentReference { 9 | if (oldAttachment) { 10 | return oldAttachment; 11 | } else { 12 | return { 13 | id: event.entityID, 14 | createdAtTimestampMillis: event.timestampMillis, 15 | type: EntityType.AttachmentReference, 16 | mimeType: event.mimeType, 17 | }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/core/src/generateUniqueID.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | encodeUUIDBytesToWebSafeBase64ID, 3 | generateUniqueID, 4 | } from "./generateUniqueID.js"; 5 | 6 | test("matches expected pattern", () => { 7 | expect(generateUniqueID().match(/^[0-9a-zA-Z_\-]{22}$/)).toBeTruthy(); 8 | }); 9 | 10 | test("different each time", () => { 11 | expect(generateUniqueID()).not.toEqual(generateUniqueID()); 12 | }); 13 | 14 | test("stable output", () => { 15 | const bytes = Uint8Array.from([ 16 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17 | ]); 18 | const id = encodeUUIDBytesToWebSafeBase64ID(bytes); 19 | expect(id).toMatchInlineSnapshot(`"AAECAwQFBgcICQoLDA0ODw"`); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { ColorPaletteName } from "./colorPaletteName.js"; 2 | export * from "./entity.js"; 3 | export * from "./event.js"; 4 | export * from "./entities/task.js"; 5 | export * from "./entities/attachmentReference.js"; 6 | export * from "./eventReducer.js"; 7 | export * from "./generateUniqueID.js"; 8 | export * from "./reviewQueue.js"; 9 | export * from "./schedulers/spacedRepetitionScheduler.js"; 10 | -------------------------------------------------------------------------------- /packages/core/src/scheduler.ts: -------------------------------------------------------------------------------- 1 | import { TaskComponentState } from "./entities/task.js"; 2 | import { TaskRepetitionOutcome } from "./event.js"; 3 | 4 | export interface Scheduler { 5 | computeNextDueIntervalMillisForRepetition( 6 | componentState: TaskComponentState, 7 | timestampMillis: number, 8 | outcome: TaskRepetitionOutcome, 9 | ): SchedulerOutput; 10 | } 11 | 12 | export type SchedulerOutput = { 13 | dueTimestampMillis: number; 14 | intervalMillis: number; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/core/src/util/crypto.native.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-namespace, @typescript-eslint/prefer-namespace-keyword 2 | declare module globalThis { 3 | const crypto: WebCrypto; 4 | } 5 | type WebCrypto = typeof import("node:crypto").webcrypto; 6 | 7 | if (!globalThis.crypto?.getRandomValues) { 8 | throw new Error( 9 | "Need to shim crypto.getRandomValues before importing this (e.g. with expo-crypto)", 10 | ); 11 | } 12 | if (!globalThis.crypto?.randomUUID) { 13 | throw new Error( 14 | "Need to shim crypto.randomUUID before importing this (e.g. with expo-crypto)", 15 | ); 16 | } 17 | 18 | const getRandomValues = globalThis.crypto.getRandomValues; 19 | const randomUUID = globalThis.crypto.randomUUID; 20 | export const crypto = { getRandomValues, randomUUID }; 21 | -------------------------------------------------------------------------------- /packages/core/src/util/crypto.ts: -------------------------------------------------------------------------------- 1 | export { webcrypto as crypto } from "node:crypto"; 2 | -------------------------------------------------------------------------------- /packages/core/src/util/crypto.web.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | export const crypto = globalThis.crypto; 4 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["./src/**/*.ts", "./@types/**/*.d.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/docs/.firebaserc: -------------------------------------------------------------------------------- 1 | ../app/.firebaserc -------------------------------------------------------------------------------- /packages/docs/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/docs 2 | 3 | Source for [Orbit's documentation site](https://docs.withorbit.com). 4 | 5 | To deploy, run: `yarn deploy`. 6 | 7 | ``` 8 | Copyright 2020 Andy Matuschak 9 | SPDX-License-Identifier: Apache-2.0 10 | ``` 11 | -------------------------------------------------------------------------------- /packages/docs/firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "target": "orbit-docs", 4 | "public": ".", 5 | "ignore": ["firebase.json", "**/.*", "**/node_modules/**"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@withorbit/docs", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "deploy": "firebase deploy" 7 | }, 8 | "devDependencies": { 9 | "firebase-tools": "^13.0.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/docs/test.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/docs/test.html -------------------------------------------------------------------------------- /packages/docs/toffoli.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/docs/toffoli.png -------------------------------------------------------------------------------- /packages/embedded-support/Readme.md: -------------------------------------------------------------------------------- 1 | # embedded-support 2 | 3 | This module contains interfaces and constants used by both `@withorbit/app` and `@withorbit/web-component` to orchestrate the embedded experience. 4 | 5 | ``` 6 | Copyright 2020 Andy Matuschak 7 | SPDX-License-Identifier: Apache-2.0 8 | ``` 9 | -------------------------------------------------------------------------------- /packages/embedded-support/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@withorbit/embedded-support", 3 | "version": "0.0.1", 4 | "type": "module", 5 | "main": "./dist/index.js", 6 | "types": "./dist/index.d.ts", 7 | "private": true, 8 | "scripts": { 9 | "build": "tsc -b" 10 | }, 11 | "dependencies": { 12 | "@withorbit/core": "0.0.1" 13 | }, 14 | "devDependencies": { 15 | "typescript": "^5.3.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/embedded-support/src/embeddedScreenInterface.ts: -------------------------------------------------------------------------------- 1 | import { ColorPaletteName, ReviewItem } from "@withorbit/core"; 2 | 3 | export interface EmbeddedScreenConfiguration { 4 | reviewItems: ReviewItem[]; 5 | // Less than ideal: here AttachmentIDs are keys of a plain old object, but we can't express that in the type (TypeScript will only allow strings and numbers to be keys of indexed types). Normally we'd deal with this by using a Map, but this structure needs to be serialized to/from JSON. 6 | attachmentIDsToURLs: { [AttachmentID: string]: string }; 7 | embeddedHostMetadata: EmbeddedHostMetadata; 8 | sessionStartTimestampMillis: number; 9 | isDebug?: boolean; 10 | } 11 | 12 | export interface EmbeddedHostMetadata { 13 | url: string; 14 | title: string | null; 15 | siteName: string | null; 16 | colorPaletteName: ColorPaletteName | null; 17 | } 18 | -------------------------------------------------------------------------------- /packages/embedded-support/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./embeddedScreenInterface.js"; 2 | export * from "./ipc.js"; 3 | -------------------------------------------------------------------------------- /packages/embedded-support/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/**/*.ts"], 8 | "references": [ 9 | { 10 | "path": "../core" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/ingester/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/ingester 2 | 3 | This package, in conjunction with `@withorbit/interpreter`, lets you import Orbit prompts from some other data source, and to keep your Orbit database in sync with that data source, ingesting missing prompts and deleting deleted ones as necessary. 4 | 5 | `interpreter` is responsible for parsing those data sources and producing a JSON file which describes the prompts embedded within it. This package can then synchronize an Orbit database with the prompts in that file. 6 | 7 | See the documentation in `interpreter` for example and more detail. 8 | 9 | --- 10 | 11 | ``` 12 | Copyright 2023 Andy Matuschak 13 | SPDX-License-Identifier: Apache-2.0 14 | ``` 15 | -------------------------------------------------------------------------------- /packages/ingester/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | plugins: [ 14 | [ 15 | "@babel/plugin-syntax-import-attributes", 16 | // TODO remove when we move to Node 22 and update import assert to import with 17 | { deprecatedAssertSyntax: true }, 18 | ], 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /packages/ingester/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/ingester/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./ingestible.js"; 2 | export * from "./ingest.js"; 3 | export * from "./validateIngestible.js"; 4 | -------------------------------------------------------------------------------- /packages/ingester/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["./src/**/*.ts", "./src/**/*.json"], 9 | "references": [ 10 | { 11 | "path": "../core" 12 | }, 13 | { 14 | "path": "../store-shared" 15 | }, 16 | { 17 | "path": "../store-fs" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/interpreter/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /packages/interpreter/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | transformIgnorePatterns: [], 9 | transform: { 10 | "\\.[jt]s$": ["babel-jest", { cwd: __dirname }], 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/interpreter/src/hasher/hasher.ts: -------------------------------------------------------------------------------- 1 | import { TaskSpec } from "@withorbit/core"; 2 | 3 | export interface Hasher { 4 | hash(spec: TaskSpec): string; 5 | } 6 | -------------------------------------------------------------------------------- /packages/interpreter/src/interpreter.ts: -------------------------------------------------------------------------------- 1 | import { Ingestible } from "@withorbit/ingester"; 2 | 3 | export interface Interpreter { 4 | interpret(files: InterpretableFile[]): Promise; 5 | } 6 | 7 | export type InterpretableFile = { 8 | name: string; 9 | path: string; 10 | content: string; 11 | }; 12 | -------------------------------------------------------------------------------- /packages/interpreter/src/interpreters/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./markdown/MarkdownInterpreter.js"; 2 | -------------------------------------------------------------------------------- /packages/interpreter/src/interpreters/markdown/utils/getNoteTitle.ts: -------------------------------------------------------------------------------- 1 | import mdast from "mdast"; 2 | import { processor } from "../markdown.js"; 3 | 4 | export function getNoteTitle(noteRoot: mdast.Root): string | null { 5 | if (noteRoot.children.length > 0) { 6 | // filter out yaml frontmatter 7 | const firstNode = noteRoot.children.filter((n) => n.type !== "yaml")[0]; 8 | if (firstNode.type === "heading") { 9 | return processor 10 | .stringify({ 11 | type: "root", 12 | children: firstNode.children, 13 | }) 14 | .trimEnd(); 15 | } else { 16 | return processor 17 | .stringify({ type: "root", children: [firstNode] }) 18 | .trimEnd(); 19 | } 20 | } else { 21 | return null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/interpreter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["./src/**/*.ts", "./src/**/*.json"], 9 | "references": [ 10 | { 11 | "path": "../core" 12 | }, 13 | { 14 | "path": "../store-fs" 15 | }, 16 | { 17 | "path": "../ingester" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: "node", 3 | globals: { 4 | Uint8Array: Uint8Array, // use Node's implementation; https://github.com/facebook/jest/issues/4422 5 | }, 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | transformIgnorePatterns: [], 9 | transform: { 10 | "\\.[jt]s$": ["babel-jest", { cwd: __dirname }], 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/sample-data/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/sample-data 2 | 3 | Sample data, mostly meant for use by test harnesses. 4 | 5 | ``` 6 | Copyright 2020 Andy Matuschak 7 | SPDX-License-Identifier: Apache-2.0 8 | ``` 9 | -------------------------------------------------------------------------------- /packages/sample-data/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@withorbit/sample-data", 3 | "version": "0.0.1", 4 | "private": true, 5 | "license": "Apache-2.0", 6 | "type": "module", 7 | "main": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": "./dist/index.js", 10 | "files": [ 11 | "dist" 12 | ], 13 | "dependencies": { 14 | "@withorbit/core": "0.0.1" 15 | }, 16 | "devDependencies": { 17 | "typescript": "^5.3.3" 18 | }, 19 | "scripts": { 20 | "build": "tsc -b" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/sample-data/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./testQASpec.js"; 2 | export * from "./testTasks.js"; 3 | export * from "./testClozeSpec.js"; 4 | -------------------------------------------------------------------------------- /packages/sample-data/src/testClozeSpec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ClozeTaskContent, 3 | MemoryTaskSpec, 4 | TaskContentType, 5 | TaskSpecType, 6 | } from "@withorbit/core"; 7 | 8 | export const testClozeSpec: MemoryTaskSpec = { 9 | type: TaskSpecType.Memory, 10 | content: { 11 | type: TaskContentType.Cloze, 12 | body: { 13 | text: "This is a test cloze prompt.", 14 | attachments: [], 15 | }, 16 | components: { 17 | a: { 18 | order: 0, 19 | ranges: [ 20 | { 21 | startIndex: 5, 22 | length: 5, 23 | hint: null, 24 | }, 25 | ], 26 | }, 27 | b: { 28 | order: 1, 29 | ranges: [ 30 | { 31 | startIndex: 2, 32 | length: 2, 33 | hint: null, 34 | }, 35 | ], 36 | }, 37 | }, 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /packages/sample-data/src/testQASpec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MemoryTaskSpec, 3 | QATaskContent, 4 | TaskContentType, 5 | TaskSpecType, 6 | } from "@withorbit/core"; 7 | 8 | export const testQASpec: MemoryTaskSpec = { 9 | type: TaskSpecType.Memory, 10 | content: { 11 | type: TaskContentType.QA, 12 | body: { 13 | text: "Is it possible to use _quantum teleportation_ to transmit information faster than light?\n\nThis is a **second paragraph** with _**bold italic**_.", 14 | attachments: [], 15 | }, 16 | answer: { 17 | text: "No.", 18 | attachments: [], 19 | }, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /packages/sample-data/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src" 6 | }, 7 | "include": ["./src/**/*.ts"], 8 | "references": [ 9 | { 10 | "path": "../core" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /packages/store-fs/Readme.md: -------------------------------------------------------------------------------- 1 | # `@withorbit/store-fs` 2 | 3 | `OrbitStoreFS` implements an on-disk `OrbitStore` in a standard format: a folder containing a SQLite database (for all events and entities) and a folder of attachments. This folder can be backed up and manipulated locally. 4 | 5 | This library is compatible with Node.js and React Native environments. 6 | 7 | ``` 8 | Copyright 2021 Andy Matuschak 9 | SPDX-License-Identifier: Apache-2.0 10 | ``` 11 | -------------------------------------------------------------------------------- /packages/store-fs/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | plugins: [ 14 | [ 15 | "@babel/plugin-syntax-import-attributes", 16 | // TODO remove when we move to Node 22 and update import assert to import with 17 | { deprecatedAssertSyntax: true }, 18 | ], 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /packages/store-fs/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/store-fs/src/database.test.ts: -------------------------------------------------------------------------------- 1 | import { Database, runDatabaseTests } from "@withorbit/store-shared"; 2 | import { SQLDatabaseBackend } from "./sqlite.js"; 3 | 4 | describe("database tests", () => { 5 | runDatabaseTests("SQLite", async (eventReducer, eventValidator) => { 6 | return new Database( 7 | new SQLDatabaseBackend(SQLDatabaseBackend.inMemoryDBSubpath), 8 | eventReducer, 9 | eventValidator, 10 | ); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/store-fs/src/index.ts: -------------------------------------------------------------------------------- 1 | export { OrbitStoreFS as default } from "./orbitStoreFS.js"; 2 | export { OrbitStoreInMemory } from "./orbitStoreInMemory.js"; 3 | -------------------------------------------------------------------------------- /packages/store-fs/src/orbitStoreInMemory.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AttachmentStore, 3 | Database, 4 | EventReducer, 5 | OrbitStore, 6 | } from "@withorbit/store-shared"; 7 | import { AttachmentStoreFS } from "./attachmentStoreFS.js"; 8 | import { SQLDatabaseBackend } from "./sqlite.js"; 9 | 10 | // An in-memory implementation of OrbitStore, compatible with Node.js and React Native. 11 | export class OrbitStoreInMemory implements OrbitStore { 12 | database: Database; 13 | attachmentStore: AttachmentStore; 14 | 15 | constructor(eventReducer?: EventReducer) { 16 | const sqlDatabaseBackend = new SQLDatabaseBackend( 17 | SQLDatabaseBackend.inMemoryDBSubpath, 18 | { enableDebugLogs: false }, 19 | ); 20 | this.database = new Database(sqlDatabaseBackend, eventReducer); 21 | 22 | this.attachmentStore = new AttachmentStoreFS(sqlDatabaseBackend); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/store-fs/src/sqlite/migrations/20210612111147_createMetadataTable.ts: -------------------------------------------------------------------------------- 1 | import { SQLMigration } from "./migrationType.js"; 2 | 3 | const migration: SQLMigration = { 4 | version: 20210612111147, 5 | statements: [`CREATE TABLE metadata (key TEXT PRIMARY KEY, value TEXT)`], 6 | }; 7 | export default migration; 8 | -------------------------------------------------------------------------------- /packages/store-fs/src/sqlite/migrations/20211019170802_createAttachmentsTable.ts: -------------------------------------------------------------------------------- 1 | import { SQLMigration } from "./migrationType.js"; 2 | 3 | const migration: SQLMigration = { 4 | version: 20211019170802, 5 | statements: [ 6 | ` 7 | CREATE TABLE attachments ( 8 | id TEXT PRIMARY KEY, 9 | data BLOB NOT NULL, 10 | mimeType TEXT NOT NULL 11 | ) 12 | `, 13 | ], 14 | }; 15 | export default migration; 16 | -------------------------------------------------------------------------------- /packages/store-fs/src/sqlite/migrations/index.ts: -------------------------------------------------------------------------------- 1 | import migration_20210612111147_createMetadataTable from "./20210612111147_createMetadataTable.js"; 2 | import migration_20210612112129_initialSchema from "./20210612112129_initialSchema.js"; 3 | import migration_20211019170802_createAttachmentsTable from "./20211019170802_createAttachmentsTable.js"; 4 | import migration_20230726103155_derived_taskComponents_whenNotDeleted from "./20230726103155_derived_taskComponents_whenNotDeleted.js"; 5 | 6 | // Should be sorted by version number. 7 | export const migrations = [ 8 | migration_20210612111147_createMetadataTable, 9 | migration_20210612112129_initialSchema, 10 | migration_20211019170802_createAttachmentsTable, 11 | migration_20230726103155_derived_taskComponents_whenNotDeleted, 12 | ]; 13 | export const latestSchemaVersionNumber = 14 | migrations[migrations.length - 1].version; 15 | -------------------------------------------------------------------------------- /packages/store-fs/src/sqlite/migrations/migrationType.ts: -------------------------------------------------------------------------------- 1 | export interface SQLMigration { 2 | version: number; 3 | statements: string[]; 4 | } 5 | -------------------------------------------------------------------------------- /packages/store-fs/src/sqlite/tables.ts: -------------------------------------------------------------------------------- 1 | export enum SQLTableName { 2 | Metadata = "metadata", 3 | Events = "events", 4 | Entities = "entities", 5 | Attachments = "attachments", 6 | } 7 | 8 | export enum SQLMetadataTableKey { 9 | Version = "__db_version", 10 | } 11 | 12 | export enum SQLEventTableColumn { 13 | SequenceNumber = "sequenceNumber", 14 | ID = "id", 15 | EntityID = "entityID", 16 | Data = "data", 17 | } 18 | 19 | export enum SQLEntityTableColumn { 20 | ID = "id", 21 | EntityType = "entityType", 22 | LastEventID = "lastEventID", 23 | LastEventTimestampMillis = "lastEventTimestampMillis", 24 | Data = "data", 25 | RowID = "rowID", 26 | } 27 | 28 | export enum SQLAttachmentTableColumn { 29 | ID = "id", 30 | Data = "data", 31 | MimeType = "mimeType", 32 | } 33 | -------------------------------------------------------------------------------- /packages/store-fs/src/util/getPathForAttachment.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | import { 3 | AttachmentID, 4 | AttachmentMIMEType, 5 | getFileExtensionForAttachmentMIMEType, 6 | } from "@withorbit/core"; 7 | 8 | export function getPathForAttachment( 9 | basePath: string, 10 | id: AttachmentID, 11 | type: AttachmentMIMEType, 12 | ) { 13 | return path.join( 14 | basePath, 15 | `${id}.${getFileExtensionForAttachmentMIMEType(type)}`, 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /packages/store-fs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": ["./src/**/*.ts", "./@types/**/*.d.ts"], 9 | "references": [ 10 | { 11 | "path": "../core" 12 | }, 13 | { 14 | "path": "../sample-data" 15 | }, 16 | { 17 | "path": "../store-shared" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/store-shared/Readme.md: -------------------------------------------------------------------------------- 1 | # `@withorbit/store-shared` 2 | 3 | `OrbitStore` implements a standard interface for interacting with a database of Orbit user data and an associated blob store for attachments. This package contains types shared by the two main implementations, `@withorbit/store-fs` (for Node.JS and React Native) and `@withorbit/store-web` (for web browsers). 4 | 5 | This library is compatible with Node.js, React Native, and web browser contexts. 6 | 7 | ``` 8 | Copyright 2021 Andy Matuschak 9 | SPDX-License-Identifier: Apache-2.0 10 | ``` 11 | -------------------------------------------------------------------------------- /packages/store-shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@withorbit/store-shared", 3 | "version": "0.0.1", 4 | "license": "Apache-2.0", 5 | "private": true, 6 | "type": "module", 7 | "main": "./dist/index.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": "./dist/index.js", 10 | "files": [ 11 | "dist" 12 | ], 13 | "sideEffects": false, 14 | "scripts": { 15 | "build": "tsc -b", 16 | "generateSchema": "typescript-json-schema src/validation/eventsValidator.ts Events -o src/validation/events.json --noExtraProps --required --ignoreErrors --strictNullChecks" 17 | }, 18 | "dependencies": { 19 | "@withorbit/core": "0.0.1", 20 | "ajv": "^8.6.2" 21 | }, 22 | "devDependencies": { 23 | "@types/jest": "^29.5.5", 24 | "@withorbit/sample-data": "0.0.1", 25 | "typescript": "^5.3.3", 26 | "typescript-json-schema": "^0.50.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/store-shared/src/attachmentStore.ts: -------------------------------------------------------------------------------- 1 | import { AttachmentID, AttachmentMIMEType } from "@withorbit/core"; 2 | 3 | export interface AttachmentStore { 4 | storeAttachment( 5 | contents: Uint8Array, 6 | id: AttachmentID, 7 | type: AttachmentMIMEType, 8 | ): Promise; 9 | 10 | // If the attachment has already been stored, resolves to its local URL; otherwise resolves to null. 11 | getURLForStoredAttachment(id: AttachmentID): Promise; 12 | 13 | // Rejects if the attachment is not stored. 14 | getAttachment( 15 | id: AttachmentID, 16 | ): Promise<{ contents: Uint8Array; type: AttachmentMIMEType }>; 17 | } 18 | -------------------------------------------------------------------------------- /packages/store-shared/src/encodeDataURL.ts: -------------------------------------------------------------------------------- 1 | import { AttachmentMIMEType } from "@withorbit/core"; 2 | import base64 from "base64-js"; 3 | 4 | export function encodeDataURL(data: ArrayBuffer, type: AttachmentMIMEType) { 5 | const b64String = base64.fromByteArray(new Uint8Array(data)); 6 | return `data:${type};base64,${b64String}`; 7 | } 8 | -------------------------------------------------------------------------------- /packages/store-shared/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { AttachmentStore } from "./attachmentStore.js"; 2 | 3 | export { Database } from "./database.js"; 4 | export type { EventReducer } from "./database.js"; 5 | 6 | export type { 7 | DatabaseBackend, 8 | DatabaseBackendEntityRecord, 9 | } from "./databaseBackend.js"; 10 | 11 | export type { 12 | DatabaseEntityQuery, 13 | DatabaseEventQuery, 14 | DatabaseQueryOptions, 15 | DatabaseQueryPredicate, 16 | DatabaseQueryPredicateRelation, 17 | DatabaseTaskQueryPredicate, 18 | } from "./databaseQuery.js"; 19 | 20 | export { encodeDataURL } from "./encodeDataURL.js"; 21 | 22 | export type { OrbitStore } from "./orbitStore.js"; 23 | 24 | export { runDatabaseTests } from "./databaseTests.js"; 25 | -------------------------------------------------------------------------------- /packages/store-shared/src/orbitStore.ts: -------------------------------------------------------------------------------- 1 | import { AttachmentStore } from "./attachmentStore.js"; 2 | import { Database } from "./database.js"; 3 | 4 | export interface OrbitStore { 5 | database: Database; 6 | attachmentStore: AttachmentStore; 7 | } 8 | -------------------------------------------------------------------------------- /packages/store-shared/src/validation/eventsValidator.ts: -------------------------------------------------------------------------------- 1 | import { Event } from "@withorbit/core"; 2 | 3 | type Events = Event[]; 4 | 5 | export type EventsValidatorError = { 6 | errors: { message: string }[]; 7 | }; 8 | 9 | export interface EventsValidator { 10 | validateEvents(events: Events): EventsValidatorError | true; 11 | } 12 | -------------------------------------------------------------------------------- /packages/store-shared/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["jest"] 7 | }, 8 | "include": ["./src/**/*.ts", "./@types/**/*.d.ts", "./src/**/*.json"], 9 | "references": [ 10 | { 11 | "path": "../core" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /packages/store-web/Readme.md: -------------------------------------------------------------------------------- 1 | # `@withorbit/store-web` 2 | 3 | Implementation of `OrbitStore` for web browser contexts. See `@withorbit/store-shared` for type definitions. 4 | 5 | ``` 6 | Copyright 2021 Andy Matuschak 7 | SPDX-License-Identifier: Apache-2.0 8 | ``` 9 | -------------------------------------------------------------------------------- /packages/store-web/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | plugins: [ 14 | [ 15 | "@babel/plugin-syntax-import-attributes", 16 | // TODO remove when we move to Node 22 and update import assert to import with 17 | { deprecatedAssertSyntax: true }, 18 | ], 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /packages/store-web/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | setupFiles: [ 9 | "fake-indexeddb/auto", 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /packages/store-web/src/database.test.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore Looks like there is no @types for this library 2 | import FDBFactory from "fake-indexeddb/lib/FDBFactory"; 3 | import { Database, runDatabaseTests } from "@withorbit/store-shared"; 4 | import { IDBDatabaseBackend } from "./indexedDB.js"; 5 | 6 | describe("database tests", () => { 7 | runDatabaseTests( 8 | "IndexedDB", 9 | async (eventReducer, eventValidator) => 10 | new Database( 11 | new IDBDatabaseBackend("TestDB", new FDBFactory()), 12 | eventReducer, 13 | eventValidator, 14 | ), 15 | ); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/store-web/src/index.ts: -------------------------------------------------------------------------------- 1 | export { OrbitStoreWeb as default } from "./orbitStoreWeb.js"; 2 | -------------------------------------------------------------------------------- /packages/store-web/src/orbitStoreWeb.ts: -------------------------------------------------------------------------------- 1 | import { Database, EventReducer, OrbitStore } from "@withorbit/store-shared"; 2 | import { AttachmentStoreWeb } from "./attachmentStoreWeb.js"; 3 | import { IDBDatabaseBackend } from "./indexedDB.js"; 4 | 5 | export class OrbitStoreWeb implements OrbitStore { 6 | database: Database; 7 | attachmentStore: AttachmentStoreWeb; 8 | 9 | constructor({ 10 | databaseName, 11 | indexedDB, 12 | eventReducer, 13 | }: { 14 | databaseName?: string; 15 | indexedDB?: IDBFactory; 16 | eventReducer?: EventReducer; 17 | }) { 18 | this.database = new Database( 19 | new IDBDatabaseBackend(databaseName, indexedDB), 20 | eventReducer, 21 | ); 22 | this.attachmentStore = new AttachmentStoreWeb( 23 | `${databaseName}-attachments`, 24 | indexedDB, 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/store-web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "lib": ["dom", "es2020"], 7 | "types": ["jest"] 8 | }, 9 | "include": ["./src/**/*.ts", "./@types/**/*.d.ts"], 10 | "references": [ 11 | { 12 | "path": "../core" 13 | }, 14 | { 15 | "path": "../sample-data" 16 | }, 17 | { 18 | "path": "../store-shared" 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/sync/babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | targets: { 7 | node: "current", 8 | }, 9 | }, 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /packages/sync/jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | "^(\\.{1,2}/.*)\\.js$": "$1", 4 | }, 5 | testEnvironment: "node", 6 | testMatch: ["**/?(*.)+(spec|test).ts?(x)"], 7 | testPathIgnorePatterns: ["dist", "node_modules"], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/sync/src/index.ts: -------------------------------------------------------------------------------- 1 | export { syncOrbitStore } from "./sync.js"; 2 | export { APISyncAdapter } from "./APISyncAdapter.js"; 3 | export type { SyncAdapter } from "./syncAdapter.js"; 4 | -------------------------------------------------------------------------------- /packages/sync/src/syncAdapter.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AttachmentID, 3 | AttachmentMIMEType, 4 | Event, 5 | EventID, 6 | } from "@withorbit/core"; 7 | 8 | export interface SyncAdapter { 9 | // This ID is used to track state associated with the remote destination associated with this interface (e.g. the last event ID sent/received to/from this destination). 10 | // Different destinations (e.g. test servers, production server, local host) should have different IDs. 11 | id: string; 12 | 13 | listEvents(afterEventID: EventID | null, limit: number): Promise; 14 | 15 | putEvents(events: Event[]): Promise; 16 | 17 | putAttachment( 18 | contents: Uint8Array, 19 | id: AttachmentID, 20 | type: AttachmentMIMEType, 21 | ): Promise; 22 | 23 | getAttachmentContents(id: AttachmentID): Promise; 24 | } 25 | -------------------------------------------------------------------------------- /packages/sync/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "rootDir": "./src", 6 | "types": ["jest", "node"] 7 | }, 8 | "include": [ 9 | "./src/**/*.ts", 10 | "./@types/**/*.d.ts", 11 | ], 12 | "references": [ 13 | { 14 | "path": "../core" 15 | }, 16 | { 17 | "path": "../sample-data" 18 | }, 19 | { 20 | "path": "../store-fs" 21 | }, 22 | { 23 | "path": "../store-shared" 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /packages/tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "allowSyntheticDefaultImports": true, 5 | "composite": true, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "isolatedModules": true, 11 | "lib": ["es2023"], 12 | "module": "nodenext", 13 | "moduleResolution": "nodenext", 14 | "resolveJsonModule": true, 15 | "skipLibCheck": true, 16 | "sourceMap": true, 17 | "strict": true, 18 | "target": "ES2022", 19 | "types": [] 20 | }, 21 | "compileOnSave": true 22 | } 23 | -------------------------------------------------------------------------------- /packages/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "references": [ 3 | { "path": "./anki-import" }, 4 | { "path": "./api" }, 5 | { "path": "./api-client" }, 6 | { "path": "./app" }, 7 | { "path": "./backend" }, 8 | { "path": "./core" }, 9 | { "path": "./embedded-support" }, 10 | { "path": "./ingester" }, 11 | { "path": "./interpreter" }, 12 | { "path": "./ui" }, 13 | { "path": "./sample-data" }, 14 | { "path": "./store-fs" }, 15 | { "path": "./store-shared" }, 16 | { "path": "./store-web" }, 17 | { "path": "./web-component" } 18 | ], 19 | "files": [] 20 | } 21 | -------------------------------------------------------------------------------- /packages/ui/.gitignore: -------------------------------------------------------------------------------- 1 | storybook-static 2 | -------------------------------------------------------------------------------- /packages/ui/.storybook/preview.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parameters: { 3 | layout: "fullscreen", 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/ui/Readme.md: -------------------------------------------------------------------------------- 1 | # @withorbit/ui 2 | 3 | Defines base UI components and styles. Should probably be rolled into `@withorbit/app`. 4 | 5 | ``` 6 | Copyright 2020 Andy Matuschak 7 | SPDX-License-Identifier: Apache-2.0 8 | ``` 9 | -------------------------------------------------------------------------------- /packages/ui/assets/fonts/.gitignore: -------------------------------------------------------------------------------- 1 | # These fonts' licenses do not permit them to be included in distributable Git repos. 2 | dr* 3 | raptor* 4 | -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_AMS-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_AMS-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_AMS-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_AMS-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_AMS-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_AMS-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Caligraphic-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Caligraphic-Bold.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Caligraphic-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Caligraphic-Bold.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Caligraphic-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Caligraphic-Bold.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Caligraphic-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Caligraphic-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Caligraphic-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Caligraphic-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Caligraphic-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Caligraphic-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Fraktur-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Fraktur-Bold.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Fraktur-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Fraktur-Bold.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Fraktur-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Fraktur-Bold.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Fraktur-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Fraktur-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Fraktur-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Fraktur-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Fraktur-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Fraktur-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Bold.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Bold.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Bold.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-BoldItalic.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-BoldItalic.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-BoldItalic.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Italic.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Italic.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Italic.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Main-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Main-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Math-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Math-BoldItalic.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Math-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Math-BoldItalic.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Math-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Math-BoldItalic.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Math-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Math-Italic.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Math-Italic.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Math-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Math-Italic.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Bold.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Bold.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Bold.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Italic.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Italic.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Italic.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_SansSerif-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_SansSerif-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Script-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Script-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Script-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Script-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Script-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Script-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size1-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size1-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size1-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size1-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size1-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size2-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size2-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size2-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size2-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size2-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size3-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size3-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size3-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size3-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size3-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size3-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size4-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size4-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size4-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Size4-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Size4-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Typewriter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Typewriter-Regular.ttf -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Typewriter-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Typewriter-Regular.woff -------------------------------------------------------------------------------- /packages/ui/assets/fonts/KaTeX_Typewriter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/fonts/KaTeX_Typewriter-Regular.woff2 -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-BL.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BL.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-BL@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-BL@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-BR.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BR.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BR@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-BR@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-BR@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-BR@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-TL.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TL.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-TL@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-TL@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-TR.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TR.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TR@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-TR@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-TR@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-TR@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/check-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/check-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-BL.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-BL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-BL@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-BL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-BL@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-BR.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-BR@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-BR@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-BR@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-BR@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-TL.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-TL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-TL@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-TL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-TL@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-TR.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-TR@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-TR@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-TR@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-TR@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/cross-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/cross-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/dots-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/dots-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/dots-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/dots-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/dots-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/dots-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/dots-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/doubleRight-TL.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-TL.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-TL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/doubleRight-TL@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-TL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/doubleRight-TL@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/doubleRight-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/doubleRight-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/doubleRight-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/doubleRight-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/left-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/left-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/left-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/left-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/left-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/left-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/left-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/list-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/list-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/list-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/list-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/list-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/list-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/list-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-bottom.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-bottom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-bottom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-bottom@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-bottom@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-bottom@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-top.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-top.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-top@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-top@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-accent-top@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-accent-top@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-bottom.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-bottom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-bottom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-bottom@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-bottom@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-bottom@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-top.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-top.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-top@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-top@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/reveal-top@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/reveal-top@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-BL.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BL.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-BL@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-BL@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-BR.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BR.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BR@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-BR@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-BR@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-BR@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-TL.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TL.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TL@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-TL@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TL@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-TL@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-TR.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TR.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TR@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-TR@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-TR@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-TR@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-center.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-center@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-center@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/icons/right-center@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/icons/right-center@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/16.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/16@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/16@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/16@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/24.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/24@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/24@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/24@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/24@3x.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/32.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/32@2x.png -------------------------------------------------------------------------------- /packages/ui/assets/logo/32@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andymatuschak/orbit/ed5a530750b6e96e86ea725ef3990c9209fc0028/packages/ui/assets/logo/32@3x.png -------------------------------------------------------------------------------- /packages/ui/babel.config.cjs: -------------------------------------------------------------------------------- 1 | // Used just for Storybook. 2 | module.exports = { 3 | sourceType: "unambiguous", 4 | presets: [ 5 | [ 6 | "@babel/preset-env", 7 | { 8 | targets: { 9 | chrome: 100, 10 | safari: 15, 11 | firefox: 91, 12 | }, 13 | }, 14 | ], 15 | "@babel/preset-typescript", 16 | "@babel/preset-react", 17 | ], 18 | plugins: [], 19 | }; 20 | -------------------------------------------------------------------------------- /packages/ui/src/@types/markdown-it-texmath/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "markdown-it-texmath" { 2 | import MarkdownIt from "markdown-it"; 3 | import katex from "katex"; 4 | export function use( 5 | katexInstance: typeof katex, 6 | ): (md: MarkdownIt, ...params: unknown[]) => void; 7 | } 8 | -------------------------------------------------------------------------------- /packages/ui/src/components/DebugGrid.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { View } from "react-native"; 3 | import DebugGrid from "./DebugGrid.js"; 4 | 5 | export default { 6 | title: "Style/Grid", 7 | }; 8 | 9 | export function Grid() { 10 | return ( 11 | 22 | 23 | 24 | ); 25 | } 26 | -------------------------------------------------------------------------------- /packages/ui/src/components/FadeView.stories.tsx: -------------------------------------------------------------------------------- 1 | import { action } from "@storybook/addon-actions"; 2 | 3 | import React, { useState } from "react"; 4 | import FadeView from "./FadeView.jsx"; 5 | import { Button, View } from "react-native"; 6 | 7 | export default { 8 | title: "FadeView", 9 | component: FadeView, 10 | }; 11 | 12 | export function Basic() { 13 | const initialValue = true; 14 | const [isVisible, setVisible] = useState(initialValue); 15 | return ( 16 | 17 | 23 | 24 | 25 |