From 07011dea45e810afb221f0375246d6bf9a2984f3 Mon Sep 17 00:00:00 2001 From: Jason Efstathiou Date: Fri, 19 Apr 2024 14:09:50 +0200 Subject: [PATCH] Revert "Feature/multiplayer (#1062)" This reverts commit bc39d56127d4e1bbfe38c6368ff992cd0a4f875b. --- .env.template | 4 - .github/workflows/check.yml | 4 +- .github/workflows/unit-tests.yml | 2 - dev.docker-compose.yml | 2 +- docker/app-e2e-test-env | 2 - docker/env-ports-exposed.docker-compose.yml | 4 - docker/env.docker-compose.yml | 32 +- docker/services/multiplayer/Dockerfile | 23 - docker/services/multiplayer/db/schema.sql | 1 - docker/services/multiplayer/envfile | 14 - docker/services/multiplayer/start.sh | 9 - .../scripts/clone-subgraph.sh | 2 +- docker/services/testnet/Dockerfile | 2 +- package-lock.json | 181 +---- package.json | 8 +- .../top-up-create-stream.e2e.test.ts | 47 +- .../annotation-box/annotation-box.svelte | 19 +- src/lib/components/button/button.svelte | 6 +- .../button/props-only-button.svelte | 17 - src/lib/components/countdown/countdown.svelte | 30 - .../components/date-picker/DateInput.svelte | 268 ------- .../components/date-picker/DatePicker.svelte | 504 ------------- .../components/date-picker/TimePicker.svelte | 212 ------ src/lib/components/date-picker/date-utils.ts | 81 --- src/lib/components/date-picker/index.ts | 9 - src/lib/components/date-picker/locale.ts | 72 -- src/lib/components/date-picker/parse.ts | 166 ----- .../voting-round-collaborators.svelte | 208 ------ .../components/voting-round-countdown.svelte | 31 - .../voting-round-notice-card.svelte | 94 --- .../components/voting-round-splits.svelte | 66 -- .../drip-list-card-representational.svelte | 354 +++++++++ .../drip-list-card-thumblink.svelte | 279 -------- .../drip-list-card/drip-list-card.svelte | 428 +---------- .../methods/get-supporters-pile.ts | 94 --- .../drip-list-editor/drip-list-editor.svelte | 14 +- .../drip-list-members-editor.svelte | 676 ++++++++++++++++++ .../item-templates/drip-list.ts | 9 + .../item-templates/eth-address.ts | 8 + .../item-templates/project.ts | 11 + .../drip-lists-section.svelte | 70 +- src/lib/components/emoji/emoji.ts | 7 +- .../components/icons/\360\237\221\252.svelte" | 164 ----- .../\360\237\227\263\357\270\217.svelte" | 34 - .../identity-badge/identity-badge.svelte | 4 +- .../components/list-editor-input.svelte | 331 --------- .../components/list-editor-item.svelte | 235 ------ .../components/list-editor-pie.svelte | 113 --- .../components/list-editor/list-editor.svelte | 256 ------- src/lib/components/list-editor/types.ts | 51 -- .../project-avatar/project-avatar.svelte | 5 +- .../project-badge/project-badge.svelte | 2 + .../segmented-control.svelte | 27 +- .../share-button/share-button.svelte | 68 +- .../splits/components/split/split.svelte | 66 +- src/lib/components/splits/splits.svelte | 238 ++---- .../status-badge/status-badge.svelte | 62 -- .../components/step-header/step-header.svelte | 4 +- src/lib/components/stepper/utils/transact.ts | 33 +- .../stream-state-badge.svelte | 62 +- .../success-step/success-step.svelte | 4 +- .../support-card/support-card.svelte | 16 +- .../components/tabbed-box/tabbed-box.svelte | 4 +- .../table/cells/project-badge.cell.svelte | 3 +- .../components/text-input/text-input.svelte | 5 +- .../two-big-options/components/option.svelte | 12 +- .../unclaimed-project-card.svelte | 2 +- .../claim-project-flow/claim-project-flow.ts | 23 +- .../claim-project-stepper.svelte | 2 +- .../add-ethereum-address.svelte | 15 +- .../configure-dependencies.svelte | 40 +- .../configure-maintainers.svelte | 17 +- .../steps/review/review.svelte | 4 +- .../create-drip-list-flow.ts | 56 +- .../steps/build-list/build-list.svelte | 24 +- .../choose-creation-mode.svelte | 106 --- .../configure-voting-round.svelte | 68 -- .../review-voting-round.svelte | 189 ----- .../steps/review/review.svelte | 33 +- .../steps/success/success.svelte | 14 +- .../flows/delete-voting-round/confirm.svelte | 55 -- .../delete-voting-round-steps.ts | 21 - .../shared/steps/edit-drip-list.svelte | 88 ++- .../edit-project-splits-steps.ts | 110 ++- .../steps/edit-dependency-list.svelte | 10 +- .../steps/edit-maintainer-list.svelte | 9 +- .../edit-project-splits/steps/review.svelte | 4 +- .../load-data.svelte | 25 - .../publish-voting-round-list-flow-steps.ts | 52 -- .../publish-voting-round-list/review.svelte | 183 ----- .../flows/view-vote/fetch-vote-data.svelte | 24 - .../flows/view-vote/view-vote-flow-steps.ts | 38 - src/lib/flows/view-vote/view-vote.svelte | 39 - .../flows/view-voting-round/fetch-data.svelte | 24 - .../view-voting-round-flow-steps.ts | 32 - .../view-voting-round.svelte | 55 -- src/lib/flows/vote/fetch-vote-data.svelte | 64 -- src/lib/flows/vote/vote-flow-steps.ts | 47 -- src/lib/flows/vote/vote.svelte | 93 --- src/lib/stores/wallet/safe/sdk.ts | 20 + src/lib/stores/wallet/wallet.store.ts | 4 +- src/lib/utils/await-store-value.ts | 15 - src/lib/utils/driplist/DripListService.ts | 174 +++-- src/lib/utils/get-drips-clients.ts | 2 +- .../metadata/NftDriverMetadataManager.ts | 4 +- src/lib/utils/metadata/schemas/index.ts | 2 - .../utils/metadata/schemas/nft-driver/v4.ts | 6 - src/lib/utils/multiplayer/index.ts | 1 - src/lib/utils/multiplayer/multiplayer.ts | 645 ----------------- src/lib/utils/multiplayer/schemas.ts | 86 --- .../signature-message-templates.ts | 76 -- src/lib/utils/project/GitProjectService.ts | 155 ++-- .../api/multiplayer/[...path]/+server.ts | 20 - .../drip-list/[listId].png/+server.ts | 61 +- src/routes/app/(app)/+page.svelte | 4 +- .../app/(app)/component-showcase/+page.svelte | 79 +- .../(app)/drip-lists/[listId]/+page.server.ts | 64 +- .../(app)/drip-lists/[listId]/+page.svelte | 153 +--- 118 files changed, 1781 insertions(+), 7225 deletions(-) delete mode 100644 docker/services/multiplayer/Dockerfile delete mode 100644 docker/services/multiplayer/db/schema.sql delete mode 100644 docker/services/multiplayer/envfile delete mode 100644 docker/services/multiplayer/start.sh delete mode 100644 src/lib/components/button/props-only-button.svelte delete mode 100644 src/lib/components/countdown/countdown.svelte delete mode 100644 src/lib/components/date-picker/DateInput.svelte delete mode 100644 src/lib/components/date-picker/DatePicker.svelte delete mode 100644 src/lib/components/date-picker/TimePicker.svelte delete mode 100644 src/lib/components/date-picker/date-utils.ts delete mode 100644 src/lib/components/date-picker/index.ts delete mode 100644 src/lib/components/date-picker/locale.ts delete mode 100644 src/lib/components/date-picker/parse.ts delete mode 100644 src/lib/components/drip-list-card/components/voting-round-collaborators.svelte delete mode 100644 src/lib/components/drip-list-card/components/voting-round-countdown.svelte delete mode 100644 src/lib/components/drip-list-card/components/voting-round-notice-card.svelte delete mode 100644 src/lib/components/drip-list-card/components/voting-round-splits.svelte create mode 100644 src/lib/components/drip-list-card/drip-list-card-representational.svelte delete mode 100644 src/lib/components/drip-list-card/drip-list-card-thumblink.svelte delete mode 100644 src/lib/components/drip-list-card/methods/get-supporters-pile.ts create mode 100644 src/lib/components/drip-list-members-editor/drip-list-members-editor.svelte create mode 100644 src/lib/components/drip-list-members-editor/item-templates/drip-list.ts create mode 100644 src/lib/components/drip-list-members-editor/item-templates/eth-address.ts create mode 100644 src/lib/components/drip-list-members-editor/item-templates/project.ts delete mode 100644 "src/lib/components/icons/\360\237\221\252.svelte" delete mode 100644 "src/lib/components/icons/\360\237\227\263\357\270\217.svelte" delete mode 100644 src/lib/components/list-editor/components/list-editor-input.svelte delete mode 100644 src/lib/components/list-editor/components/list-editor-item.svelte delete mode 100644 src/lib/components/list-editor/components/list-editor-pie.svelte delete mode 100644 src/lib/components/list-editor/list-editor.svelte delete mode 100644 src/lib/components/list-editor/types.ts delete mode 100644 src/lib/components/status-badge/status-badge.svelte delete mode 100644 src/lib/flows/create-drip-list-flow/steps/choose-creation-mode/choose-creation-mode.svelte delete mode 100644 src/lib/flows/create-drip-list-flow/steps/configure-voting-round/configure-voting-round.svelte delete mode 100644 src/lib/flows/create-drip-list-flow/steps/review-voting-round/review-voting-round.svelte delete mode 100644 src/lib/flows/delete-voting-round/confirm.svelte delete mode 100644 src/lib/flows/delete-voting-round/delete-voting-round-steps.ts delete mode 100644 src/lib/flows/publish-voting-round-list/load-data.svelte delete mode 100644 src/lib/flows/publish-voting-round-list/publish-voting-round-list-flow-steps.ts delete mode 100644 src/lib/flows/publish-voting-round-list/review.svelte delete mode 100644 src/lib/flows/view-vote/fetch-vote-data.svelte delete mode 100644 src/lib/flows/view-vote/view-vote-flow-steps.ts delete mode 100644 src/lib/flows/view-vote/view-vote.svelte delete mode 100644 src/lib/flows/view-voting-round/fetch-data.svelte delete mode 100644 src/lib/flows/view-voting-round/view-voting-round-flow-steps.ts delete mode 100644 src/lib/flows/view-voting-round/view-voting-round.svelte delete mode 100644 src/lib/flows/vote/fetch-vote-data.svelte delete mode 100644 src/lib/flows/vote/vote-flow-steps.ts delete mode 100644 src/lib/flows/vote/vote.svelte create mode 100644 src/lib/stores/wallet/safe/sdk.ts delete mode 100644 src/lib/utils/await-store-value.ts delete mode 100644 src/lib/utils/metadata/schemas/nft-driver/v4.ts delete mode 100644 src/lib/utils/multiplayer/index.ts delete mode 100644 src/lib/utils/multiplayer/multiplayer.ts delete mode 100644 src/lib/utils/multiplayer/schemas.ts delete mode 100644 src/lib/utils/multiplayer/signature-message-templates.ts delete mode 100644 src/routes/api/multiplayer/[...path]/+server.ts diff --git a/.env.template b/.env.template index e96fa19ab..764d25a33 100644 --- a/.env.template +++ b/.env.template @@ -38,7 +38,3 @@ CACHE_REDIS_CONNECTION_STRING=string # Optional base URL to use in local requests. Defaults to http://localhost:5173 PUBLIC_BASE_URL=string - -# URL of the Drips Multiplayer API deployment to use. Set to the defaults below to use public Sepolia deployment. -MULTIPLAYER_API_URL=string # Default for sepolia https://multiplayer-sepolia.up.railway.app -MULTIPLAYER_API_ACCESS_TOKEN=string # Default for sepolia 992b2122-9a09-4a97-b2cc-2292d3dd23aa diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index ae3fbc359..2e163795b 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -37,8 +37,6 @@ jobs: envkey_GQL_ACCESS_TOKEN: afdb8b7e-8fa7-4de9-bd95-b650b839e745 # public token envkey_PUBLIC_PINATA_GATEWAY_URL: http://localhost:3000 envkey_INFURA_KEY: 1234 - envkey_MULTIPLAYER_API_ACCESS_TOKEN: 1234 - envkey_MULTIPLAYER_API_URL: http://foobar:3000/ - name: Install dependencies run: npm ci @@ -47,4 +45,4 @@ jobs: run: npm run build:graphql - name: Run svelte-check - run: npm run check + run: npm run check -- --fail-on-warnings diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 35cfdb7ae..f47e8b523 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -30,8 +30,6 @@ jobs: envkey_GQL_ACCESS_TOKEN: afdb8b7e-8fa7-4de9-bd95-b650b839e745 # public token envkey_PUBLIC_PINATA_GATEWAY_URL: http://localhost:3000 envkey_INFURA_KEY: 1234 - envkey_MULTIPLAYER_API_ACCESS_TOKEN: 1234 - envkey_MULTIPLAYER_API_URL: http://foobar:3000/ - name: Install dependencies run: npm ci diff --git a/dev.docker-compose.yml b/dev.docker-compose.yml index 0d3a853ac..81ade1e47 100644 --- a/dev.docker-compose.yml +++ b/dev.docker-compose.yml @@ -74,7 +74,7 @@ services: postgres_pass: postgres postgres_db: graph-node ipfs: 'ipfs:5001' - ethereum: "sepolia:http://testnet:8545" + ethereum: "goerli:http://testnet:8545" GRAPH_LOG: info subgraph-deployer: diff --git a/docker/app-e2e-test-env b/docker/app-e2e-test-env index 280994dfb..e3d63f8b5 100644 --- a/docker/app-e2e-test-env +++ b/docker/app-e2e-test-env @@ -17,5 +17,3 @@ VITE_TEST_MODE=true CACHE_REDIS_CONNECTION_STRING=redis://redis:6379 INFURA_KEY=1234 PUBLIC_BASE_URL=http://localhost:3001 -MULTIPLAYER_API_URL=http://multiplayer:5001 -MULTIPLAYER_API_ACCESS_TOKEN=1234 diff --git a/docker/env-ports-exposed.docker-compose.yml b/docker/env-ports-exposed.docker-compose.yml index 85700084e..1edebca39 100644 --- a/docker/env-ports-exposed.docker-compose.yml +++ b/docker/env-ports-exposed.docker-compose.yml @@ -19,7 +19,3 @@ services: ports: [3000:3000] redis: ports: [6379:6379] - postgres-multiplayer: - ports: [5434:5432] - multiplayer: - ports: [5002:5002] diff --git a/docker/env.docker-compose.yml b/docker/env.docker-compose.yml index 536dd6580..e6d29435b 100644 --- a/docker/env.docker-compose.yml +++ b/docker/env.docker-compose.yml @@ -33,7 +33,7 @@ services: postgres_pass: postgres postgres_db: graph-node ipfs: 'ipfs:5001' - ethereum: "sepolia:http://testnet:8545" + ethereum: "goerli:http://testnet:8545" GRAPH_LOG: info ETHEREUM_REORG_THRESHOLD: 1 ETHEREUM_ANCESTOR_COUNT: 1 @@ -94,33 +94,3 @@ services: context: . ports: - '3000:3000' - - postgres-multiplayer: - image: postgres - command: ["postgres", "-cshared_preload_libraries=pg_stat_statements"] - volumes: - - ./services/multiplayer/db:/docker-entrypoint-initdb.d - environment: - POSTGRES_USER: user - POSTGRES_PASSWORD: admin - POSTGRES_DB: dripsdb - POSTGRES_INITDB_ARGS: -E UTF8 --locale=C - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] - interval: 5s - timeout: 5s - retries: 5 - - multiplayer: - build: - dockerfile: ./services/multiplayer/Dockerfile - context: . - args: - - MULTIPLAYER_BRANCH - depends_on: - - postgres-multiplayer - healthcheck: - test: ["CMD", "curl", "http://multiplayer:5002"] - interval: 2s - timeout: 20s - retries: 10 diff --git a/docker/services/multiplayer/Dockerfile b/docker/services/multiplayer/Dockerfile deleted file mode 100644 index dd5797a94..000000000 --- a/docker/services/multiplayer/Dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM node:20-alpine3.16 - -RUN apk add --no-cache git -RUN apk add --no-cache g++ make py3-pip -RUN apk add --no-cache postgresql-client - -WORKDIR /app - -ARG MULTIPLAYER_BRANCH=main -ADD "https://api.github.com/repos/drips-network/multiplayer/commits/${MULTIPLAYER_BRANCH}?per_page=1" latest_commit -RUN git clone --branch ${MULTIPLAYER_BRANCH} --single-branch https://github.com/drips-network/multiplayer.git - -WORKDIR /app/multiplayer -RUN npm ci --fetch-timeout=600000 -COPY ./services/multiplayer/envfile .env.prod - -RUN npm run build - -COPY ./services/multiplayer/start.sh start.sh - -EXPOSE 5002 - -CMD ["sh", "start.sh"] diff --git a/docker/services/multiplayer/db/schema.sql b/docker/services/multiplayer/db/schema.sql deleted file mode 100644 index e03c16ba6..000000000 --- a/docker/services/multiplayer/db/schema.sql +++ /dev/null @@ -1 +0,0 @@ -CREATE SCHEMA sepolia; diff --git a/docker/services/multiplayer/envfile b/docker/services/multiplayer/envfile deleted file mode 100644 index 3df5b312c..000000000 --- a/docker/services/multiplayer/envfile +++ /dev/null @@ -1,14 +0,0 @@ -PORT=5002 -NETWORK=sepolia -DB_HOST=postgres-multiplayer -DB_PORT=5432 -DB_USER=user -DB_PASSWORD=admin -DB_NAME=dripsdb -LOG_LEVEL=debug -GRAPHQL_URL=http://drips-gql-api:8080 -GRAPHQL_TOKEN=afdb8b7e-8fa7-4de9-bd95-b650b839e745 -RPC_URL=http://testnet:8545 -ADDRESS_DRIVER_ADDRESS=0xcc137285FD4D8914Dae08629086309B89aA6FDef -REPO_DRIVER_ADDRESS=0xb9C8e18E82687a564Ac4D26E22D28a4C95057CE9 -API_KEY=1234 diff --git a/docker/services/multiplayer/start.sh b/docker/services/multiplayer/start.sh deleted file mode 100644 index 4e51d4970..000000000 --- a/docker/services/multiplayer/start.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -until pg_isready -U postgres -h postgres-multiplayer; do - echo "Postgres is unavailable - waiting" - sleep 2 -done -echo "Postgres is up - executing command" - -NODE_ENV=prod node dist/src/main.js diff --git a/docker/services/subgraph-deployer/scripts/clone-subgraph.sh b/docker/services/subgraph-deployer/scripts/clone-subgraph.sh index 1d96be867..f21df20c8 100644 --- a/docker/services/subgraph-deployer/scripts/clone-subgraph.sh +++ b/docker/services/subgraph-deployer/scripts/clone-subgraph.sh @@ -6,7 +6,7 @@ git clone -b feature/dependency-funding --single-branch https://github.com/radic echo "📁 Creating subgraph config file for local env" cd ./drips-subgraph -printf '{ "network": "sepolia", "immutableSplitsDriver": { "address": "0xEC8493BdbBbBe22a6F54573cFeE23ac8Ab90dF77", "block": 0 }, "repoDriver": { "address": "0xb9C8e18E82687a564Ac4D26E22D28a4C95057CE9", "block": 0 }, "drips": { "address": "0xa0523b86472561f0859d84C094cc04e6c4B33169", "block": 0 }, "nftDriver": { "address": "0xc95eb214845d5693abc750692161CB008796ae5C", "block": 0 },"metaData": { "address": "0xC58cEa5a448A761d2dE80DFa8BfE298780e9dd66", "block": 0 } }' > config.json +printf '{ "network": "goerli", "immutableSplitsDriver": { "address": "0xEC8493BdbBbBe22a6F54573cFeE23ac8Ab90dF77", "block": 0 }, "repoDriver": { "address": "0xb9C8e18E82687a564Ac4D26E22D28a4C95057CE9", "block": 0 }, "drips": { "address": "0xa0523b86472561f0859d84C094cc04e6c4B33169", "block": 0 }, "nftDriver": { "address": "0xc95eb214845d5693abc750692161CB008796ae5C", "block": 0 },"metaData": { "address": "0xC58cEa5a448A761d2dE80DFa8BfE298780e9dd66", "block": 0 } }' > config.json echo "🛠 Installing subgraph deps…" npm install diff --git a/docker/services/testnet/Dockerfile b/docker/services/testnet/Dockerfile index ecc5b44b9..9a683deaf 100644 --- a/docker/services/testnet/Dockerfile +++ b/docker/services/testnet/Dockerfile @@ -2,4 +2,4 @@ FROM ghcr.io/foundry-rs/foundry:latest COPY ./services/testnet/state state -ENTRYPOINT anvil --chain-id 11155111 --state ./state --mnemonic "fame elevator saddle renew match guilt seat duck seven buyer true smoke" --host 0.0.0.0 --block-time 2 \ No newline at end of file +ENTRYPOINT anvil --chain-id 5 --state ./state --mnemonic "fame elevator saddle renew match guilt seat duck seven buyer true smoke" --host 0.0.0.0 --block-time 2 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b18721aef..4a1ddcfff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,8 @@ "@octokit/rest": "^19.0.7", "@pinata/sdk": "^1.1.26", "@resvg/resvg-js": "^2.6.0", - "@safe-global/safe-apps-provider": "^0.18.2", - "@safe-global/safe-apps-sdk": "^9.0.0", + "@safe-global/safe-apps-provider": "^0.16.0", + "@safe-global/safe-apps-sdk": "^7.10.0", "@sveltejs/adapter-netlify": "^2.0.6", "@tanstack/svelte-table": "^8.5.15", "@uniswap/default-token-list": "^11.15.0", @@ -97,11 +97,6 @@ "integrity": "sha512-DA5a1C0gD/pLOvhv33YMrbf2FK3oUzwNl9oOJqE4XVjuEtt6XIakRcsd7eLiOSPkp1kTRQGICTA8cKra/vFbjw==", "dev": true }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==" - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -4123,28 +4118,6 @@ "tslib": "^2.3.1" } }, - "node_modules/@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4745,107 +4718,21 @@ } }, "node_modules/@safe-global/safe-apps-provider": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.2.tgz", - "integrity": "sha512-yHHAcppwE7aIUWEeZiYAClQzZCdP5l0Kbd0CBlhKAsTcqZnx4Gh3G3G3frY5LlWcGzp9qmQ5jv+J1GBpaZLDgw==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-provider/-/safe-apps-provider-0.16.0.tgz", + "integrity": "sha512-oeRlvU+2hjFx/7EbskGq30kkwL2hyfdseZZZYf6na/xD85mZ59zKO81lBxZcWnvofJFqjqtScz84PAKth9Sq2g==", "dependencies": { - "@safe-global/safe-apps-sdk": "^9.0.0", + "@safe-global/safe-apps-sdk": "7.10.0", "events": "^3.3.0" } }, "node_modules/@safe-global/safe-apps-sdk": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.0.0.tgz", - "integrity": "sha512-fEqmQBU3JqTjORSl3XYrcaxdxkUqeeM39qsQjqCzzTHioN8DEfg3JCLq6EBoXzcKTVOYi8SPzLV7KJccdDw+4w==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/@safe-global/safe-apps-sdk/-/safe-apps-sdk-7.10.0.tgz", + "integrity": "sha512-is0QAHVoGkP06YfOPcp4X3/YUEA3wRdgFUyKZ4rT47uOEnzxA9Sm8BFJrIZqZOjjqC+aJXRMF0cE2qucS953rg==", "dependencies": { "@safe-global/safe-gateway-typescript-sdk": "^3.5.3", - "viem": "^1.6.0" - } - }, - "node_modules/@safe-global/safe-apps-sdk/node_modules/abitype": { - "version": "0.9.8", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.9.8.tgz", - "integrity": "sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.19.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/@safe-global/safe-apps-sdk/node_modules/typescript": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", - "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/@safe-global/safe-apps-sdk/node_modules/viem": { - "version": "1.21.4", - "resolved": "https://registry.npmjs.org/viem/-/viem-1.21.4.tgz", - "integrity": "sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "0.9.8", - "isows": "1.0.3", - "ws": "8.13.0" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@safe-global/safe-apps-sdk/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "ethers": "^5.7.2" } }, "node_modules/@safe-global/safe-gateway-typescript-sdk": { @@ -4856,39 +4743,6 @@ "cross-fetch": "^3.1.5" } }, - "node_modules/@scure/base": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", - "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", - "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", - "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@shuding/opentype.js": { "version": "1.4.0-beta.0", "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz", @@ -12875,20 +12729,6 @@ "ws": "*" } }, - "node_modules/isows": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", - "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" - } - ], - "peerDependencies": { - "ws": "*" - } - }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -18302,6 +18142,7 @@ "version": "8.14.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "dev": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 1b50ad2f0..312f3ad39 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,9 @@ "local-env:start": "docker compose -f ./docker/env.docker-compose.yml -f ./docker/env-ports-exposed.docker-compose.yml up --build --always-recreate-deps --force-recreate -V", "local-env:stop": "docker compose -f ./docker/env.docker-compose.yml -f ./docker/env-ports-exposed.docker-compose.yml down", "build": "vite build", - "build:e2e": "MULTIPLAYER_API_URL=http://multiplayer:5001 MULTIPLAYER_API_ACCESS_TOKEN=1234 GQL_URL=http://localhost:8080 PUBLIC_PINATA_GATEWAY_URL=http://localhost:3000 GQL_ACCESS_TOKEN=afdb8b7e-8fa7-4de9-bd95-b650b839e745 VITE_TEST_MODE=true npm run build", + "build:e2e": "GQL_URL=http://localhost:8080 PUBLIC_PINATA_GATEWAY_URL=http://localhost:3000 GQL_ACCESS_TOKEN=afdb8b7e-8fa7-4de9-bd95-b650b839e745 VITE_TEST_MODE=true npm run build", "preview": "vite preview", - "test:e2e": "MULTIPLAYER_API_URL=http://multiplayer:5001 MULTIPLAYER_API_ACCESS_TOKEN=1234 PUBLIC_TEST_MODE=true vitest run e2e", + "test:e2e": "PUBLIC_TEST_MODE=true vitest run e2e", "test:unit": "vitest run unit", "e2e": "docker compose -f ./docker/env.docker-compose.yml -f ./docker/app-e2e-test.docker-compose.yml up --build --attach app --exit-code-from app --abort-on-container-exit --always-recreate-deps --force-recreate -V", "coverage": "vitest run --coverage", @@ -75,8 +75,8 @@ "@octokit/rest": "^19.0.7", "@pinata/sdk": "^1.1.26", "@resvg/resvg-js": "^2.6.0", - "@safe-global/safe-apps-provider": "^0.18.2", - "@safe-global/safe-apps-sdk": "^9.0.0", + "@safe-global/safe-apps-provider": "^0.16.0", + "@safe-global/safe-apps-sdk": "^7.10.0", "@sveltejs/adapter-netlify": "^2.0.6", "@tanstack/svelte-table": "^8.5.15", "@uniswap/default-token-list": "^11.15.0", diff --git a/src/e2e-tests/top-up-create-stream.e2e.test.ts b/src/e2e-tests/top-up-create-stream.e2e.test.ts index 5eb3c3034..4d55e77aa 100644 --- a/src/e2e-tests/top-up-create-stream.e2e.test.ts +++ b/src/e2e-tests/top-up-create-stream.e2e.test.ts @@ -444,28 +444,11 @@ describe('app', async () => { await expect(page.locator('h1:has-text("Create a Drip List")')).toHaveCount(1); }); - it('renames the drip list', async () => { - const titleField = page.locator('label:has-text("Title*")'); - await titleField.clear(); - await titleField.fill('This is a Test Drip List'); - }); - - it('gives a description', async () => { - await page.locator('label:has-text("Description")').fill('This is my list description.'); - }); - - it('selects choose yourself option', async () => { - await page.locator('text=Choose by yourself').click(); - await page.locator('text=Continue').click(); - - await expect(page.locator('h1:has-text("Create a Drip List")')).toHaveCount(1); - }); - it('adds items', async () => { console.log(1); const input = page.locator( - 'input[placeholder="GitHub URL, ETH address, or Drip List URL"]', + 'input[placeholder="GitHub URL, Ethereum address, or Drip List URL"]', ); await expect(input).toHaveCount(1); await input.click(); @@ -478,9 +461,7 @@ describe('app', async () => { console.log(4); await expect( - page.locator( - 'data-testid=item-80921553623925136102837120782793736893291544351678576578072673071408', - ), + page.locator('data-testid=item-https://github.com/efstajas/drips-test-repo-10'), ).toHaveCount(1); console.log(5); @@ -493,12 +474,26 @@ describe('app', async () => { console.log(7); await expect( - page.locator('data-testid=item-383620263794848526656662033323214000554911775452'), + page.locator('data-testid=item-0x433220a86126eFe2b8C98a723E73eBAd2D0CbaDc'), ).toHaveCount(1); console.log(8); }); + it('assigns equal percentages', async () => { + await page.locator('button', { hasText: 'Split evenly' }).click(); + }); + + it('renames the drip list', async () => { + const titleField = page.locator('label:has-text("Title*")'); + await titleField.clear(); + await titleField.fill('This is a Test Drip List'); + }); + + it('gives a description', async () => { + await page.locator('label:has-text("Description")').fill('This is my list description.'); + }); + it('advances the flow', async () => { await page.locator('button', { hasText: 'Continue' }).click(); }); @@ -544,8 +539,8 @@ describe('app', async () => { it('creates the drip list', async () => { await page.locator('button', { hasText: 'Confirm in wallet' }).click(); - await expect(page.locator('text=Congratulations!')).toHaveCount(1, { timeout: 20000 }); - }, 30000); + await expect(page.locator('text=Congratulations!')).toHaveCount(1, { timeout: 10000 }); + }, 10000); }); describe('edit drip list', () => { @@ -563,14 +558,14 @@ describe('app', async () => { }); it('removes an item', async () => { - await page.getByTestId('remove-383620263794848526656662033323214000554911775452').click(); + await page.getByTestId('remove-0x433220a86126eFe2b8C98a723E73eBAd2D0CbaDc').click(); await expect(page.locator('text=50% split')).toHaveCount(1); }); it('adds a new item', async () => { await page - .locator('input[placeholder="GitHub URL, ETH address, or Drip List URL"]') + .locator('input[placeholder="GitHub URL, Ethereum address, or Drip List URL"]') .click(); await page.keyboard.type('github.com/efstajas/drips-test-repo-11'); diff --git a/src/lib/components/annotation-box/annotation-box.svelte b/src/lib/components/annotation-box/annotation-box.svelte index 85d6001a2..e0fead965 100644 --- a/src/lib/components/annotation-box/annotation-box.svelte +++ b/src/lib/components/annotation-box/annotation-box.svelte @@ -1,24 +1,18 @@
- {#if icon} - - {:else if type === 'warning'} + {#if type === 'warning'} - {:else if type === 'info'} - {:else} - + {/if}
@@ -46,15 +40,12 @@ .annotation-box.warning { background-color: var(--color-caution-level-1); + border: 1px solid var(--color-caution-level-6); color: var(--color-caution-level-6); } .annotation-box.info { background-color: var(--color-primary-level-1); - } - - .annotation-box.error { - background-color: var(--color-negative-level-1); - color: var(--color-negative-level-6); + border: 1px solid var(--color-primary-level-6); } diff --git a/src/lib/components/button/button.svelte b/src/lib/components/button/button.svelte index fdaa4675d..4e918476c 100644 --- a/src/lib/components/button/button.svelte +++ b/src/lib/components/button/button.svelte @@ -36,14 +36,10 @@ {rel} class="button size-{size}" class:disabled={isDisabled} - class:loading disabled={isDisabled} aria-disabled={isDisabled} on:click|stopPropagation data-testid={dataTestId} - on:mouseenter - on:mouseleave - on:focus >
- - - diff --git a/src/lib/components/countdown/countdown.svelte b/src/lib/components/countdown/countdown.svelte deleted file mode 100644 index 7f7e7edda..000000000 --- a/src/lib/components/countdown/countdown.svelte +++ /dev/null @@ -1,30 +0,0 @@ - - -{Math.floor(timeLeft / 1000 / 60 / 60 / 24)} day{Math.floor(timeLeft / 1000 / 60 / 60 / 24) === 1 - ? '' - : 's'}, {Math.floor(timeLeft / 1000 / 60 / 60) % 24} hours, -{Math.floor(timeLeft / 1000 / 60) % 60} minutes, {Math.floor(timeLeft / 1000) % 60} seconds diff --git a/src/lib/components/date-picker/DateInput.svelte b/src/lib/components/date-picker/DateInput.svelte deleted file mode 100644 index 4419f52db..000000000 --- a/src/lib/components/date-picker/DateInput.svelte +++ /dev/null @@ -1,268 +0,0 @@ - - - - -
- (visible = true)} - on:mousedown={() => (visible = true)} - on:input={(e) => { - if ( - e instanceof InputEvent && - e.inputType === 'insertText' && - typeof e.data === 'string' && - e.currentTarget instanceof HTMLInputElement && - e.currentTarget?.value === text + e.data - ) { - // check for missing punctuation, and add if there is any - let result = parse(text, formatTokens, $store); - if (result.missingPunctuation !== '' && !result.missingPunctuation.startsWith(e.data)) { - text = text + result.missingPunctuation + e.data; - return; - } - } - - if (e instanceof InputEvent && e.currentTarget instanceof HTMLInputElement) { - text = e.currentTarget?.value; - } - }} - /> - {#if visible && !disabled} -
- -
- {/if} -
- - diff --git a/src/lib/components/date-picker/DatePicker.svelte b/src/lib/components/date-picker/DatePicker.svelte deleted file mode 100644 index c8478d3d0..000000000 --- a/src/lib/components/date-picker/DatePicker.svelte +++ /dev/null @@ -1,504 +0,0 @@ - - - - - -
-
-
- - - - -
-
- - {#each Array(7) as _, i} - {#if i + iLocale.weekStartsOn < 7} -
{iLocale.weekdays[iLocale.weekStartsOn + i]}
- {:else} -
{iLocale.weekdays[iLocale.weekStartsOn + i - 7]}
- {/if} - {/each} -
- - {#each Array(6) as _, weekIndex} -
- {#each calendarDays.slice(weekIndex * 7, weekIndex * 7 + 7) as calendarDay} - -
selectDay(calendarDay)} - class:disabled={!dayIsInRange(calendarDay, min, max)} - class:selected={value && - calendarDay.year === value.getFullYear() && - calendarDay.month === value.getMonth() && - calendarDay.number === value.getDate()} - class:today={calendarDay.year === todayDate.getFullYear() && - calendarDay.month === todayDate.getMonth() && - calendarDay.number === todayDate.getDate()} - class:other-month={calendarDay.month !== browseMonth} - > - {calendarDay.number} -
- {/each} -
- {/each} - - -
-
- - diff --git a/src/lib/components/date-picker/TimePicker.svelte b/src/lib/components/date-picker/TimePicker.svelte deleted file mode 100644 index ee22303be..000000000 --- a/src/lib/components/date-picker/TimePicker.svelte +++ /dev/null @@ -1,212 +0,0 @@ - - - -{#if timePrecision} -
{ - if (e.target instanceof HTMLElement && e.target.tagName === 'SPAN') { - e.target.focus(); - e.preventDefault(); // prevent text dragging - } - }} - > - {('00' + browseDate.getHours()).slice(-2)}: - {('00' + browseDate.getMinutes()).slice(-2)} - {#if timePrecision !== 'minute'} - :{('00' + browseDate.getSeconds()).slice(-2)} - {#if timePrecision !== 'second'} - .{('000' + browseDate.getMilliseconds()).slice(-3)} - {/if} - {/if} -
-{/if} - - diff --git a/src/lib/components/date-picker/date-utils.ts b/src/lib/components/date-picker/date-utils.ts deleted file mode 100644 index 2c1b554bc..000000000 --- a/src/lib/components/date-picker/date-utils.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - Adapted from https://github.com/probablykasper/date-picker-svelte - Credit to Kasper Henningsen & Contributors! -*/ - -import type { FormatToken } from './parse.js'; - -export function isLeapYear(year: number): boolean { - return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; -} -export function getMonthLength(year: number, month: number): number { - const feb = isLeapYear(year) ? 29 : 28; - const monthLengths = [31, feb, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; - return monthLengths[month]; -} - -export function toText(date: Date | null, formatTokens: FormatToken[]): string { - let text = ''; - if (date) { - for (const token of formatTokens) { - if (typeof token === 'string') { - text += token; - } else { - text += token.toString(date); - } - } - } - return text; -} - -export type CalendarDay = { - year: number; - month: number; - number: number; -}; -export function getMonthDays(year: number, month: number): CalendarDay[] { - const monthLength = getMonthLength(year, month); - const days: CalendarDay[] = []; - for (let i = 0; i < monthLength; i++) { - days.push({ - year: year, - month: month, - number: i + 1, - }); - } - return days; -} -export function getCalendarDays(value: Date, weekStartsOn: number): CalendarDay[] { - const year = value.getFullYear(); - const month = value.getMonth(); - const firstWeekday = new Date(year, month, 1).getDay(); - - let days: CalendarDay[] = []; - - // add last month - const daysBefore = (firstWeekday - weekStartsOn + 7) % 7; - if (daysBefore > 0) { - let lastMonth = month - 1; - let lastMonthYear = year; - if (lastMonth === -1) { - lastMonth = 11; - lastMonthYear = year - 1; - } - days = getMonthDays(lastMonthYear, lastMonth).slice(-daysBefore); - } - - // add current month - days = days.concat(getMonthDays(year, month)); - - // add next month - let nextMonth = month + 1; - let nextMonthYear = year; - if (nextMonth === 12) { - nextMonth = 0; - nextMonthYear = year + 1; - } - const daysAfter = 42 - days.length; - days = days.concat(getMonthDays(nextMonthYear, nextMonth).slice(0, daysAfter)); - - return days; -} diff --git a/src/lib/components/date-picker/index.ts b/src/lib/components/date-picker/index.ts deleted file mode 100644 index d9c89b5d4..000000000 --- a/src/lib/components/date-picker/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - Adapted from https://github.com/probablykasper/date-picker-svelte - Credit to Kasper Henningsen & Contributors! -*/ - -export { default as DatePicker } from './DatePicker.svelte'; -export { default as DateInput } from './DateInput.svelte'; - -export { localeFromDateFnsLocale, type Locale } from './locale.js'; diff --git a/src/lib/components/date-picker/locale.ts b/src/lib/components/date-picker/locale.ts deleted file mode 100644 index 06be29909..000000000 --- a/src/lib/components/date-picker/locale.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - Adapted from https://github.com/probablykasper/date-picker-svelte - Credit to Kasper Henningsen & Contributors! -*/ - -export type Locale = { - weekdays?: string[]; - months?: string[]; - weekStartsOn?: number; -}; -type InnerLocale = { - weekdays: string[]; - months: string[]; - weekStartsOn: number; -}; -export function getLocaleDefaults(): InnerLocale { - return { - weekdays: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], - months: [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ], - weekStartsOn: 1, - }; -} -export function getInnerLocale(locale: Locale = {}): InnerLocale { - const innerLocale = getLocaleDefaults(); - if (typeof locale.weekStartsOn === 'number') { - innerLocale.weekStartsOn = locale.weekStartsOn; - } - if (locale.months) innerLocale.months = locale.months; - if (locale.weekdays) innerLocale.weekdays = locale.weekdays; - return innerLocale; -} - -type DateFnsLocale = { - options?: { - weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6; - }; - localize?: { - month: (n: number, options?: { width?: string }) => string; - day: (i: number, options?: { width?: string }) => string; - }; -}; -/** Create a Locale from a date-fns locale */ -export function localeFromDateFnsLocale(dateFnsLocale: DateFnsLocale): InnerLocale { - const locale = getLocaleDefaults(); - if (typeof dateFnsLocale?.options?.weekStartsOn === 'number') { - locale.weekStartsOn = dateFnsLocale.options.weekStartsOn; - } - if (dateFnsLocale.localize) { - for (let i = 0; i < 7; i++) { - // widths: narrow, short, abbreviated, wide, any - locale.weekdays[i] = dateFnsLocale.localize.day(i, { width: 'short' }); - } - - for (let i = 0; i < 12; i++) { - locale.months[i] = dateFnsLocale.localize.month(i, { width: 'wide' }); - } - } - return locale; -} diff --git a/src/lib/components/date-picker/parse.ts b/src/lib/components/date-picker/parse.ts deleted file mode 100644 index efe61ccdb..000000000 --- a/src/lib/components/date-picker/parse.ts +++ /dev/null @@ -1,166 +0,0 @@ -/* - Adapted from https://github.com/probablykasper/date-picker-svelte - Credit to Kasper Henningsen & Contributors! -*/ - -import { getMonthLength } from './date-utils.js'; - -type RuleToken = { - id: string; - toString: (d: Date) => string; -}; - -export type FormatToken = string | RuleToken; - -type ParseResult = { - date: Date | null; - missingPunctuation: string; -}; -/** Parse a string according to the supplied format tokens. Returns a date if successful, and the missing punctuation if there is any that should be after the string */ -export function parse(str: string, tokens: FormatToken[], baseDate: Date | null): ParseResult { - let missingPunctuation = ''; - let valid = true; - - baseDate = baseDate || new Date(2020, 0, 1, 0, 0, 0, 0); - let year = baseDate.getFullYear(); - let month = baseDate.getMonth(); - let day = baseDate.getDate(); - let hours = baseDate.getHours(); - let minutes = baseDate.getMinutes(); - let seconds = baseDate.getSeconds(); - const ms = baseDate.getMilliseconds(); - - function parseString(token: string) { - for (let i = 0; i < token.length; i++) { - if (str.startsWith(token[i])) { - str = str.slice(1); - } else { - valid = false; - if (str.length === 0) missingPunctuation = token.slice(i); - return; - } - } - } - - function parseUint(pattern: RegExp, min: number, max: number) { - const matches = str.match(pattern); - if (matches?.[0]) { - str = str.slice(matches[0].length); - const n = parseInt(matches[0]); - if (n > max || n < min) { - valid = false; - return null; - } else { - return n; - } - } else { - valid = false; - return null; - } - } - - function parseToken(token: FormatToken) { - if (typeof token === 'string') { - parseString(token); - } else if (token.id === 'yy') { - const value = parseUint(/^[0-9]{2}/, 0, 99); - if (value !== null) year = 2000 + value; - } else if (token.id === 'yyyy') { - const value = parseUint(/^[0-9]{4}/, 0, 9999); - if (value !== null) year = value; - } else if (token.id === 'MM') { - const value = parseUint(/^[0-9]{2}/, 1, 12); - if (value !== null) month = value - 1; - } else if (token.id === 'dd') { - const value = parseUint(/^[0-9]{2}/, 1, 31); - if (value !== null) day = value; - } else if (token.id === 'HH') { - const value = parseUint(/^[0-9]{2}/, 0, 23); - if (value !== null) hours = value; - } else if (token.id === 'mm') { - const value = parseUint(/^[0-9]{2}/, 0, 59); - if (value !== null) minutes = value; - } else if (token.id === 'ss') { - const value = parseUint(/^[0-9]{2}/, 0, 59); - if (value !== null) seconds = value; - } - } - - for (const token of tokens) { - parseToken(token); - if (!valid) break; - } - - const monthLength = getMonthLength(year, month); - if (day > monthLength) { - valid = false; - } - - return { - date: valid ? new Date(year, month, day, hours, minutes, seconds, ms) : null, - missingPunctuation: missingPunctuation, - }; -} - -function twoDigit(value: number) { - return ('0' + value.toString()).slice(-2); -} - -const ruleTokens: RuleToken[] = [ - { - id: 'yyyy', - toString: (d: Date) => d.getFullYear().toString(), - }, - { - id: 'yy', - toString: (d: Date) => d.getFullYear().toString().slice(-2), - }, - { - id: 'MM', - toString: (d: Date) => twoDigit(d.getMonth() + 1), - }, - { - id: 'dd', - toString: (d: Date) => twoDigit(d.getDate()), - }, - { - id: 'HH', - toString: (d: Date) => twoDigit(d.getHours()), - }, - { - id: 'mm', - toString: (d: Date) => twoDigit(d.getMinutes()), - }, - { - id: 'ss', - toString: (d: Date) => twoDigit(d.getSeconds()), - }, -]; -function parseRule(s: string) { - for (const token of ruleTokens) { - if (s.startsWith(token.id)) { - return token; - } - } -} - -export function createFormat(s: string): FormatToken[] { - const tokens = []; - while (s.length > 0) { - const token = parseRule(s); - if (token) { - // parsed a token like "yyyy" - tokens.push(token); - s = s.slice(token.id.length); - } else if (typeof tokens[tokens.length - 1] === 'string') { - // last token is a string token, so append to it - tokens[tokens.length - 1] += s[0]; - s = s.slice(1); - } else { - // add string token - tokens.push(s[0]); - s = s.slice(1); - } - } - return tokens; -} diff --git a/src/lib/components/drip-list-card/components/voting-round-collaborators.svelte b/src/lib/components/drip-list-card/components/voting-round-collaborators.svelte deleted file mode 100644 index 017111f9b..000000000 --- a/src/lib/components/drip-list-card/components/voting-round-collaborators.svelte +++ /dev/null @@ -1,208 +0,0 @@ - - - -
- {#if votingRound.areVotesPrivate && collaborator?.isCollaborator && $walletStore.address && votingRound.status === 'Started'} - - modal.show( - Stepper, - undefined, - voteFlowSteps(votingRound, collaborator ?? undefined), - ), - buttonProps: { - variant: 'primary', - icon: Proposals, - }, - }, - }, - }, - }} - /> - {/if} - {#if votingRound.votes || revealedVotes} - [ - v.collaboratorAddress, - { - type: 'address', - address: v.collaboratorAddress, - rightComponent: getCollaboratorRightButton($walletStore.address, v), - }, - ]), - )} - /> - {:else if votingRound.areVotesPrivate} -
-

Collaborators hidden

-

The owner of this list chose to hide collaborators and their votes.

- {#if isOwnVotingRound} -
- -
- {/if} -
- {/if} -
-
- - diff --git a/src/lib/components/drip-list-card/components/voting-round-countdown.svelte b/src/lib/components/drip-list-card/components/voting-round-countdown.svelte deleted file mode 100644 index 82d295415..000000000 --- a/src/lib/components/drip-list-card/components/voting-round-countdown.svelte +++ /dev/null @@ -1,31 +0,0 @@ - - - - {#if $status === 'Completed' || $status === 'PendingLinkCompletion'} -

- {formatDate(new Date(votingRound.schedule.voting.endsAt), 'verbose')} your time. -

- {:else} -

- -

-

- That's {formatDate(new Date(votingRound.schedule.voting.endsAt), 'verbose')} your time. -

- {/if} -
diff --git a/src/lib/components/drip-list-card/components/voting-round-notice-card.svelte b/src/lib/components/drip-list-card/components/voting-round-notice-card.svelte deleted file mode 100644 index fbd36a5a2..000000000 --- a/src/lib/components/drip-list-card/components/voting-round-notice-card.svelte +++ /dev/null @@ -1,94 +0,0 @@ - - -{#if $status === 'Started'} -
- - This list is in voting. - - - - -
-{:else if ($status === 'Completed' || $status === 'PendingLinkCompletion') && !votingRound.result} -
- - Voting has ended but no collaborators voted. - - {#if isPublisher} - - {/if} - - -
-{:else if ($status === 'Completed' || $status === 'PendingLinkCompletion') && isPublisher} -
- - Voting has ended. You can now publish. - - - - -
-{:else if $status === 'Completed' || $status === 'PendingLinkCompletion'} -
- - Voting has ended. Waiting for the owner to publish this Drip List on-chain. - -
-{/if} - - diff --git a/src/lib/components/drip-list-card/components/voting-round-splits.svelte b/src/lib/components/drip-list-card/components/voting-round-splits.svelte deleted file mode 100644 index 05a84572b..000000000 --- a/src/lib/components/drip-list-card/components/voting-round-splits.svelte +++ /dev/null @@ -1,66 +0,0 @@ - - - -
- {#if !votingRound.result && $status === 'Started'} -
- -

Awaiting votes

- {#if votingRound.areVotesPrivate} -

Vote results will be revealed after the voting period ends.

- {:else} -

No one has voted yet.

- {/if} -
- {:else if (!votingRound.result || votingRound.result?.length === 0) && $status === 'Completed'} -
- -

No recipients

-

No collaborators voted.

-
- {:else if votingRound.splits} -
- -
- {/if} -
-
- - diff --git a/src/lib/components/drip-list-card/drip-list-card-representational.svelte b/src/lib/components/drip-list-card/drip-list-card-representational.svelte new file mode 100644 index 000000000..bd0626bc6 --- /dev/null +++ b/src/lib/components/drip-list-card/drip-list-card-representational.svelte @@ -0,0 +1,354 @@ + + + + + +
+
+
+

+ + {dripList.name} + +

+ {#if format === 'thumblink'} + + {:else} +
+ + {#if isOwnList} + + {/if} +
+ {/if} +
+ {#if (dripList.description ?? '').length > 0} +
+ + {dripList.description} + +
+ {/if} +
+ +
+
+
+ +
+
+ {#if browser} + + {/if} +  total +
+ {#if supportersPile && supportersPile.length > 0} +
+ Supported by + +
+ {/if} +
+
+ +
+
+
+
+ + + diff --git a/src/lib/components/drip-list-card/drip-list-card-thumblink.svelte b/src/lib/components/drip-list-card/drip-list-card-thumblink.svelte deleted file mode 100644 index 6459bb90a..000000000 --- a/src/lib/components/drip-list-card/drip-list-card-thumblink.svelte +++ /dev/null @@ -1,279 +0,0 @@ - - - - - -
-
-
-
- {dripList?.name || votingRound?.name} -
- {#if votingRound} - - {votingEnded ? 'Voting ended' : 'In voting'} - - {/if} -
- {#if (description ?? '').length > 0} -
- - {description} - -
- {/if} - {#if supportersPile && supportersPile.length > 0} -
- Supported by -
- {/if} -
- -
- {#if dripList || votingRound?.result} -
-
- -
- {#if dripList && browser} -
- -  total -
- {/if} -
- {/if} -
- {#if dripList} - - {:else if votingRound} - - {/if} -
-
-
-
- - - diff --git a/src/lib/components/drip-list-card/drip-list-card.svelte b/src/lib/components/drip-list-card/drip-list-card.svelte index 66f901c05..0a86f9676 100644 --- a/src/lib/components/drip-list-card/drip-list-card.svelte +++ b/src/lib/components/drip-list-card/drip-list-card.svelte @@ -1,110 +1,25 @@ -{#if votingRound} - -{/if} - -
-
-
-
-

- - {(dripList?.name || votingRound?.name) ?? unreachable()} - -

-
- - {#if isOwnList} - - {/if} -
-
- {#if (dripList?.description ?? votingRound?.description ?? '').length > 0} -
- - {dripList?.description || votingRound?.description} - -
- {/if} -
- Created by -
-
- -
- {#if dripList && votingRound} -
- -
- {/if} - - -
-
- {#if dripList} -
-
-
- -
-
- {#if browser} - - {/if} -  total -
- {#if supportersPile && supportersPile.length > 0} -
- Supported by - -
- {/if} -
-
-
- -
-
-
- {/if} -
- -
- {#if votingRound} -
-
- {#if votingRound.result} -
- -
- {/if} -
- -
-
-
- - - - - - {#if isOwnVotingRound} -
-
- -
- - {#if $votingRoundStatus === 'Completed' || $votingRoundStatus === 'PendingLinkCompletion'} -
- -
- {/if} -
- {/if} - {/if} -
-
-
-
-
-
- - + diff --git a/src/lib/components/drip-list-card/methods/get-supporters-pile.ts b/src/lib/components/drip-list-card/methods/get-supporters-pile.ts deleted file mode 100644 index 5a579755d..000000000 --- a/src/lib/components/drip-list-card/methods/get-supporters-pile.ts +++ /dev/null @@ -1,94 +0,0 @@ -import IdentityBadge from '$lib/components/identity-badge/identity-badge.svelte'; -import ProjectAvatar from '$lib/components/project-avatar/project-avatar.svelte'; -import type { Stream } from '$lib/stores/streams/types'; -import mapFilterUndefined from '$lib/utils/map-filter-undefined'; -import { gql } from 'graphql-request'; -import type { DripListCardSupporterPileFragment } from './__generated__/gql.generated'; - -export const DRIP_LIST_CARD_SUPPORTER_PILE_FRAGMENT = gql` - fragment DripListCardSupporterPile on DripList { - support { - ... on DripListSupport { - dripList { - owner { - address - } - } - } - ... on ProjectSupport { - project { - ...ProjectAvatar - } - } - ... on OneTimeDonationSupport { - account { - address - } - } - } - } -`; - -export default function getSupportersPile( - streams: Stream[], - support: DripListCardSupporterPileFragment['support'], -) { - let result = []; - - result.push( - ...mapFilterUndefined(support, (s) => { - switch (s.__typename) { - case 'DripListSupport': - return { - component: IdentityBadge, - props: { - address: s.dripList.owner.address, - showIdentity: false, - size: 'normal', - disableTooltip: true, - }, - }; - case 'ProjectSupport': - return { - component: ProjectAvatar, - props: { - project: s.project, - outline: true, - size: 'tiny', - }, - }; - case 'OneTimeDonationSupport': - return { - component: IdentityBadge, - props: { - address: s.account.address, - showIdentity: false, - size: 'normal', - disableTooltip: true, - }, - }; - } - }), - ); - - // If the owner is streaming to the list, we only want to show them once in the pile. - if (streams.length > 0) { - result.push({ - component: IdentityBadge, - props: { - address: streams[0].sender.address, - showIdentity: false, - size: 'normal', - disableTooltip: true, - }, - }); - } - - // Dedupe identity badges based on address prop - result = result.filter( - (item, index, self) => - self.findIndex((i) => i && item && i.props.address === item.props.address) === index, - ); - - return result.flat(); -} diff --git a/src/lib/components/drip-list-editor/drip-list-editor.svelte b/src/lib/components/drip-list-editor/drip-list-editor.svelte index 327c31e73..e71dab7b3 100644 --- a/src/lib/components/drip-list-editor/drip-list-editor.svelte +++ b/src/lib/components/drip-list-editor/drip-list-editor.svelte @@ -1,16 +1,18 @@ + + + +
+ {#if isEditable} +
+
+ +
+ e.key === 'Enter' && handleSubmitInput()} + on:paste={() => setTimeout(() => handleSubmitInput())} + class="typo-text" + type="text" + placeholder={inputPlaceholder} + /> + +
+ {/if} + {#if Object.keys(items).length > 0 || inputMessage} +
+ {#if inputMessage} +
+
+ {#if inputMessage.type === 'success'} + + {:else} + + {/if} +
+
+ {inputMessage.message} +
+
+ {/if} +
    + {#each Object.entries(items) as [slug, item], index} +
  • +
    +
    + {#if item.type === 'address'} + + {:else if item.type === 'project'} + + {:else if item.type === 'drip-list'} + + {/if} +
    +
    + +
    + {#if !isEditable} +
    {percentages[slug].toFixed(2).replace('.00', '')}%
    + {:else} + { + autoSplitEnabled = false; + }} + /> +
    +
  • + {/each} +
+
+ {/if} + {#if isEditable && Object.keys(items).length > 0} +
+
+ + + +
+
+ {#if hasEmptyPercents} + Empty inputs + {:else} + {Math.round(totalPercentage * 100) / 100}% split + {/if} +
+ + {#if !error && !valid} + + {/if} + + {#if error} +
+ +
+ {:else if valid} +
+ +
+ {/if} +
+
+
+ {/if} +
+ + diff --git a/src/lib/components/drip-list-members-editor/item-templates/drip-list.ts b/src/lib/components/drip-list-members-editor/item-templates/drip-list.ts new file mode 100644 index 000000000..f79238b08 --- /dev/null +++ b/src/lib/components/drip-list-members-editor/item-templates/drip-list.ts @@ -0,0 +1,9 @@ +import type { DripListMembersEditorDripListFragment } from '../__generated__/gql.generated'; +import type { ListItem } from '../drip-list-members-editor.svelte'; + +const dripListItem = (dripList: DripListMembersEditorDripListFragment): ListItem => ({ + type: 'drip-list', + list: dripList, +}); + +export default dripListItem; diff --git a/src/lib/components/drip-list-members-editor/item-templates/eth-address.ts b/src/lib/components/drip-list-members-editor/item-templates/eth-address.ts new file mode 100644 index 000000000..f9779020e --- /dev/null +++ b/src/lib/components/drip-list-members-editor/item-templates/eth-address.ts @@ -0,0 +1,8 @@ +import type { ListItem } from '../drip-list-members-editor.svelte'; + +const ethAddressItem: (address: string) => ListItem = (address: string) => ({ + type: 'address', + address, +}); + +export default ethAddressItem; diff --git a/src/lib/components/drip-list-members-editor/item-templates/project.ts b/src/lib/components/drip-list-members-editor/item-templates/project.ts new file mode 100644 index 000000000..1215211cf --- /dev/null +++ b/src/lib/components/drip-list-members-editor/item-templates/project.ts @@ -0,0 +1,11 @@ +import type { ListItem } from '../drip-list-members-editor.svelte'; +import type { DripListMembersEditorProjectFragment } from '../__generated__/gql.generated'; + +function projectItem(project: DripListMembersEditorProjectFragment): ListItem { + return { + type: 'project', + project, + } +}; + +export default projectItem; diff --git a/src/lib/components/drip-lists-section/drip-lists-section.svelte b/src/lib/components/drip-lists-section/drip-lists-section.svelte index 00b5d60bb..d5d12610e 100644 --- a/src/lib/components/drip-lists-section/drip-lists-section.svelte +++ b/src/lib/components/drip-lists-section/drip-lists-section.svelte @@ -1,9 +1,8 @@ @@ -105,7 +78,7 @@ }} skeleton={{ loaded: error || dripLists !== undefined, - empty: dripListsAndVotingRounds.length === 0 ?? undefined, + empty: (dripLists && dripLists.length === 0) ?? undefined, error, emptyStateEmoji: '🫗', emptyStateHeadline: isSelf ? 'You donʼt have any Drip Lists' : 'No Drip Lists', @@ -115,18 +88,12 @@ horizontalScroll: false, }} > - {#if dripListsAndVotingRounds} + {#if dripLists}
- {#each dripListsAndVotingRounds as list} - {#if list.type === 'drip-list'} - - {:else} - - {/if} + {#each dripLists as dripList} + {/each} {#if showCreateNewListCard}
Got a new idea?

You can create as many Drip Lists as you like.

- goto('/app/funder-onboarding')} + >Create a new Drip List
diff --git a/src/lib/components/emoji/emoji.ts b/src/lib/components/emoji/emoji.ts index 805c9ffd0..56e0e7ce7 100644 --- a/src/lib/components/emoji/emoji.ts +++ b/src/lib/components/emoji/emoji.ts @@ -1,5 +1,3 @@ -import type { ComponentType } from 'svelte'; - import CheckIcon from '$lib/components/icons/✅.svelte'; import WarningIcon from '$lib/components/icons/⚠️.svelte'; import GlobeIcon from '$lib/components/icons/🌐.svelte'; @@ -17,8 +15,7 @@ import PenIcon from '$lib/components/icons/✏️.svelte'; import ForwardIcon from '$lib/components/icons/⏩.svelte'; import BubblesIcon from '$lib/components/icons/🫧.svelte'; import HourglassIcon from '$lib/components/icons/⏳.svelte'; -import BallotIcon from '$lib/components/icons/🗳️.svelte'; -import FamilyIcon from '$lib/components/icons/👪.svelte'; +import type { ComponentType } from 'svelte'; export const CUSTOM_EMOJI_COMPONENTS: { [key: string]: ComponentType } = { ['✅']: CheckIcon, @@ -38,6 +35,4 @@ export const CUSTOM_EMOJI_COMPONENTS: { [key: string]: ComponentType } = { ['⏳']: HourglassIcon, ['✏️']: PenIcon, ['⏩']: ForwardIcon, - ['🗳️']: BallotIcon, - ['👪']: FamilyIcon, }; diff --git "a/src/lib/components/icons/\360\237\221\252.svelte" "b/src/lib/components/icons/\360\237\221\252.svelte" deleted file mode 100644 index f38e6c72b..000000000 --- "a/src/lib/components/icons/\360\237\221\252.svelte" +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git "a/src/lib/components/icons/\360\237\227\263\357\270\217.svelte" "b/src/lib/components/icons/\360\237\227\263\357\270\217.svelte" deleted file mode 100644 index e05a3e513..000000000 --- "a/src/lib/components/icons/\360\237\227\263\357\270\217.svelte" +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - diff --git a/src/lib/components/identity-badge/identity-badge.svelte b/src/lib/components/identity-badge/identity-badge.svelte index 5af191798..52bdb8ec4 100644 --- a/src/lib/components/identity-badge/identity-badge.svelte +++ b/src/lib/components/identity-badge/identity-badge.svelte @@ -99,7 +99,7 @@ > {toDisplay} {#if ens?.name && showFullAddress} -
{address}
+
{address}
{/if}
{#key toDisplay} @@ -113,7 +113,7 @@
{toDisplay}
{#if ens?.name && showFullAddress} -
+
{address}
{/if} diff --git a/src/lib/components/list-editor/components/list-editor-input.svelte b/src/lib/components/list-editor/components/list-editor-input.svelte deleted file mode 100644 index 93bf8ac4d..000000000 --- a/src/lib/components/list-editor/components/list-editor-input.svelte +++ /dev/null @@ -1,331 +0,0 @@ - - -
- {#if weightsMode} - - {:else} - - {/if} - - -
- -{#if currentError} - {@const color = currentError.severity === 'error' ? 'negative' : 'caution'} - {@const textColor = `var(--color-${color}-level-6)`} -
- - {currentError.message} -
-{/if} - - diff --git a/src/lib/components/list-editor/components/list-editor-item.svelte b/src/lib/components/list-editor/components/list-editor-item.svelte deleted file mode 100644 index b1f9f71ff..000000000 --- a/src/lib/components/list-editor/components/list-editor-item.svelte +++ /dev/null @@ -1,235 +0,0 @@ - - -
-
-
- {#if item.type === 'project'} - - {:else if item.type === 'address'} - - {:else if item.type === 'drip-list'} - - {/if} -
-
- -
- {#if weightsMode} - -
1000000} - > - - {formatPercentage(percentage)} - - % - -
- {/if} - - {#if item.rightComponent} - - {/if} - - {#if isEditable} -
-
- - diff --git a/src/lib/components/list-editor/components/list-editor-pie.svelte b/src/lib/components/list-editor/components/list-editor-pie.svelte deleted file mode 100644 index e15998364..000000000 --- a/src/lib/components/list-editor/components/list-editor-pie.svelte +++ /dev/null @@ -1,113 +0,0 @@ - - -
- {#if hasEmptyInputs} - Empty inputs - {:else} - {formatWeight(totalWeight)}% split - {/if} -
- - {#if !error && !valid} - - {/if} - - {#if error} -
- -
- {:else if valid} -
- -
- {/if} -
-
- - diff --git a/src/lib/components/list-editor/list-editor.svelte b/src/lib/components/list-editor/list-editor.svelte deleted file mode 100644 index 876a05be8..000000000 --- a/src/lib/components/list-editor/list-editor.svelte +++ /dev/null @@ -1,256 +0,0 @@ - - -
-
- {#if isEditable} - = maxItems} - on:addAddress={(e) => handleAddAddress(e.detail.accountId, e.detail.address)} - on:addProject={(e) => handleAddProject(e.detail.accountId, e.detail.project)} - on:addDripList={(e) => handleAddDripList(e.detail.accountId, e.detail.dripList)} - /> - {/if} - - {#if Object.keys(items).length > 0} -
- {#each Object.entries(items) as [key, item]} - handlePercentageEdit(key, e.detail)} - on:deleteItem={() => handleItemDelete(key)} - {item} - weight={weights[key]} - /> - {/each} -
- {/if} -
- - {#if weightsMode && isEditable} -
-
- - - -
- - v === 0)} /> -
- {/if} -
- - diff --git a/src/lib/components/list-editor/types.ts b/src/lib/components/list-editor/types.ts deleted file mode 100644 index db9074ad9..000000000 --- a/src/lib/components/list-editor/types.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { gql } from 'graphql-request'; -import { PROJECT_BADGE_FRAGMENT } from '../project-badge/project-badge.svelte'; -import { DRIP_LIST_BADGE_FRAGMENT } from '../drip-list-badge/drip-list-badge.svelte'; -import type { - ListEditorDripListFragment, - ListEditorProjectFragment, -} from './__generated__/gql.generated'; -import type { ComponentType } from 'svelte'; - -export const LIST_EDITOR_PROJECT_FRAGMENT = gql` - ${PROJECT_BADGE_FRAGMENT} - fragment ListEditorProject on Project { - ...ProjectBadge - } -`; - -export const LIST_EDITOR_DRIP_LIST_FRAGMENT = gql` - ${DRIP_LIST_BADGE_FRAGMENT} - fragment ListEditorDripList on DripList { - ...DripListBadge - } -`; - -type BaseItem = { - rightComponent?: { - component: ComponentType; - props: Record; - }; -}; - -type ProjectItem = BaseItem & { - type: 'project'; - project: ListEditorProjectFragment; -}; - -type DripListItem = BaseItem & { - type: 'drip-list'; - dripList: ListEditorDripListFragment; -}; - -type EthAddressItem = BaseItem & { - type: 'address'; - address: string; -}; - -export type ListEditorItem = ProjectItem | DripListItem | EthAddressItem; - -export type AccountId = string; - -export type Items = Record; -export type Weights = Record; diff --git a/src/lib/components/project-avatar/project-avatar.svelte b/src/lib/components/project-avatar/project-avatar.svelte index b16a54451..fa26303c4 100644 --- a/src/lib/components/project-avatar/project-avatar.svelte +++ b/src/lib/components/project-avatar/project-avatar.svelte @@ -35,7 +35,8 @@ type Size = 'tiny' | 'small' | 'medium' | 'large' | 'huge'; export let size: Size = 'small'; - export let outline = project.__typename === 'ClaimedProject'; + export let outline = + project.__typename === 'ClaimedProject' && project.avatar.__typename === 'ImageAvatar'; const CONTAINER_SIZES: Record = { tiny: '1.5rem', @@ -89,7 +90,7 @@
{:else if project.avatar.__typename === 'ImageAvatar'} -
+
(customImageLoading = false)} diff --git a/src/lib/components/project-badge/project-badge.svelte b/src/lib/components/project-badge/project-badge.svelte index d72444ffb..7c2ae4f75 100644 --- a/src/lib/components/project-badge/project-badge.svelte +++ b/src/lib/components/project-badge/project-badge.svelte @@ -54,6 +54,7 @@ export let hideAvatar = false; export let linkToNewTab = false; export let linkTo: 'external-url' | 'project-page' | 'nothing' = 'project-page'; + export let maxWidth: number | false = 320; export let size: 'tiny' | 'small' | 'medium' | 'large' | 'huge' = 'small'; let unclaimedProject: ProjectBadge_UnclaimedProject_Fragment; @@ -71,6 +72,7 @@ import { browser } from '$app/environment'; - import { createEventDispatcher } from 'svelte'; + import { createEventDispatcher, onMount, tick } from 'svelte'; type T = $$Generic; type Option = { title: string; value: V }[]; @@ -19,19 +19,25 @@ let selectorWidth: number; let selectorOffset: number; - let transition = false; - - function updateSelector(shouldTransition = false) { - transition = shouldTransition; + let initialRender = true; + async function updateSelector() { selectorOffset = (optionElems[active]?.offsetLeft ?? 4) - 4; selectorWidth = optionElems[active]?.offsetWidth ?? 0; + + await tick(); + + initialRender = false; } - $: active && updateSelector(true); + onMount(async () => { + updateSelector(); + }); + + $: active && updateSelector(); let containerElem: HTMLDivElement | undefined; - let containerResizeObserver = browser ? new ResizeObserver(() => updateSelector()) : undefined; + let containerResizeObserver = browser ? new ResizeObserver(updateSelector) : undefined; $: containerElem && containerResizeObserver?.observe(containerElem); $: dispatch('select', active); @@ -68,7 +74,7 @@
o.value === active) === 0} class:at-end={options.findIndex((o) => o.value === active) === options.length - 1} style="transform: translateX({selectorOffset}px); width: {selectorWidth}px;" @@ -113,10 +119,11 @@ top: 0.25rem; bottom: 0.25rem; border-radius: 0.25rem; + transition: all 0.3s; } - .selector.transition { - transition: transform 0.3s, width 0.3s, border-radius 0.3s; + .selector.initial-render { + transition: none; } .selector.at-beginning { diff --git a/src/lib/components/share-button/share-button.svelte b/src/lib/components/share-button/share-button.svelte index 13d562c61..527699023 100644 --- a/src/lib/components/share-button/share-button.svelte +++ b/src/lib/components/share-button/share-button.svelte @@ -5,15 +5,9 @@ import CopyIcon from '$lib/components/icons/Copy.svelte'; import CheckCircle from '$lib/components/icons/CheckCircle.svelte'; import { fade } from 'svelte/transition'; - import Button from '../button/button.svelte'; - import type { ComponentProps } from 'svelte'; export let text: string | undefined = undefined; export let url: string; - export let buttonVariant: ComponentProps + {:else} - + Copy link + {/if} diff --git a/src/lib/components/splits/components/split/split.svelte b/src/lib/components/splits/components/split/split.svelte index 3801966bd..a09be0b38 100644 --- a/src/lib/components/splits/components/split/split.svelte +++ b/src/lib/components/splits/components/split/split.svelte @@ -20,7 +20,6 @@ export let split: SplitsComponentSplitsReceiver | SplitGroup; export let linkToNewTab = false; export let isNested = false; - export let draft = false; /** Set to false to hide the chevron next to split groups. */ export let groupsExpandable = true; @@ -133,7 +132,7 @@
-
+
- - {getSplitPercent( - split.__typename === 'SplitGroup' ? calcGroupWeight(split) : split.weight, - 'pretty', - )} - + {getSplitPercent( + split.__typename === 'SplitGroup' ? calcGroupWeight(split) : split.weight, + 'pretty', + )}
{#if isFirst}
@@ -175,7 +171,7 @@ {:else if split.__typename === 'ProjectReceiver'} - + {:else if split.__typename === 'SplitGroup'}
{#if groupExpanded}
- +
{/if}
@@ -217,27 +213,11 @@ diff --git a/src/lib/components/status-badge/status-badge.svelte b/src/lib/components/status-badge/status-badge.svelte deleted file mode 100644 index ddb35fafe..000000000 --- a/src/lib/components/status-badge/status-badge.svelte +++ /dev/null @@ -1,62 +0,0 @@ - - -
- {#if icon} - - {:else} -
- {/if} - -
- - diff --git a/src/lib/components/step-header/step-header.svelte b/src/lib/components/step-header/step-header.svelte index 04f1bbd21..28e311965 100644 --- a/src/lib/components/step-header/step-header.svelte +++ b/src/lib/components/step-header/step-header.svelte @@ -2,13 +2,13 @@ import Emoji from '$lib/components/emoji/emoji.svelte'; export let emoji: string | undefined = undefined; - export let headline: string | undefined = undefined; + export let headline: string; export let description: string | undefined = undefined;
{#if emoji}{/if} - {#if headline}

{headline}

{/if} +

{headline}

{#if description}

{description}

{/if}
diff --git a/src/lib/components/stepper/utils/transact.ts b/src/lib/components/stepper/utils/transact.ts index 8f3d4e3f0..6702039a7 100644 --- a/src/lib/components/stepper/utils/transact.ts +++ b/src/lib/components/stepper/utils/transact.ts @@ -8,9 +8,9 @@ import { get } from 'svelte/store'; import type { Nullable } from 'vitest'; import type { StepComponentEvents, UpdateAwaitStepFn, UpdateAwaitStepParams } from '../types'; import unreachable from '$lib/utils/unreachable'; +import SafeAppsSDK from '$lib/stores/wallet/safe/sdk'; import assert from '$lib/utils/assert'; import isTest from '$lib/utils/is-test'; -import SafeAppsSDK, { type SendTransactionsResponse } from '@safe-global/safe-apps-sdk'; type BeforeFunc = () => PromiseLike | void>; @@ -42,19 +42,9 @@ export type TransactPayload> = { * to a Safe. * @param receipts An array of transaction receipts for all transactions described in `transactions`. * @param context Object with optional context returned from `before`. - * @returns A promise that will be awaited before moving on in the flow. + * @returns */ after?: (receipts: ContractReceipt[], context: Context) => PromiseLike; - /** - * Function to run after transctions have been proposed to a Safe. This function will ONLY run if the app is - * connected to a Safe. - * @param sendTransactionsResponse The response from the Safe Apps SDK after proposing the transactions. - * @returns A promise that will be awaited before moving on in the flow. - */ - afterSafe?: ( - sendTransactionsResponse: SendTransactionsResponse, - context: Context, - ) => PromiseLike; /** * Optionally specify custom messages that appear while the `before` and `after` steps are executed. */ @@ -138,7 +128,7 @@ export default function transact( assert(address); const safeAppMode = Boolean(safe); - const { before, transactions: transactionsBuilder, after, afterSafe, messages } = resolvedPayload; + const { before, transactions: transactionsBuilder, after, messages } = resolvedPayload; const receipts: ContractReceipt[] = []; @@ -150,12 +140,11 @@ export default function transact( const beforeResult = await before?.(); const transactionWrappers = await transactionsBuilder(beforeResult); - - let safeSendTransactionResponse: SendTransactionsResponse | undefined = undefined; + const isTxBatch = transactionWrappers.length > 1; // If we're in a Safe and need to process more than one transaction, we send them to the // Safe as a batch. - if (safeAppMode) { + if (safeAppMode && isTxBatch) { const safeAppsSdk = new SafeAppsSDK(); let estimatedGasWithBuffer: number; @@ -200,7 +189,7 @@ export default function transact( value: '0', })); - safeSendTransactionResponse = await safeAppsSdk.txs.send({ + await safeAppsSdk.txs.send({ txs, params: { safeTxGas: estimatedGasWithBuffer, @@ -280,16 +269,6 @@ export default function transact( ); await after?.(receipts, beforeResult); - } else if (afterSafe) { - updateAwaitStep( - messages?.duringAfter ?? { - message: 'Wrapping up...', - }, - ); - - assert(safeSendTransactionResponse, 'Expected SafeSendTransactionResponse to be defined.'); - - await afterSafe?.(safeSendTransactionResponse, beforeResult); } modal.setHideable(true); diff --git a/src/lib/components/stream-state-badge/stream-state-badge.svelte b/src/lib/components/stream-state-badge/stream-state-badge.svelte index ff158e97f..78eac0b2e 100644 --- a/src/lib/components/stream-state-badge/stream-state-badge.svelte +++ b/src/lib/components/stream-state-badge/stream-state-badge.svelte @@ -2,7 +2,6 @@ import balances from '$lib/stores/balances/balances.store'; import streams from '$lib/stores/streams'; import streamState, { STREAM_STATE_LABELS } from '$lib/utils/stream-state'; - import StatusBadge from '../status-badge/status-badge.svelte'; export let streamId: string; export let streamScheduledStart: Date | undefined = undefined; @@ -30,19 +29,62 @@ ); const colorMap = { - paused: 'caution', - active: 'positive', - ended: 'foreground', - scheduled: 'caution', - 'out-of-funds': 'negative', + paused: 'color-caution', + active: 'color-positive', + ended: 'color-foreground', + scheduled: 'color-caution', + 'out-of-funds': 'color-negative', } as const; - $: color = state ? colorMap[state] : undefined; + $: stateColor = state ? colorMap[state] : undefined; $: stateLabel = state ? STREAM_STATE_LABELS[state] : undefined; + + const textClasses = { + small: 'typo-text-small', + normal: 'typo-text', + large: 'typo-header-3', + }; {#if state && !(state === 'active' && hideActive)} - - {stateLabel} - +
+
+ {stateLabel} +
{/if} + + diff --git a/src/lib/components/success-step/success-step.svelte b/src/lib/components/success-step/success-step.svelte index 86bc2c506..02320fb62 100644 --- a/src/lib/components/success-step/success-step.svelte +++ b/src/lib/components/success-step/success-step.svelte @@ -16,6 +16,8 @@ export let safeAppMode = false; function handleConfirm() { + onAction?.(); + if (action === 'continue') { dispatch('goForward'); } else if (action === 'hide-modal') { @@ -23,8 +25,6 @@ } else { dispatch('conclude'); } - - onAction?.(); } diff --git a/src/lib/components/support-card/support-card.svelte b/src/lib/components/support-card/support-card.svelte index 35933e202..a47fb5284 100644 --- a/src/lib/components/support-card/support-card.svelte +++ b/src/lib/components/support-card/support-card.svelte @@ -80,17 +80,11 @@ import unreachable from '$lib/utils/unreachable'; import TransitionedHeight from '../transitioned-height/transitioned-height.svelte'; import SupportButtons from './components/support-buttons.svelte'; - import { BASE_URL } from '$lib/utils/base-url'; export let project: SupportCardProjectFragment | undefined = undefined; export let dripList: SupportCardDripListFragment | undefined = undefined; - export let draftListMode = false; - export let disabled = false; - $: { - if (!project && !dripList) disabled = true; - } $: type = project ? ('project' as const) : ('dripList' as const); @@ -106,7 +100,9 @@ if (project) { supportUrl = project.source.url; } else if (dripList) { - supportUrl = `${BASE_URL}/app/drip-lists/${dripList.account.accountId}`; + supportUrl = `https://drips.network/app/drip-lists/${dripList.account.accountId}`; + } else { + throw new Error('You must populate either the `project` or `dripList` prop.'); } } @@ -181,8 +177,6 @@ } async function onClickAddToDripList() { - if (!project && !dripList) return; - if (!ownDripLists) { goto(buildUrl('/app/funder-onboarding', { urlToAdd: supportUrl })); } else { @@ -207,7 +201,7 @@
- {#if !draftListMode && (ownDripLists === undefined || updating)} + {#if ownDripLists === undefined || updating}
@@ -226,7 +220,7 @@

Become a supporter

-

Donate once, continuously, or add this to your Drip List.

+

Donate once, continuously, or add them to your Drip List.

-
+
.tabbed-box { - border-top: 1px solid var(--color-foreground); + border: 1px solid var(--color-foreground); border-radius: 1rem 0 1rem 1rem; margin-top: 21px; position: relative; diff --git a/src/lib/components/table/cells/project-badge.cell.svelte b/src/lib/components/table/cells/project-badge.cell.svelte index d3503271b..76b2f5e3d 100644 --- a/src/lib/components/table/cells/project-badge.cell.svelte +++ b/src/lib/components/table/cells/project-badge.cell.svelte @@ -4,7 +4,6 @@ export let context: CellContext; - // eslint-disable-next-line @typescript-eslint/no-explicit-any let project: any; $: { @@ -13,5 +12,5 @@
- +
diff --git a/src/lib/components/text-input/text-input.svelte b/src/lib/components/text-input/text-input.svelte index 42f5d6f59..9ea6ab1ee 100644 --- a/src/lib/components/text-input/text-input.svelte +++ b/src/lib/components/text-input/text-input.svelte @@ -35,8 +35,6 @@ export let hint: string | undefined = undefined; export let suffix: string | undefined = undefined; - export let inputElement: HTMLInputElement | undefined = undefined; - export let validationState: TextInputValidationState = { type: 'unvalidated', }; @@ -45,6 +43,8 @@ inputElement && inputElement.focus(); }; + let inputElement: HTMLInputElement | undefined = undefined; + // Canʼt use normal `autofocus` attribute on the `inputElement`: "Autofocus // processing was blocked because a document's URL has a fragment". // preventScroll is necessary for onboarding animations to work. @@ -93,7 +93,6 @@ on:change on:click on:input - on:focus on:keydown on:keypress on:paste diff --git a/src/lib/components/two-big-options/components/option.svelte b/src/lib/components/two-big-options/components/option.svelte index 3abf1b4bc..8a7c672c4 100644 --- a/src/lib/components/two-big-options/components/option.svelte +++ b/src/lib/components/two-big-options/components/option.svelte @@ -22,7 +22,7 @@
-
+
{attribute.text}
@@ -48,7 +48,11 @@ z-index: 1; } - .option:hover { + .option.selected { + background-color: var(--color-primary-level-1); + } + + .option:hover:not(.selected) { background-color: var(--color-foreground-level-1); } @@ -56,10 +60,6 @@ box-shadow: 0px 0px 0px 2px var(--color-primary); } - .option.selected { - background-color: var(--color-primary-level-1); - } - .attributes { padding-top: 1rem; display: flex; diff --git a/src/lib/components/unclaimed-project-card/unclaimed-project-card.svelte b/src/lib/components/unclaimed-project-card/unclaimed-project-card.svelte index cbfe8c67f..1bd3e8870 100644 --- a/src/lib/components/unclaimed-project-card/unclaimed-project-card.svelte +++ b/src/lib/components/unclaimed-project-card/unclaimed-project-card.svelte @@ -73,7 +73,7 @@
{#if project}
- + {#if projectMetadata?.description}

{projectMetadata.description} diff --git a/src/lib/flows/claim-project-flow/claim-project-flow.ts b/src/lib/flows/claim-project-flow/claim-project-flow.ts index 1cec7dd7f..64b6bf5dc 100644 --- a/src/lib/flows/claim-project-flow/claim-project-flow.ts +++ b/src/lib/flows/claim-project-flow/claim-project-flow.ts @@ -1,4 +1,4 @@ -import { get, writable, type Writable } from 'svelte/store'; +import { writable } from 'svelte/store'; import type { Slots } from '../../components/standalone-flow-slots/standalone-flow-slots.svelte'; import { makeStep } from '$lib/components/stepper/types'; import ConnectWallet from './steps/connect-wallet/connect-wallet.svelte'; @@ -10,6 +10,7 @@ import AddEthereumAddress, { } from './steps/add-ethereum-address/add-ethereum-address.svelte'; import ProjectSlot from './slots/project-slot.svelte'; import SplitYourFunds from './steps/split-your-funds/split-your-funds.svelte'; +import type { ListEditorConfig } from '$lib/components/drip-list-members-editor/drip-list-members-editor.svelte'; import ConfigureMaintainers from './steps/configure-maintainers/configure-maintainers.svelte'; import ConfigureDependencies from './steps/configure-dependencies/configure-dependencies.svelte'; import Review, { REVIEW_STEP_PROJECT_FRAGMENT } from './steps/review/review.svelte'; @@ -20,7 +21,6 @@ import Success from './steps/success/success.svelte'; import WalletSlot from '$lib/components/slots/wallet-slot.svelte'; import { gql } from 'graphql-request'; import type { ClaimProjectFlowProject_UnclaimedProject_Fragment } from './__generated__/gql.generated'; -import type { Items, Weights } from '$lib/components/list-editor/types'; export const CLAIM_PROJECT_FLOW_PROJECT_FRAGMENT = gql` ${ENTER_GIT_URL_STEP_PROJECT_FRAGMENT} @@ -33,9 +33,8 @@ export const CLAIM_PROJECT_FLOW_PROJECT_FRAGMENT = gql` } `; -interface ListEditorConfig { - items: Items; - weights: Weights; +interface SplitsConfig extends ListEditorConfig { + itemsPromise: Promise[] | undefined; } interface Amount { @@ -63,8 +62,8 @@ export interface State { } | undefined; highLevelPercentages: { [key: string]: number }; - maintainerSplits: ListEditorConfig; - dependencySplits: ListEditorConfig; + maintainerSplits: SplitsConfig; + dependencySplits: SplitsConfig; dependenciesAutoImported: boolean; avatar: | { @@ -88,12 +87,14 @@ export const state = () => unclaimedFunds: undefined, highLevelPercentages: { maintainers: 60, dependencies: 40 }, maintainerSplits: { + itemsPromise: undefined, items: {}, - weights: {}, + percentages: {}, }, dependencySplits: { + itemsPromise: undefined, items: {}, - weights: {}, + percentages: {}, }, dependenciesAutoImported: false, avatar: { @@ -147,11 +148,11 @@ export function slotsTemplate(state: State, stepIndex: number): Slots { } export const steps = ( - state: Writable, skipWalletConnect = false, isModal = false, projectUrl: string | undefined = undefined, ) => [ + // TODO: skip this step entirely if project is provided (like "Claim project" button on project-profile) makeStep({ component: EnterGitUrl, props: { @@ -177,12 +178,10 @@ export const steps = ( makeStep({ component: ConfigureMaintainers, props: undefined, - condition: () => get(state).highLevelPercentages.maintainers > 0, }), makeStep({ component: ConfigureDependencies, props: undefined, - condition: () => get(state).highLevelPercentages.dependencies > 0, }), makeStep({ component: Review, diff --git a/src/lib/flows/claim-project-flow/claim-project-stepper.svelte b/src/lib/flows/claim-project-flow/claim-project-stepper.svelte index 64da9e965..3b1690c67 100644 --- a/src/lib/flows/claim-project-flow/claim-project-stepper.svelte +++ b/src/lib/flows/claim-project-flow/claim-project-stepper.svelte @@ -30,7 +30,7 @@ bind:currentStepIndex on:stepChange={() => window.scrollTo({ top: 0 })} context={() => myState} - steps={steps(myState, skipWalletConnect, true, projectUrl)} + steps={steps(skipWalletConnect, true, projectUrl)} minHeightPx={0} /> diff --git a/src/lib/flows/claim-project-flow/steps/add-ethereum-address/add-ethereum-address.svelte b/src/lib/flows/claim-project-flow/steps/add-ethereum-address/add-ethereum-address.svelte index c82aa1ec3..66f0f3f99 100644 --- a/src/lib/flows/claim-project-flow/steps/add-ethereum-address/add-ethereum-address.svelte +++ b/src/lib/flows/claim-project-flow/steps/add-ethereum-address/add-ethereum-address.svelte @@ -33,6 +33,7 @@ import type { Writable } from 'svelte/store'; import type { State } from '../../claim-project-flow'; import assert from '$lib/utils/assert'; + import ethAddressItem from '$lib/components/drip-list-members-editor/item-templates/eth-address'; import Checkbox from '$lib/components/checkbox/checkbox.svelte'; import GitHub from '$lib/utils/github/GitHub'; import { gql } from 'graphql-request'; @@ -52,19 +53,21 @@ function verify() { dispatch('await', { promise: async () => { - const { address, dripsAccountId } = $walletStore; - assert(address && dripsAccountId); + const { address } = $walletStore; + assert(address); - const addressInMaintainers = Boolean($context.maintainerSplits.items[dripsAccountId]); + const addressInMaintainers = $context.maintainerSplits.items[address]; const maintainersListEmpty = Object.keys($context.maintainerSplits.items).length === 0; if (!addressInMaintainers && maintainersListEmpty) { $context.maintainerSplits.items = { - [dripsAccountId]: { type: 'address', address }, + [address]: ethAddressItem(address), }; - $context.maintainerSplits.weights = { - [dripsAccountId]: 1000000, + $context.maintainerSplits.items[address] = ethAddressItem(address); + + $context.maintainerSplits.percentages = { + [address]: 100, }; } diff --git a/src/lib/flows/claim-project-flow/steps/configure-dependencies/configure-dependencies.svelte b/src/lib/flows/claim-project-flow/steps/configure-dependencies/configure-dependencies.svelte index 954f521f3..d7271c3dc 100644 --- a/src/lib/flows/claim-project-flow/steps/configure-dependencies/configure-dependencies.svelte +++ b/src/lib/flows/claim-project-flow/steps/configure-dependencies/configure-dependencies.svelte @@ -7,7 +7,10 @@ import Button from '$lib/components/button/button.svelte'; import type { Writable } from 'svelte/store'; import type { State } from '../../claim-project-flow'; - import ListEditor from '$lib/components/list-editor/list-editor.svelte'; + import ListEditor, { + type ListItem, + } from '$lib/components/drip-list-members-editor/drip-list-members-editor.svelte'; + import projectItem from '$lib/components/drip-list-members-editor/item-templates/project'; import mapFilterUndefined from '$lib/utils/map-filter-undefined'; const dispatch = createEventDispatcher(); @@ -20,8 +23,35 @@ if ($context.highLevelPercentages['dependencies'] === 0) { dispatch('goForward'); } + await fetchProjectDeps(); }); + async function fetchProjectDeps() { + try { + if ($context.dependencySplits.itemsPromise) { + const promises = $context.dependencySplits.itemsPromise.map((p) => + p.catch((error) => { + // eslint-disable-next-line no-console + console.log('💧 ~ Could not fetch project:', error); + return undefined; + }), + ); + + const depsGitProjects = mapFilterUndefined(await Promise.all(promises), (v) => v); + + let dependencySplits: { [key: string]: ListItem } = {}; + depsGitProjects.forEach((d) => { + dependencySplits[d.source.url] = projectItem(d); + }); + + $context.dependencySplits.items = dependencySplits; + } + } catch (error) { + // eslint-disable-next-line no-console + console.log('💧 ~ Could not fetch project dependencies:', error); + } + } + $: maintainerKeys = Object.keys($context.maintainerSplits.items); @@ -39,13 +69,11 @@ > v, - )} + allowedItems={['eth-addresses', 'projects', 'drip-lists']} + blockedKeys={[$context.gitUrl, ...maintainerKeys]} maxItems={200 - maintainerKeys.length} /> diff --git a/src/lib/flows/claim-project-flow/steps/configure-maintainers/configure-maintainers.svelte b/src/lib/flows/claim-project-flow/steps/configure-maintainers/configure-maintainers.svelte index 2ff008790..476de837b 100644 --- a/src/lib/flows/claim-project-flow/steps/configure-maintainers/configure-maintainers.svelte +++ b/src/lib/flows/claim-project-flow/steps/configure-maintainers/configure-maintainers.svelte @@ -2,17 +2,23 @@ import StandaloneFlowStepLayout from '$lib/components/standalone-flow-step-layout/standalone-flow-step-layout.svelte'; import ArrowRightIcon from '$lib/components/icons/ArrowRight.svelte'; import ArrowLeftIcon from '$lib/components/icons/ArrowLeft.svelte'; - import { createEventDispatcher } from 'svelte'; + import { createEventDispatcher, onMount } from 'svelte'; import type { StepComponentEvents } from '$lib/components/stepper/types'; import Button from '$lib/components/button/button.svelte'; import type { Writable } from 'svelte/store'; import type { State } from '../../claim-project-flow'; - import ListEditor from '$lib/components/list-editor/list-editor.svelte'; + import ListEditor from '$lib/components/drip-list-members-editor/drip-list-members-editor.svelte'; const dispatch = createEventDispatcher(); export let context: Writable; + onMount(async () => { + if ($context.highLevelPercentages['maintainers'] === 0) { + dispatch('goForward'); + } + }); + let formValid: boolean; $: dependencyKeys = Object.keys($context.dependencySplits.items); @@ -25,13 +31,12 @@ ]}% split to your project’s maintainers. In total, you can add up to 200 maintainers and dependencies, and change this list later anytime." > diff --git a/src/lib/flows/claim-project-flow/steps/review/review.svelte b/src/lib/flows/claim-project-flow/steps/review/review.svelte index 21c846c79..f1e0e83cb 100644 --- a/src/lib/flows/claim-project-flow/steps/review/review.svelte +++ b/src/lib/flows/claim-project-flow/steps/review/review.svelte @@ -72,13 +72,13 @@ $: dependencyRepresentationalSplits = mapSplitsFromListEditorData( $context.dependencySplits.items, - $context.dependencySplits.weights, + $context.dependencySplits.percentages, $context.highLevelPercentages['dependencies'], ); $: maintainerRepresentationalSplits = mapSplitsFromListEditorData( $context.maintainerSplits.items, - $context.maintainerSplits.weights, + $context.maintainerSplits.percentages, $context.highLevelPercentages['maintainers'], ); diff --git a/src/lib/flows/create-drip-list-flow/create-drip-list-flow.ts b/src/lib/flows/create-drip-list-flow/create-drip-list-flow.ts index a5e5f47f8..3502d021a 100644 --- a/src/lib/flows/create-drip-list-flow/create-drip-list-flow.ts +++ b/src/lib/flows/create-drip-list-flow/create-drip-list-flow.ts @@ -16,15 +16,9 @@ import ChooseSupportTypeStep from './steps/choose-support-type/choose-support-ty import WalletSlot from '$lib/components/slots/wallet-slot.svelte'; import DripListIcon from '$lib/components/icons/DripList.svelte'; import ConfigureOneTimeDonation from './steps/configure-one-time-donation/configure-one-time-donation.svelte'; -import ChooseCreationMode from './steps/choose-creation-mode/choose-creation-mode.svelte'; -import ConfigureVotingRound from './steps/configure-voting-round/configure-voting-round.svelte'; -import type { Items } from '$lib/components/list-editor/types'; -import ReviewVotingRound from './steps/review-voting-round/review-voting-round.svelte'; export interface State { dripList: DripListConfig; - /** 1 is immediate DL creation, 2 is creating a draft / voting round */ - selectedCreationMode: 1 | 2 | undefined; /** 1 is Continuous Support, 2 is one-time donation */ selectedSupportOption: 1 | 2 | undefined; continuousSupportConfig: { @@ -38,19 +32,12 @@ export interface State { topUpMax: boolean; amount: bigint | undefined; }; - votingRoundConfig: { - collaborators: Items; - votingEnds: Date | undefined; - areVotesPrivate: boolean; - }; - newVotingRoundId: string | undefined; dripListId: string | undefined; } export const state = () => writable({ - dripList: { title: 'My Drip List', weights: {}, items: {}, description: undefined }, - selectedCreationMode: undefined, + dripList: { title: 'My Drip List', percentages: {}, items: {}, description: undefined }, selectedSupportOption: undefined, continuousSupportConfig: { listSelected: [], @@ -61,12 +48,6 @@ export const state = () => topUpMax: false, amount: undefined, }, - votingRoundConfig: { - collaborators: {}, - votingEnds: undefined, - areVotesPrivate: false, - }, - newVotingRoundId: undefined, dripListId: undefined, }); @@ -93,7 +74,7 @@ export function slotsTemplate(state: State, stepIndex: number): Slots { return { component: DripListBadge, props: { - listId: item.dripList.account.accountId, + listId: item.list.account.accountId, }, }; } @@ -138,25 +119,11 @@ export function slotsTemplate(state: State, stepIndex: number): Slots { export const steps = (state: Writable, skipWalletConnect = false, isModal = false) => [ makeStep({ - component: ChooseCreationMode, + component: BuildListStep, props: { canCancel: isModal, }, }), - makeStep({ - component: BuildListStep, - props: undefined, - condition: () => { - return get(state).selectedCreationMode === 1; - }, - }), - makeStep({ - component: ConfigureVotingRound, - props: undefined, - condition: () => { - return get(state).selectedCreationMode === 2; - }, - }), ...(skipWalletConnect ? [] : [ @@ -168,22 +135,19 @@ export const steps = (state: Writable, skipWalletConnect = false, isModal makeStep({ component: ChooseSupportTypeStep, props: undefined, - condition: () => { - return get(state).selectedCreationMode === 1; - }, }), makeStep({ component: ConfigureContinuousSupportStep, props: undefined, condition: () => { - return get(state).selectedCreationMode === 1 && get(state).selectedSupportOption === 1; + return get(state).selectedSupportOption === 1; }, }), makeStep({ component: ConfigureOneTimeDonation, props: undefined, condition: () => { - return get(state).selectedCreationMode === 1 && get(state).selectedSupportOption === 2; + return get(state).selectedSupportOption === 2; }, }), makeStep({ @@ -191,16 +155,6 @@ export const steps = (state: Writable, skipWalletConnect = false, isModal props: { connectedWalletHidden: skipWalletConnect, }, - condition: () => { - return get(state).selectedCreationMode === 1; - }, - }), - makeStep({ - component: ReviewVotingRound, - props: undefined, - condition: () => { - return get(state).selectedCreationMode === 2; - }, }), makeStep({ component: Success, diff --git a/src/lib/flows/create-drip-list-flow/steps/build-list/build-list.svelte b/src/lib/flows/create-drip-list-flow/steps/build-list/build-list.svelte index b5ad983f4..c1071195e 100644 --- a/src/lib/flows/create-drip-list-flow/steps/build-list/build-list.svelte +++ b/src/lib/flows/create-drip-list-flow/steps/build-list/build-list.svelte @@ -7,38 +7,30 @@ import type { Writable } from 'svelte/store'; import type { State } from '../../create-drip-list-flow'; import { page } from '$app/stores'; - import ArrowLeft from '$lib/components/icons/ArrowLeft.svelte'; - import FormField from '$lib/components/form-field/form-field.svelte'; - import ListEditor from '$lib/components/list-editor/list-editor.svelte'; + import DripListEditor from '$lib/components/drip-list-editor/drip-list-editor.svelte'; const dispatch = createEventDispatcher(); export let context: Writable; + export let canCancel = false; const { searchParams } = $page.url; const urlToAdd = searchParams.get('urlToAdd') ?? undefined; - let listValid = false; + let isValid = false; - - - - - - + + {#if canCancel} + + {/if} - import Button from '$lib/components/button/button.svelte'; - import type { StepComponentEvents } from '$lib/components/stepper/types'; - import { createEventDispatcher } from 'svelte'; - import StandaloneFlowStepLayout from '$lib/components/standalone-flow-step-layout/standalone-flow-step-layout.svelte'; - import Check from '$lib/components/icons/Check.svelte'; - import type { Writable } from 'svelte/store'; - import type { State } from '../../create-drip-list-flow'; - import TwoBigOptions from '$lib/components/two-big-options/two-big-options.svelte'; - import DripList from '$lib/components/icons/DripList.svelte'; - import TokenStreams from '$lib/components/icons/TokenStreams.svelte'; - import Proposals from '$lib/components/icons/Proposals.svelte'; - import ArrowUp from '$lib/components/icons/ArrowUp.svelte'; - import FormField from '$lib/components/form-field/form-field.svelte'; - import TextInput from '$lib/components/text-input/text-input.svelte'; - import TextArea from '$lib/components/text-area/text-area.svelte'; - import type { TextInputValidationState } from '$lib/components/text-input/text-input'; - - const dispatch = createEventDispatcher(); - - export let context: Writable; - export let canCancel = false; - - let textAreaValidationState: TextInputValidationState; - $: textAreaValidationState = !$context.dripList.description - ? { type: 'valid' } - : $context.dripList.description.length >= 1000 - ? { type: 'invalid', message: `Cannot exceed ${Number(1000).toLocaleString()} characters.` } - : /<[^>]+>/gi.test($context.dripList.description) - ? { type: 'invalid', message: 'HTML currently not allowed.' } - : { type: 'valid' }; - - $: isValid = - $context.selectedCreationMode !== undefined && - $context.dripList.title.length > 0 && - textAreaValidationState.type === 'valid'; - - - - - - - - -