diff --git a/.husky/pre-commit b/.husky/pre-commit index 7ce7052c..1a1f1f06 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1 @@ -yarn lintAndFormatAllPrePush - +yarn lint-staged \ No newline at end of file diff --git a/README.md b/README.md index dc905c8a..520e408f 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,12 @@ Build the sidecar binaries (requires Rust and Go installed): bash ./scripts/setup-binaries.sh ``` +or fetch with + +```bash +yarn fetch:binaries +``` + Build the Node Rust-add-ons ```bash diff --git a/package.json b/package.json index ea1a11bd..801d3d4d 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,9 @@ "winston": "3.13.0", "zod": "^3.23.6" }, + "lint-staged": { + "*.{js,ts,svelte,json,postcss,html}": "yarn lintAndFormatAllPrePush" + }, "devDependencies": { "@electron-toolkit/eslint-config-prettier": "^2.0.0", "@electron-toolkit/eslint-config-ts": "^2.0.0", @@ -91,6 +94,7 @@ "get-port": "7.1.0", "husky": "^9.0.11", "js-yaml": "^4.1.0", + "lint-staged": "^15.2.4", "mocha": "10.4.0", "prettier": "^3.1.1", "rimraf": "5.0.5", diff --git a/src/main/index.ts b/src/main/index.ts index 722e55b7..1b1d1792 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -4,7 +4,7 @@ import { AppWebsocket, type CallZomeRequest } from '@holochain/client'; import { decode } from '@msgpack/msgpack'; import { initTRPC } from '@trpc/server'; import type { AppVersionEntry } from 'appstore-tools'; -import { AppstoreAppClient, DevhubAppClient } from 'appstore-tools'; +import { AppstoreAppClient } from 'appstore-tools'; import { webhappToHappAndUi } from 'appstore-tools'; import * as childProcess from 'child_process'; import { Command, Option } from 'commander'; @@ -206,7 +206,7 @@ const WINDOW_INFO_MAP: WindowInfoRecord = {}; // WindowInfo by webContents.id - const APP_CLIENTS: Record = {}; let APPSTORE_APP_CLIENT: AppstoreAppClient | undefined; -let DEVHUB_APP_CLIENT: DevhubAppClient | undefined; +// let DEVHUB_APP_CLIENT: DevhubAppClient | undefined; const handleSignZomeCall = async (e: IpcMainInvokeEvent, request: CallZomeRequest) => { // TODO check here that cellId belongs to the installedAppId that the window belongs to @@ -466,15 +466,14 @@ const getAppstoreAppClient = async () => { return APPSTORE_APP_CLIENT; }; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const getDevhubAppClient = async () => { - if (DEVHUB_APP_CLIENT) return DEVHUB_APP_CLIENT; - if (!DEFAULT_HOLOCHAIN_DATA_ROOT) throw new Error('Default holochain data root is not defined.'); - const appClient = await getAppClient(DEVHUB_APP_ID); - const devhubAppClient = new DevhubAppClient(appClient); - DEVHUB_APP_CLIENT = devhubAppClient; - return DEVHUB_APP_CLIENT; -}; +// const getDevhubAppClient = async () => { +// if (DEVHUB_APP_CLIENT) return DEVHUB_APP_CLIENT; +// if (!DEFAULT_HOLOCHAIN_DATA_ROOT) throw new Error('Default holochain data root is not defined.'); +// const appClient = await getAppClient(DEVHUB_APP_ID); +// const devhubAppClient = new DevhubAppClient(appClient); +// DEVHUB_APP_CLIENT = devhubAppClient; +// return DEVHUB_APP_CLIENT; +// }; const router = t.router({ openSettings: t.procedure.mutation(() => { @@ -664,18 +663,23 @@ const router = t.router({ launch: handlePasswordInput(handleLaunch), initializeDefaultAppPorts: t.procedure.query(async () => { const defaultHolochainManager = HOLOCHAIN_MANAGERS[DEFAULT_HOLOCHAIN_DATA_ROOT!.name]; - const appstoreAuthenticationToken = await defaultHolochainManager.getAppToken(APP_STORE_APP_ID); - const devhubAuthenticationToken = await defaultHolochainManager.getAppToken(DEVHUB_APP_ID); - if (!appstoreAuthenticationToken) { - return throwTRPCErrorError({ - message: NO_APPSTORE_AUTHENTICATION_TOKEN_FOUND, - }); - } - if (isDevhubInstalled(HOLOCHAIN_MANAGERS) && !devhubAuthenticationToken) { - return throwTRPCErrorError({ - message: NO_DEVHUB_AUTHENTICATION_TOKEN_FOUND, - }); - } + + const getTokenOrThrow = async (appId: string, errorMessage: string) => { + const token = await defaultHolochainManager.getAppToken(appId); + if (!token) { + throwTRPCErrorError({ message: errorMessage }); + } + return token; + }; + + const appstoreAuthenticationToken = await getTokenOrThrow( + APP_STORE_APP_ID, + NO_APPSTORE_AUTHENTICATION_TOKEN_FOUND, + ); + const devhubAuthenticationToken = isDevhubInstalled(HOLOCHAIN_MANAGERS) + ? await getTokenOrThrow(DEVHUB_APP_ID, NO_DEVHUB_AUTHENTICATION_TOKEN_FOUND) + : undefined; + return validateWithZod({ schema: InitializeAppPortsSchema, data: { diff --git a/src/renderer/src/app.postcss b/src/renderer/src/app.postcss index 76784a17..6c567b6e 100644 --- a/src/renderer/src/app.postcss +++ b/src/renderer/src/app.postcss @@ -56,6 +56,10 @@ body { @apply bg-button-gradient font-semibold; } +.btn-happ-button { + @apply btn bg-add-happ-button font-semibold; +} + .btn-secondary, .btn-install { @apply border border-surface-400 bg-transparent !text-sm; diff --git a/src/renderer/src/lib/const/launcher.ts b/src/renderer/src/lib/const/launcher.ts index 4878d9cf..854f4d56 100644 --- a/src/renderer/src/lib/const/launcher.ts +++ b/src/renderer/src/lib/const/launcher.ts @@ -2,13 +2,14 @@ import { SETTINGS_SCREEN } from '$shared/const'; export const MODAL_INSTALL_FROM_FILE = 'modalInstallFromFile'; export const MODAL_INSTALL_KANDO = 'modalInstallKando'; -export const MODAL_ADD_PUBLISHER = 'modalAddPublisher'; export const MODAL_ADD_NEW_HAPP_VERSION = 'modalAddNewHappVersion'; export const MODAL_DEVHUB_INSTALLATION_CONFIRMATION = 'modalDevHubInstallationConfirmation'; export const SELECTED_ICON_STYLE = 'fill-light-primary dark:fill-white'; export const DEV_PAGE = `${SETTINGS_SCREEN}/dev`; +export const DEV_APP_PAGE = `${DEV_PAGE}/app`; +export const PUBLISHER_SCREEN = `${DEV_PAGE}/publisher`; export const SEARCH_URL_QUERY = 'search'; export const PRESEARCH_URL_QUERY = 'presearch'; diff --git a/src/renderer/src/lib/helpers/display.ts b/src/renderer/src/lib/helpers/display.ts index 12567fea..ab220780 100644 --- a/src/renderer/src/lib/helpers/display.ts +++ b/src/renderer/src/lib/helpers/display.ts @@ -19,7 +19,11 @@ export const showModalError = ({ modalStore.trigger(modal); }; -export const createModalParams = (component: Modals): ModalSettings => ({ +export const createModalParams = ( + component: Modals, + response?: (r: unknown) => void +): ModalSettings => ({ type: 'component' as const, - component + component, + response }); diff --git a/src/renderer/src/lib/icons/Publisher.svelte b/src/renderer/src/lib/icons/Publisher.svelte new file mode 100644 index 00000000..8f8eb0e1 --- /dev/null +++ b/src/renderer/src/lib/icons/Publisher.svelte @@ -0,0 +1,10 @@ + + + + diff --git a/src/renderer/src/lib/icons/index.ts b/src/renderer/src/lib/icons/index.ts index 0ae61c3f..73828bf3 100644 --- a/src/renderer/src/lib/icons/index.ts +++ b/src/renderer/src/lib/icons/index.ts @@ -11,6 +11,7 @@ export { default as MenuGear } from './Menu-Gear.svelte'; export { default as MenuInfo } from './Menu-Info.svelte'; export { default as PasswordEye } from './PasswordEye.svelte'; export { default as Plus } from './Plus.svelte'; +export { default as Publisher } from './Publisher.svelte'; export { default as Rocket } from './Rocket.svelte'; export { default as Upload } from './Upload.svelte'; export { default as UploadImage } from './UploadImage.svelte'; diff --git a/src/renderer/src/lib/locale/en/common.json b/src/renderer/src/lib/locale/en/common.json index 2e30e66c..3e7beb01 100644 --- a/src/renderer/src/lib/locale/en/common.json +++ b/src/renderer/src/lib/locale/en/common.json @@ -48,9 +48,12 @@ "passwordPlaceholder": "Enter your password", "passwordWarning": "Your password can not be reset, recovered or changed. Save it in your password manager or some other secure location.", "passwordsDontMatch": "Passwords don't match!", + "publishYourApp": "Publish your App", + "publishingDashboard": "Publishing Dashboard", "region": "Region", "releases": "Releases", "searchForApps": "Search for apps", + "setUpYourPublisherProfile": "Set up your publisher profile", "setYourPassword": "Set your password", "setupError": "Setup Error", "setupProgress": "Setup Progress", @@ -62,9 +65,11 @@ "uninstall": "Uninstall", "updateAvailable": "Update available", "uploadAndPublish": "upload and publish apps", + "uploadYourBundle": "Upload your bundle", "useWebhappFileToAddHapp": "Use a webhapp file to add your hApp", "versionHistory": "Version History", "website": "Website", + "welcomeToTheHolochainLauncherDeveloperDashboard": "Welcome to the Holochain Launcher Developer Dashboard! Sharing your app with the world begins with creating a publisher account.", "whatDoYouWantToInstall": "What do you want to install?", "yourHapps": "Your hApps" } diff --git a/src/renderer/src/lib/modal/AddNewHappVersion.svelte b/src/renderer/src/lib/modal/AddNewHappVersion.svelte index e26a111f..117b9b77 100644 --- a/src/renderer/src/lib/modal/AddNewHappVersion.svelte +++ b/src/renderer/src/lib/modal/AddNewHappVersion.svelte @@ -25,7 +25,9 @@ .sort((a, b) => a.last_updated - b.last_updated)[0].bundle_hashes.happ_hash; const setAppDataBytes = async (files: FileList | null) => { - bytes = files && files.length > 0 ? await convertFileToUint8Array(files[0]) : undefined; + if (files && files.length > 0) { + bytes = await convertFileToUint8Array(files[0]); + } }; $: setAppDataBytes(files); @@ -57,7 +59,7 @@ } }} > - + - import { getModalStore } from '@skeletonlabs/skeleton'; - import type { CreatePublisherFrontendInput } from 'appstore-tools'; - - import { goto } from '$app/navigation'; - import { AddTypeModalFooter, IconInput } from '$components'; - import { DEV_PAGE } from '$const'; - import { base64ToArrayBuffer, convertFileToUint8Array } from '$helpers'; - import { defaultIcon } from '$icons'; - import { createAppQueries } from '$queries'; - import { i18n } from '$services'; - - import InputModal from './InputModal.svelte'; - - const { publisherMutation } = createAppQueries(); - - const modalStore = getModalStore(); - - let publisherData: CreatePublisherFrontendInput = { - name: '', - location: '', - website: { url: '', context: undefined }, - icon: base64ToArrayBuffer(defaultIcon) - }; - - const handleFileUpload = async (file: File): Promise => { - publisherData.icon = await convertFileToUint8Array(file); - }; - - -{#if $modalStore[0]} -
-
- {$i18n.t('addPublisher')} -
-
-{/if} diff --git a/src/renderer/src/lib/modal/DevHubInstallationConfirmation.svelte b/src/renderer/src/lib/modal/DevHubInstallationConfirmation.svelte index a92f3dc0..364f144f 100644 --- a/src/renderer/src/lib/modal/DevHubInstallationConfirmation.svelte +++ b/src/renderer/src/lib/modal/DevHubInstallationConfirmation.svelte @@ -2,16 +2,10 @@ import { getModalStore } from '@skeletonlabs/skeleton'; import { Button } from '$components'; - import { showModalError } from '$helpers'; import { Confirmation } from '$icons'; - import { createDevHubClient, i18n, trpc } from '$services'; - - const client = trpc(); + import { i18n } from '$services'; const modalStore = getModalStore(); - - const installDevhub = client.installDevhub.createMutation(); - const isDevhubInstalled = client.isDevhubInstalled.createQuery(); {#if $modalStore[0]} @@ -34,25 +28,9 @@ diff --git a/src/renderer/src/routes/settings/(menu)/dev/publisher/add/+page.svelte b/src/renderer/src/routes/settings/(menu)/dev/publisher/add/+page.svelte new file mode 100644 index 00000000..716fd3c1 --- /dev/null +++ b/src/renderer/src/routes/settings/(menu)/dev/publisher/add/+page.svelte @@ -0,0 +1,76 @@ + + +
+ {$i18n.t('setUpYourPublisherProfile')} +
+