chore(ci): add linters (#22)

* chore(ci): add linters

* chore: apply linter fixes

* chore(ci): add cache layer

* chore(ci): change lint flavour

* chore: apply linter fixes

* chore(cI): fix linter errors

* chore

* chore(ci): add renovate

* chore(ci): add renovate workflow

* chore(

* chore(ci): enable git lfs

---------

Co-authored-by: leafdbot[bot] <192038741+leafdbot[bot]@users.noreply.github.com>
This commit is contained in:
Leafd 2025-10-05 00:10:10 -06:00 committed by GitHub
parent a2b1e2de9a
commit 1e52ddc88c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 421 additions and 195 deletions

23
.github/renovate-ci.json5 vendored Normal file
View file

@ -0,0 +1,23 @@
{
"extends": [":enableRenovate", ":semanticCommits", ":enablePreCommit"],
"platform": "github",
"username": "leafdbot[bot]",
"repositories": ["hackclub/hackatime-desktop"],
"onboarding": false,
"requireConfig": "optional",
"gitAuthor": "leafdbot[bot] <192038741+leafdbot[bot]@users.noreply.github.com>",
"timezone": "UTC",
"dependencyDashboard": true,
"stabilityDays": 1,
"platformCommit": true,
"prCreation": "not-pending",
"commitBody": "Signed-off-by: leafdbot[bot] <192038741+leafdbot[bot]@users.noreply.github.com>",
"suppressNotifications": ["prIgnoreNotification"],
"rebaseWhen": "conflicted",
"git-submodules": {"enabled": true},
"packageRules": [
{"matchUpdateTypes": ["major"], "addLabels": ["dependency/major"]},
{"matchUpdateTypes": ["minor"], "addLabels": ["dependency/minor"]},
{"matchUpdateTypes": ["patch"], "addLabels": ["dependency/patch"]}
]
}

119
.github/workflows/lint.yaml vendored Normal file
View file

@ -0,0 +1,119 @@
---
name: leafdlint
on:
pull_request:
branches: [main, develop]
push:
branches: [main, develop]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
lint:
name: LINTEEER
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.event.action != 'closed'
env:
APPLY_FIXES: all
APPLY_FIXES_EVENT: all
APPLY_FIXES_MODE: commit
outputs:
changes_detected: ${{ steps.autocommit.outputs.changes_detected }}
commit_hash: ${{ steps.autocommit.outputs.commit_hash }}
steps:
- name: Generate GitHub App Token
uses: actions/create-github-app-token@v1
id: generate-token
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout Code
uses: actions/checkout@v4
with:
token: ${{ steps.generate-token.outputs.token }}
fetch-depth: 0
ref: ${{ github.head_ref || github.ref }}
lfs: true
- name: Run MegaLinter
uses: oxsecurity/megalinter/flavors/rust@v8.8.0
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
DEFAULT_BRANCH: main
VALIDATE_ALL_CODEBASE: true
ENABLE: RUST,JAVASCRIPT,TYPESCRIPT,JSON,YAML,MARKDOWN,REPOSITORY
ENABLE_LINTERS: RUST_CLIPPY,RUST_RUSTFMT,VUE_ESLINT_PLUGIN_VUE,REPOSITORY_GIT_DIFF,REPOSITORY_SECRETLINT,REPOSITORY_TRIVY_SBOM,REPOSITORY_TRUFFLEHOG,YAML_PRETTIER,YAML_YAMLLINT
DISABLE: COPYPASTE,SPELL
DISABLE_LINTERS: REPOSITORY_CHECKOV,REPOSITORY_GITLEAKS
SECURITY_LINTERS_ENABLED: true
# Rust linter configuration
RUST_PRE_COMMANDS: "[{\"cwd\": \"workspace\", \"command\": \"apk add --no-cache pkgconfig gtk+3.0-dev webkit2gtk-4.1-dev openssl-dev\"}]"
RUST_CLIPPY_ARGUMENTS: -- --manifest-path src-tauri/Cargo.toml
RUST_RUSTFMT_ARGUMENTS: --edition 2024
# Other linter arguments
REPOSITORY_TRIVY_ARGUMENTS: --scanners vuln,misconfig --severity HIGH,CRITICAL --exit-code 1
JSON_PRETTIER_FILTER_REGEX_EXCLUDE: ".release-please-manifest.json"
MARKDOWN_FILTER_REGEX_EXCLUDE: "CHANGELOG.md"
# File filtering
FILTER_REGEX_INCLUDE: (src-tauri/.*\.rs|src/.*\.(js|ts|tsx|jsx|json|yaml|yml|toml|md))
FILTER_REGEX_EXCLUDE: (target/|src-tauri/target/|node_modules/|dist/|build/)
# Apply fixes configuration
APPLY_FIXES: all
APPLY_FIXES_EVENT: all
APPLY_FIXES_MODE: commit
# Reporter settings
FILEIO_REPORTER: false
FLAVOR_SUGGESTIONS: false
SHOW_ELAPSED_TIME: true
PRINT_ALPACA: false
PRINT_ALL_FILES: false
- name: Archive Linter Reports
if: always()
uses: actions/upload-artifact@v4
with:
name: megalinter-reports
path: |
megalinter-reports/
mega-linter.log
retention-days: 30
- name: Add Reports to Gitignore
if: success() || failure()
run: |
touch .gitignore
grep -qxF 'megalinter-reports/' .gitignore || echo 'megalinter-reports/' >> .gitignore
grep -qxF 'mega-linter.log' .gitignore || echo 'mega-linter.log' >> .gitignore
- name: Prepare Git for Commit
if: success() || failure()
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
sudo chown -Rc $UID .git/ || true
- name: Commit and Push Linter Fixes
id: autocommit
if: success() || failure()
uses: stefanzweifel/git-auto-commit-action@v5
with:
branch: ${{ github.head_ref || github.ref_name }}
commit_user_name: ${{ vars.BOT_NAME }}
commit_user_email: ${{ vars.BOT_EMAIL }}
commit_author: ${{ vars.BOT_NAME }} <${{ vars.BOT_EMAIL }}>
commit_message: "chore: apply linter fixes"
skip_dirty_check: false
skip_fetch: false
skip_checkout: false
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}

View file

@ -1,3 +1,4 @@
---
name: Release
'on':
workflow_dispatch: null

51
.github/workflows/renovate.yaml vendored Normal file
View file

@ -0,0 +1,51 @@
---
name: Renovate
"on":
push:
branches: [main]
pull_request:
types: [edited]
issues:
types: [edited]
workflow_dispatch:
inputs:
# checkov:skip=CKV_GHA_7:The build output is unaffected by these inputs
dryRun:
description: "Dry-Run"
default: "true"
required: false
logLevel:
description: "Log-Level"
default: "debug"
required: false
env:
LOG_LEVEL: info
DRY_RUN: false
jobs:
renovate:
name: Renovate
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Generate Token
uses: tibdex/github-app-token@v2
id: generate-token
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ steps.generate-token.outputs.token }}
fetch-depth: 1
- name: Override default config from dispatch variables
run: |
echo "DRY_RUN=${{ github.event.inputs.dryRun || env.DRY_RUN }}" >> "${GITHUB_ENV}"
echo "LOG_LEVEL=${{ github.event.inputs.logLevel || env.LOG_LEVEL }}" >> "${GITHUB_ENV}"
- name: Run Renovate
uses: renovatebot/github-action@v41.0.3
with:
configurationFile: .github/renovate-ci.json5
token: "x-access-token:${{ steps.generate-token.outputs.token }}"

