diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34d41f8..1493398 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: 'publish' +name: "publish" on: workflow_dispatch: {} @@ -18,16 +18,16 @@ jobs: fail-fast: false matrix: include: - - platform: 'macos-latest' # for Arm based macs (M1 and above). - args: '--target aarch64-apple-darwin' - - platform: 'macos-latest' # for Intel based macs. - args: '--target x86_64-apple-darwin' - - platform: 'ubuntu-22.04' # for Tauri v1 you could replace this with ubuntu-20.04. - args: '' - - platform: 'ubuntu-22.04-arm' - args: '--target aarch64-unknown-linux-gnu' - - platform: 'windows-latest' - args: '' + - platform: "macos-14" # for Arm based macs (M1 and above). + args: "--target aarch64-apple-darwin" + - platform: "macos-14" # for Intel based macs. + args: "--target x86_64-apple-darwin" + - platform: "ubuntu-22.04" # for Tauri v1 you could replace this with ubuntu-20.04. + args: "" + - platform: "ubuntu-22.04-arm" + args: "--target aarch64-unknown-linux-gnu" + - platform: "windows-latest" + args: "" runs-on: ${{ matrix.platform }} steps: @@ -36,16 +36,29 @@ jobs: submodules: true token: ${{ secrets.GITHUB_TOKEN }} + - name: setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + run_install: false + - name: setup node uses: actions/setup-node@v4 with: node-version: lts/* + cache: pnpm + - name: install Rust nightly uses: dtolnay/rust-toolchain@nightly with: # Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds. - targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} + targets: ${{ matrix.platform == 'macos-14' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} + + - name: Rust cache + uses: swatinem/rust-cache@v2 + with: + workspaces: './src-tauri -> target' - name: install dependencies (ubuntu only) if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm' # This must match the platform value defined above. @@ -54,9 +67,8 @@ jobs: sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils # webkitgtk 4.0 is for Tauri v1 - webkitgtk 4.1 is for Tauri v2. - - name: Import Apple Developer Certificate - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-14' env: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} @@ -67,18 +79,30 @@ jobs: security default-keychain -s build.keychain security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain security set-keychain-settings -t 3600 -u build.keychain - - curl https://droposs.org/drop.crt --output drop.pem - sudo security authorizationdb write com.apple.trust-settings.user allow - security add-trusted-cert -r trustRoot -k build.keychain -p codeSign -u -1 drop.pem - sudo security authorizationdb remove com.apple.trust-settings.user + + + echo "Created keychain" + + curl https://droposs.org/drop.der --output drop.der + + # swiftc libs/appletrust/add-certificate.swift + # ./add-certificate drop.der + # rm add-certificate + + # echo "Added certificate to keychain using swift util" + + ## Script is equivalent to: + sudo security authorizationdb write com.apple.trust-settings.admin allow + sudo security add-trusted-cert -d -r trustRoot -k build.keychain -p codeSign -u -1 drop.der + sudo security authorizationdb remove com.apple.trust-settings.admin security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign + echo "Imported certificate" security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain security find-identity -v -p codesigning build.keychain - name: Verify Certificate - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-14' run: | CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Drop OSS") CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}') @@ -86,7 +110,7 @@ jobs: echo "Certificate imported. Using identity: $CERT_ID" - name: install frontend dependencies - run: yarn install # change this to npm, pnpm or bun depending on which one you use. + run: pnpm install # change this to npm, pnpm or bun depending on which one you use. - uses: tauri-apps/tauri-action@v0 env: @@ -97,8 +121,8 @@ jobs: NO_STRIP: true with: tagName: v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version. - releaseName: 'Auto-release v__VERSION__' - releaseBody: 'See the assets to download this version and install. This release was created automatically.' + releaseName: "Auto-release v__VERSION__" + releaseBody: "See the assets to download this version and install. This release was created automatically." releaseDraft: false prerelease: true - args: ${{ matrix.args }} \ No newline at end of file + args: ${{ matrix.args }} diff --git a/.gitignore b/.gitignore index c60be72..b2300d2 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,6 @@ src-tauri/flamegraph.svg src-tauri/perf* /*.AppImage -/squashfs-root \ No newline at end of file +/squashfs-root + +/target/ diff --git a/.gitlab-ci-local/.gitignore b/.gitlab-ci-local/.gitignore deleted file mode 100644 index d6b7ef3..0000000 --- a/.gitlab-ci-local/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/README.md b/README.md index f66cea8..662712b 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,21 @@ -# Drop App +# Drop Desktop Client -Drop app is the companion app for [Drop](https://github.com/Drop-OSS/drop). It uses a Tauri base with Nuxt 3 + TailwindCSS on top of it, so we can re-use components from the web UI. +The Drop Desktop Client is the companion app for [Drop](https://github.com/Drop-OSS/drop). It is the official & intended way to download and play games on your Drop server. -## Running -Before setting up the drop app, be sure that you have a server set up. -The instructions for this can be found on the [Drop Docs](https://docs.droposs.org/docs/guides/quickstart) +## Internals -## Current features -Currently supported are the following features: -- Signin (with custom server) -- Database registering & recovery -- Dynamic library fetching from server -- Installing & uninstalling games -- Download progress monitoring -- Launching / playing games +It uses a Tauri base with Nuxt 3 + TailwindCSS on top of it, so we can re-use components from the web UI. ## Development +Before setting up a development environemnt, be sure that you have a server set up. The instructions for this can be found on the [Drop Docs](https://docs.droposs.org/docs/guides/quickstart). -Install dependencies with `yarn` +Then, install dependencies with `yarn`. This'll install the custom builder's dependencies. Then, check everything works properly with `yarn tauri build`. -Run the app in development with `yarn tauri dev`. NVIDIA users on Linux, use shell script `./nvidia-prop-dev.sh` +Run the app in development with `yarn tauri dev`. NVIDIA users on Linux, use shell script `./nvidia-prop-dev.sh` To manually specify the logging level, add the environment variable `RUST_LOG=[debug, info, warn, error]` to `yarn tauri dev`: e.g. `RUST_LOG=debug yarn tauri dev` ## Contributing -Check the original [Drop repo](https://github.com/Drop-OSS/drop/blob/main/CONTRIBUTING.md) for contributing guidelines. \ No newline at end of file +Check out the contributing guide on our Developer Docs: [Drop Developer Docs - Contributing](https://developer.droposs.org/contributing). diff --git a/build.mjs b/build.mjs index c4846f1..68d5a18 100644 --- a/build.mjs +++ b/build.mjs @@ -21,6 +21,13 @@ async function spawn(exec, opts) { }); } +const expectedLibs = ["drop-base/package.json"]; + +for (const lib of expectedLibs) { + const path = `./libs/${lib}`; + if (!fs.existsSync(path)) throw `Missing "${expectedLibs}". Run "git submodule update --init --recursive"`; +} + const views = fs.readdirSync(".").filter((view) => { const expectedPath = `./${view}/package.json`; return fs.existsSync(expectedPath); @@ -33,10 +40,10 @@ for (const view of views) { process.chdir(`./${view}`); loggerChild.info(`Install deps for "${view}"`); - await spawn("yarn"); + await spawn("pnpm install"); loggerChild.info(`Building "${view}"`); - await spawn("yarn build", { + await spawn("pnpm run build", { env: { ...process.env, NUXT_APP_BASE_URL: `/${view}/` }, }); diff --git a/libs/appletrust/add-certificate.swift b/libs/appletrust/add-certificate.swift new file mode 100644 index 0000000..8ed6601 --- /dev/null +++ b/libs/appletrust/add-certificate.swift @@ -0,0 +1,72 @@ +import Foundation +import Security + +enum SecurityError: Error { + case generalError +} + +func deleteCertificateFromKeyChain(_ certificateLabel: String) -> Bool { + let delQuery: [NSString: Any] = [ + kSecClass: kSecClassCertificate, + kSecAttrLabel: certificateLabel, + ] + let delStatus: OSStatus = SecItemDelete(delQuery as CFDictionary) + + return delStatus == errSecSuccess +} + +func saveCertificateToKeyChain(_ certificate: SecCertificate, certificateLabel: String) throws { + SecKeychainSetPreferenceDomain(SecPreferencesDomain.system) + deleteCertificateFromKeyChain(certificateLabel) + + let setQuery: [NSString: AnyObject] = [ + kSecClass: kSecClassCertificate, + kSecValueRef: certificate, + kSecAttrLabel: certificateLabel as AnyObject, + kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, + kSecAttrCanSign: true as AnyObject, + ] + let addStatus: OSStatus = SecItemAdd(setQuery as CFDictionary, nil) + + guard addStatus == errSecSuccess else { + throw SecurityError.generalError + } + + var status = SecTrustSettingsSetTrustSettings(certificate, SecTrustSettingsDomain.admin, nil) +} + +func getCertificateFromString(stringData: String) throws -> SecCertificate { + if let data = NSData(base64Encoded: stringData, options: NSData.Base64DecodingOptions.ignoreUnknownCharacters) { + if let certificate = SecCertificateCreateWithData(kCFAllocatorDefault, data) { + return certificate + } + } + throw SecurityError.generalError +} + +if CommandLine.arguments.count != 2 { + print("Usage: \(CommandLine.arguments[0]) [cert.file]") + print("Usage: \(CommandLine.arguments[0]) --version") + exit(1) +} + +if (CommandLine.arguments[1] == "--version") { + let version = "dev" + print(version) + exit(0) +} else { + let fileURL = URL(fileURLWithPath: CommandLine.arguments[1]) + do { + let certData = try Data(contentsOf: fileURL) + let certificate = SecCertificateCreateWithData(nil, certData as CFData) + if certificate != nil { + try? saveCertificateToKeyChain(certificate!, certificateLabel: "DropOSS") + exit(0) + } else { + print("ERROR: Unknown error while reading the \(CommandLine.arguments[1]) file.") + } + } catch { + print("ERROR: Unexpected error while reading the \(CommandLine.arguments[1]) file. \(error)") + } +} +exit(1) \ No newline at end of file diff --git a/main/app.vue b/main/app.vue index 7d4165f..1594dd6 100644 --- a/main/app.vue +++ b/main/app.vue @@ -1,5 +1,5 @@ diff --git a/main/composables/downloads.ts b/main/composables/downloads.ts index d75c46f..f9ab1cd 100644 --- a/main/composables/downloads.ts +++ b/main/composables/downloads.ts @@ -32,3 +32,5 @@ listen("update_stats", (event) => { const stats = useStatsState(); stats.value = event.payload as StatsState; }); + +export const useDownloadHistory = () => useState>('history', () => []); \ No newline at end of file diff --git a/main/nuxt.config.ts b/main/nuxt.config.ts index 8ee30e8..bbc3b40 100644 --- a/main/nuxt.config.ts +++ b/main/nuxt.config.ts @@ -12,6 +12,7 @@ export default defineNuxtConfig({ css: ["~/assets/main.scss"], ssr: false, + devtools: false, extends: [["../libs/drop-base"]], diff --git a/main/package.json b/main/package.json index 78f9361..15be40f 100644 --- a/main/package.json +++ b/main/package.json @@ -1,7 +1,7 @@ { "name": "view", "private": true, - "version": "0.3.3", + "version": "0.3.4", "type": "module", "scripts": { "build": "nuxt generate", @@ -14,6 +14,8 @@ "@heroicons/vue": "^2.1.5", "@nuxtjs/tailwindcss": "^6.12.2", "@tauri-apps/api": "^2.7.0", + "@tauri-apps/plugin-os": "^2.3.2", + "@tauri-apps/plugin-shell": "^2.3.3", "koa": "^2.16.1", "markdown-it": "^14.1.0", "micromark": "^4.0.1", @@ -32,6 +34,5 @@ "tailwindcss": "^3.4.13", "typescript": "^5.8.3", "vue-tsc": "^2.2.10" - }, - "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" + } } diff --git a/main/pages/queue.vue b/main/pages/queue.vue index 8d5c4ef..30eb886 100644 --- a/main/pages/queue.vue +++ b/main/pages/queue.vue @@ -4,18 +4,18 @@ class="h-16 overflow-hidden relative rounded-xl flex flex-row border border-zinc-900" >
- {{ formatKilobytes(stats.speed) }}/s - {{ formatKilobytes(stats.speed) }}B/s + {{ formatTime(stats.time) }} left
-
+
@@ -62,9 +62,9 @@ class="mt-2 inline-flex items-center gap-x-1 text-zinc-400 text-sm font-display" >{{ formatKilobytes(element.current / 1000) - }} + }}B / - {{ formatKilobytes(element.max / 1000) }}{{ formatKilobytes(element.max / 1000) }}B
@@ -91,7 +91,7 @@