diff --git a/.codex/project.md b/.codex/project.md new file mode 100644 index 000000000..2bcb2de69 --- /dev/null +++ b/.codex/project.md @@ -0,0 +1,34 @@ +# Modrinth Plus + +Modrinth Plus is a fork of the official Modrinth monorepo focused on the +desktop app. Its first custom feature is Connected Library: public Git-hosted +modpack manifests that can install and update exported `.mrpack` releases. + +## Stack + +- Monorepo package manager: pnpm +- Desktop app frontend: Vue +- Desktop app shell: Tauri +- Core app logic: Rust crate `theseus` in `packages/app-lib` +- Local app storage: SQLite migrations in `packages/app-lib/migrations` +- CI target: Gitea Actions runner + +## Connected Library Defaults + +- Supports public HTTPS raw manifest URLs and GitHub/GitLab/Gitea repo URLs. +- Manifest filename is `modrinth-plus.json`. +- Auto-update is disabled by default and can be enabled per connected pack. +- Private repository auth, SSH, and token storage are out of scope for v1. + +## Verification + +Use the cheapest relevant checks first: + +```bash +pnpm install +pnpm --filter @modrinth/app-frontend run lint +cargo fmt --check +cargo clippy --package theseus +``` + +Full app packaging may require platform-specific Tauri dependencies. diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 000000000..999916899 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,51 @@ +name: Build + +on: + push: + branches: + - main + - master + workflow_dispatch: + +jobs: + verify: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9.15.0 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - name: Install Tauri Linux prerequisites + run: | + sudo apt-get update + sudo apt-get install -y \ + libwebkit2gtk-4.1-dev \ + libayatana-appindicator3-dev \ + librsvg2-dev \ + patchelf + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Frontend lint + run: pnpm --filter @modrinth/app-frontend run lint + + - name: Rust format + run: cargo fmt --check + + - name: Rust clippy + run: cargo clippy --package theseus --all-targets -- -D warnings diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index aed1666ac..34c4c785f 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -14,6 +14,7 @@ import { CompassIcon, DownloadIcon, ExternalIcon, + GitGraphIcon, HomeIcon, LeftArrowIcon, LibraryIcon, @@ -75,6 +76,7 @@ import FriendsList from '@/components/ui/friends/FriendsList.vue' import AddServerToInstanceModal from '@/components/ui/install_flow/AddServerToInstanceModal.vue' import IncompatibilityWarningModal from '@/components/ui/install_flow/IncompatibilityWarningModal.vue' import UnknownPackWarningModal from '@/components/ui/install_flow/UnknownPackWarningModal.vue' +import { check_all_connected_packs } from '@/helpers/connected-library' import MinecraftAuthErrorModal from '@/components/ui/minecraft-auth-error-modal/MinecraftAuthErrorModal.vue' import AppSettingsModal from '@/components/ui/modal/AppSettingsModal.vue' import AuthGrantFlowWaitModal from '@/components/ui/modal/AuthGrantFlowWaitModal.vue' @@ -425,6 +427,9 @@ initialize_state() console.error(err) error.showError(err, null, false, 'state_init') }) + check_all_connected_packs().catch((err) => { + console.warn('Connected Library startup check failed', err) + }) }) .catch((err) => { stateFailed.value = true @@ -1244,6 +1249,13 @@ provideAppUpdateDownloadProgress(appUpdateDownload) > + + + { + return await invoke('plugin:connected-library|connected_library_list') +} + +export async function connect_pack(sourceUrl: string): Promise { + return await invoke('plugin:connected-library|connected_library_connect', { sourceUrl }) +} + +export async function remove_connected_pack(id: string): Promise { + return await invoke('plugin:connected-library|connected_library_remove', { id }) +} + +export async function set_connected_pack_auto_update( + id: string, + autoUpdate: boolean, +): Promise { + return await invoke('plugin:connected-library|connected_library_set_auto_update', { + id, + autoUpdate, + }) +} + +export async function check_connected_pack(id: string): Promise { + return await invoke('plugin:connected-library|connected_library_check', { id }) +} + +export async function check_all_connected_packs(): Promise { + return await invoke('plugin:connected-library|connected_library_check_all') +} + +export async function install_connected_pack(id: string): Promise { + return await invoke('plugin:connected-library|connected_library_install', { id }) +} diff --git a/apps/app-frontend/src/pages/library/Connected.vue b/apps/app-frontend/src/pages/library/Connected.vue new file mode 100644 index 000000000..706630cf7 --- /dev/null +++ b/apps/app-frontend/src/pages/library/Connected.vue @@ -0,0 +1,334 @@ + + + + + diff --git a/apps/app-frontend/src/pages/library/Index.vue b/apps/app-frontend/src/pages/library/Index.vue index 327ab44d9..a4c49431f 100644 --- a/apps/app-frontend/src/pages/library/Index.vue +++ b/apps/app-frontend/src/pages/library/Index.vue @@ -41,13 +41,14 @@ onUnmounted(() => { :links="[ { label: 'All instances', href: `/library` }, { label: 'Modpacks', href: `/library/modpacks` }, + { label: 'Connected Library', href: `/library/connected` }, { label: 'Servers', href: `/library/servers` }, { label: 'Custom', href: `/library/custom` }, { label: 'Shared with me', href: `/library/shared`, shown: false }, { label: 'Saved', href: `/library/saved`, shown: false }, ]" /> -