2
.gitignore vendored
View file

@ -22,3 +22,5 @@ dist-ssr
*.njsproj
*.sln
*.sw?
megalinter-reports/
mega-linter.log

6
.trivyignore Normal file
View file

@ -0,0 +1,6 @@
# Trivy ignore file
# Suppress known issues that cannot be easily fixed
# More info on : https://github.com/tauri-apps/tauri/issues/12048
GHSA-wrw7-89jp-8q8g

233
src-tauri/Cargo.lock generated
View file

@ -314,11 +314,11 @@ dependencies = [
[[package]]
name = "block2"
version = "0.6.1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2"
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
dependencies = [
"objc2 0.6.2",
"objc2 0.6.3",
]
[[package]]
@ -363,9 +363,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "bytemuck"
version = "1.23.2"
version = "1.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
[[package]]
name = "byteorder"
@ -451,9 +451,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.39"
version = "1.2.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f"
checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb"
dependencies = [
"find-msvc-tools",
"shlex",
@ -899,7 +899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2 0.6.3",
]
[[package]]
@ -1150,9 +1150,9 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3"
[[package]]
name = "flate2"
@ -2364,11 +2364,10 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
[[package]]
name = "lock_api"
version = "0.4.13"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"autocfg",
"scopeguard",
]
@ -2489,10 +2488,10 @@ dependencies = [
"dpi",
"gtk",
"keyboard-types",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"once_cell",
"png",
"serde",
@ -2665,9 +2664,9 @@ dependencies = [
[[package]]
name = "objc2"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc"
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
dependencies = [
"objc2-encode",
"objc2-exception-helper",
@ -2675,77 +2674,104 @@ dependencies = [
[[package]]
name = "objc2-app-kit"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.1",
"block2 0.6.2",
"libc",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-cloud-kit",
"objc2-core-data",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-core-image",
"objc2-foundation 0.3.1",
"objc2-quartz-core 0.3.1",
"objc2-core-text",
"objc2-core-video",
"objc2-foundation 0.3.2",
"objc2-quartz-core 0.3.2",
]
[[package]]
name = "objc2-cloud-kit"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d"
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2-foundation 0.3.1",
"objc2 0.6.3",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-core-data"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d"
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2-foundation 0.3.1",
"objc2 0.6.3",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-core-foundation"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.9.4",
"dispatch2",
"objc2 0.6.2",
"objc2 0.6.3",
]
[[package]]
name = "objc2-core-graphics"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags 2.9.4",
"dispatch2",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]]
name = "objc2-core-image"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e"
checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006"
dependencies = [
"objc2 0.6.2",
"objc2-foundation 0.3.1",
"objc2 0.6.3",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-core-text"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-core-graphics",
]
[[package]]
name = "objc2-core-video"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-io-surface",
]
[[package]]
@ -2777,35 +2803,35 @@ dependencies = [
[[package]]
name = "objc2-foundation"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.1",
"block2 0.6.2",
"libc",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-core-foundation",
]
[[package]]
name = "objc2-io-surface"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-core-foundation",
]
[[package]]
name = "objc2-javascript-core"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9052cb1bb50a4c161d934befcf879526fb87ae9a68858f241e693ca46225cf5a"
checksum = "2a1e6550c4caed348956ce3370c9ffeca70bb1dbed4fa96112e7c6170e074586"
dependencies = [
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-core-foundation",
]
@ -2823,14 +2849,14 @@ dependencies = [
[[package]]
name = "objc2-osa-kit"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26bb88504b5a050dbba515d2414607bf5e57dd56b107bc5f0351197a3e7bdc5d"
checksum = "f112d1746737b0da274ef79a23aac283376f335f4095a083a267a082f21db0c0"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
]
[[package]]
@ -2848,50 +2874,50 @@ dependencies = [
[[package]]
name = "objc2-quartz-core"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5"
checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2-foundation 0.3.1",
"objc2 0.6.3",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-security"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1f8e0ef3ab66b08c42644dcb34dba6ec0a574bbd8adbb8bdbdc7a2779731a44"
checksum = "709fe137109bd1e8b5a99390f77a7d8b2961dafc1a1c5db8f2e60329ad6d895a"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-core-foundation",
]
[[package]]
name = "objc2-ui-kit"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed"
checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-web-kit"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91672909de8b1ce1c2252e95bbee8c1649c9ad9d14b9248b3d7b4c47903c47ad"
checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.1",
"objc2 0.6.2",
"block2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"objc2-javascript-core",
"objc2-security",
]
@ -2999,8 +3025,8 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "732c71caeaa72c065bb69d7ea08717bd3f4863a4f451402fc9513e29dbd5261b"
dependencies = [
"objc2 0.6.2",
"objc2-foundation 0.3.1",
"objc2 0.6.3",
"objc2-foundation 0.3.2",
"objc2-osa-kit",
"serde",
"serde_json",
@ -3040,9 +3066,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "parking_lot"
version = "0.12.4"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
@ -3050,15 +3076,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.11"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets 0.52.6",
"windows-link 0.2.0",
]
[[package]]
@ -3601,9 +3627,9 @@ checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
[[package]]
name = "redox_syscall"
version = "0.5.17"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags 2.9.4",
]
@ -4118,9 +4144,9 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.14.1"
version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e"
checksum = "6093cd8c01b25262b84927e0f7151692158fab02d961e04c979d3903eba7ecc5"
dependencies = [
"base64 0.22.1",
"chrono",
@ -4129,8 +4155,7 @@ dependencies = [
"indexmap 2.11.4",
"schemars 0.9.0",
"schemars 1.0.4",
"serde",
"serde_derive",
"serde_core",
"serde_json",
"serde_with_macros",
"time",
@ -4138,9 +4163,9 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "3.14.1"
version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e"
checksum = "a7e6c180db0816026a61afa1cff5344fb7ebded7e4d3062772179f2501481c27"
dependencies = [
"darling",
"proc-macro2",
@ -4705,7 +4730,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "959469667dbcea91e5485fc48ba7dd6023face91bb0f1a14681a70f99847c3f7"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.1",
"block2 0.6.2",
"core-foundation 0.10.1",
"core-graphics",
"crossbeam-channel",
@ -4722,9 +4747,9 @@ dependencies = [
"ndk",
"ndk-context",
"ndk-sys",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"once_cell",
"parking_lot",
"raw-window-handle",
@ -4788,9 +4813,9 @@ dependencies = [
"log",
"mime",
"muda",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"objc2-ui-kit",
"objc2-web-kit",
"percent-encoding",
@ -4928,7 +4953,7 @@ dependencies = [
"dunce",
"glob",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"open",
"schemars 0.8.22",
"serde",
@ -4994,7 +5019,7 @@ dependencies = [
"gtk",
"http 1.3.1",
"jni",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-ui-kit",
"objc2-web-kit",
"raw-window-handle",
@ -5018,9 +5043,9 @@ dependencies = [
"http 1.3.1",
"jni",
"log",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"once_cell",
"percent-encoding",
"raw-window-handle",
@ -5470,11 +5495,11 @@ dependencies = [
"dirs",
"libappindicator",
"muda",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"once_cell",
"png",
"serde",
@ -5496,9 +5521,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
[[package]]
name = "typenum"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "uds_windows"
@ -5997,10 +6022,10 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9bec5a31f3f9362f2258fd0e9c9dd61a9ca432e7306cc78c444258f0dce9a9c"
dependencies = [
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"raw-window-handle",
"windows-sys 0.59.0",
"windows-version",
@ -6528,7 +6553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f0e9642a0d061f6236c54ccae64c2722a7879ad4ec7dff59bd376d446d8e90"
dependencies = [
"base64 0.22.1",
"block2 0.6.1",
"block2 0.6.2",
"cookie",
"crossbeam-channel",
"dirs",
@ -6543,10 +6568,10 @@ dependencies = [
"kuchikiki",
"libc",
"ndk",
"objc2 0.6.2",
"objc2 0.6.3",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
"objc2-foundation 0.3.2",
"objc2-ui-kit",
"objc2-web-kit",
"once_cell",

View file

@ -1,179 +1,178 @@
import { invoke } from "@tauri-apps/api/core";
import { invoke } from '@tauri-apps/api/core'
interface ApiConfig {
base_url: string;
base_url: string
}
interface AuthState {
is_authenticated: boolean;
access_token: string | null;
user_info: Record<string, any> | null;
is_authenticated: boolean
access_token: string | null
user_info: Record<string, any> | null
}
export class KubeTimeApi {
private baseUrl: string = "https://hackatime.hackclub.com";
private accessToken: string | null = null;
private latestPresenceCache: { data: any | null; fetchedAt: number } = { data: null, fetchedAt: 0 };
private baseUrl: string = 'https://hackatime.hackclub.com'
private accessToken: string | null = null
private latestPresenceCache: { data: any | null, fetchedAt: number } = { data: null, fetchedAt: 0 }
async initialize() {
async initialize () {
try {
const config: ApiConfig = await invoke("get_api_config");
const config: ApiConfig = await invoke('get_api_config')
if (config.base_url && config.base_url.trim()) {
this.baseUrl = config.base_url;
this.baseUrl = config.base_url
}
const authState: AuthState = await invoke("get_auth_state");
this.accessToken = authState.access_token;
const authState: AuthState = await invoke('get_auth_state')
this.accessToken = authState.access_token
} catch (error) {
console.error("Failed to initialize API:", error);
console.error('Failed to initialize API:', error)
if (!this.baseUrl || !this.baseUrl.trim()) {
this.baseUrl = "https://hackatime.hackclub.com";
this.baseUrl = 'https://hackatime.hackclub.com'
}
}
}
async getCurrentUser() {
async getCurrentUser () {
if (!this.accessToken) {
throw new Error("Not authenticated");
throw new Error('Not authenticated')
}
try {
const response = await fetch(`${this.baseUrl}/api/v1/authenticated/me`, {
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
},
});
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json'
}
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
throw new Error(`HTTP error! status: ${response.status}`)
}
return await response.json();
return await response.json()
} catch (error) {
console.error("Failed to fetch current user:", error);
throw error;
console.error('Failed to fetch current user:', error)
throw error
}
}
async getHours(startDate?: string, endDate?: string) {
async getHours (startDate?: string, endDate?: string) {
if (!this.accessToken) {
throw new Error("Not authenticated");
throw new Error('Not authenticated')
}
try {
const params = new URLSearchParams();
if (startDate) params.append('start_date', startDate);
if (endDate) params.append('end_date', endDate);
const url = `${this.baseUrl}/api/v1/authenticated/hours${params.toString() ? `?${params.toString()}` : ''}`;
const params = new URLSearchParams()
if (startDate) params.append('start_date', startDate)
if (endDate) params.append('end_date', endDate)
const url = `${this.baseUrl}/api/v1/authenticated/hours${params.toString() ? `?${params.toString()}` : ''}`
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
},
});
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json'
}
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
throw new Error(`HTTP error! status: ${response.status}`)
}
return await response.json();
return await response.json()
} catch (error) {
console.error("Failed to fetch hours:", error);
throw error;
console.error('Failed to fetch hours:', error)
throw error
}
}
async getWeeklyHours() {
const endDate = new Date();
const startDate = new Date();
startDate.setDate(endDate.getDate() - 7);
async getWeeklyHours () {
const endDate = new Date()
const startDate = new Date()
startDate.setDate(endDate.getDate() - 7)
const formatDate = (date: Date) => date.toISOString().split('T')[0];
return this.getHours(formatDate(startDate), formatDate(endDate));
const formatDate = (date: Date) => date.toISOString().split('T')[0]
return await this.getHours(formatDate(startDate), formatDate(endDate))
}
async getStreak() {
async getStreak () {
if (!this.accessToken) {
throw new Error("Not authenticated");
throw new Error('Not authenticated')
}
try {
const response = await fetch(`${this.baseUrl}/api/v1/authenticated/streak`, {
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
},
});
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json'
}
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
throw new Error(`HTTP error! status: ${response.status}`)
}
return await response.json();
return await response.json()
} catch (error) {
console.error("Failed to fetch streak:", error);
throw error;
console.error('Failed to fetch streak:', error)
throw error
}
}
async getStats() {
async getStats () {
if (!this.accessToken) {
throw new Error("Not authenticated");
throw new Error('Not authenticated')
}
try {
const [hoursData, streakData] = await Promise.all([
this.getWeeklyHours(),
this.getStreak()
]);
])
return {
...hoursData,
current_streak: streakData.current_streak,
longest_streak: streakData.longest_streak
};
}
} catch (error) {
console.error("Failed to fetch stats:", error);
throw error;
console.error('Failed to fetch stats:', error)
throw error
}
}
async getCurrentPresence() {
async getCurrentPresence () {
if (!this.accessToken) {
throw new Error("Not authenticated");
throw new Error('Not authenticated')
}
try {
// Return cached result if fetched within last 60s
const now = Date.now();
const now = Date.now()
if (now - this.latestPresenceCache.fetchedAt < 60_000 && this.latestPresenceCache.data !== null) {
return this.latestPresenceCache.data;
return this.latestPresenceCache.data
}
const response = await fetch(`${this.baseUrl}/api/v1/authenticated/heartbeats/latest`, {
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
},
});
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json'
}
})
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
throw new Error(`HTTP error! status: ${response.status}`)
}
const json = await response.json();
this.latestPresenceCache = { data: json, fetchedAt: Date.now() };
return json;
const json = await response.json()
this.latestPresenceCache = { data: json, fetchedAt: Date.now() }
return json
} catch (error) {
console.error("Failed to fetch current presence:", error);
throw error;
console.error('Failed to fetch current presence:', error)
throw error
}
}
}
export const api = new KubeTimeApi();
export const api = new KubeTimeApi()

View file

@ -4,7 +4,7 @@ export type Theme = 'dark' | 'light'
const currentTheme = ref<Theme>('dark')
export function useTheme() {
export function useTheme () {
const setTheme = (theme: Theme) => {
currentTheme.value = theme
document.documentElement.className = theme

View file

@ -1,5 +1,5 @@
import { createApp } from "vue";
import App from "./App.vue";
import "./style.css";
import { createApp } from 'vue'
import App from './App.vue'
import './style.css'
createApp(App).mount("#app");
createApp(App).mount('#app')

8
src/vite-env.d.ts vendored
View file

@ -1,7 +1,7 @@
/// <reference types="vite/client" />
declare module "*.vue" {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}