something-x-dev 1.7.0.dev15__tar.gz → 1.7.1.dev15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- something_x_dev-1.7.1.dev15/.github/CODEOWNERS +1 -0
- something_x_dev-1.7.1.dev15/.github/workflows/ci.yml +64 -0
- something_x_dev-1.7.1.dev15/.github/workflows/release-dev.yml +97 -0
- something_x_dev-1.7.1.dev15/.github/workflows/release.yml +190 -0
- something_x_dev-1.7.1.dev15/.gitignore +46 -0
- something_x_dev-1.7.1.dev15/DEVICES.md +37 -0
- {something_x_dev-1.7.0.dev15/something_x_dev.egg-info → something_x_dev-1.7.1.dev15}/PKG-INFO +1 -1
- something_x_dev-1.7.1.dev15/PKGBUILD +24 -0
- something_x_dev-1.7.1.dev15/ROADMAP.md +69 -0
- something_x_dev-1.7.1.dev15/cliff.toml +41 -0
- something_x_dev-1.7.1.dev15/data/style.css +355 -0
- something_x_dev-1.7.1.dev15/docs/RELEASING.md +192 -0
- something_x_dev-1.7.1.dev15/docs/docs.html +802 -0
- something_x_dev-1.7.1.dev15/docs/index.html +588 -0
- something_x_dev-1.7.1.dev15/flake.nix +66 -0
- something_x_dev-1.7.1.dev15/main.py +10 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/__init__.py +4 -5
- something_x_dev-1.7.1.dev15/nothing_app/_version.py +24 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/pyproject.toml +10 -2
- something_x_dev-1.7.1.dev15/requirements.txt +3 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15/something_x_dev.egg-info}/PKG-INFO +1 -1
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/something_x_dev.egg-info/SOURCES.txt +20 -0
- something_x_dev-1.7.1.dev15/somethingx +3 -0
- something_x_dev-1.7.1.dev15/tests/__init__.py +0 -0
- something_x_dev-1.7.1.dev15/tests/conftest.py +40 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/LICENSE +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/README.md +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/application.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/bluetooth.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/data/__init__.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/data/com.something.x.omarchy.desktop +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/data/style.css +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/pages/__init__.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/pages/device.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/pages/home.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/profiles.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/protocol.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/splash.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/tray.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/nothing_app/window.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/setup.cfg +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/something_x_dev.egg-info/dependency_links.txt +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/something_x_dev.egg-info/entry_points.txt +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/something_x_dev.egg-info/requires.txt +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/something_x_dev.egg-info/top_level.txt +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/tests/test_bluetooth.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/tests/test_crc.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/tests/test_profiles.py +0 -0
- {something_x_dev-1.7.0.dev15 → something_x_dev-1.7.1.dev15}/tests/test_protocol.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @SoaOaoS
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches-ignore: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
pull-requests: write # needed for reviewdog to post inline comments
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
lint:
|
|
15
|
+
name: Lint & format
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.11"
|
|
24
|
+
|
|
25
|
+
- name: Install ruff
|
|
26
|
+
run: pip install ruff
|
|
27
|
+
|
|
28
|
+
- name: Setup reviewdog
|
|
29
|
+
uses: reviewdog/action-setup@v1
|
|
30
|
+
with:
|
|
31
|
+
reviewdog_version: latest
|
|
32
|
+
|
|
33
|
+
# Posts inline review comments on the PR diff for every ruff finding
|
|
34
|
+
- name: Lint with reviewdog
|
|
35
|
+
run: ruff check --output-format rdjson nothing_app/ | reviewdog -f=rdjson -reporter=github-pr-review -fail-on-error
|
|
36
|
+
env:
|
|
37
|
+
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
38
|
+
|
|
39
|
+
# Still fail the job if formatting is wrong
|
|
40
|
+
- name: Check formatting
|
|
41
|
+
run: ruff format --check nothing_app/
|
|
42
|
+
|
|
43
|
+
test:
|
|
44
|
+
name: Unit tests
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v4
|
|
49
|
+
|
|
50
|
+
- name: Install system dependencies
|
|
51
|
+
run: |
|
|
52
|
+
sudo apt-get update -q
|
|
53
|
+
sudo apt-get install -y python3-gi python3-gi-cairo gir1.2-gtk-4.0 libgirepository1.0-dev
|
|
54
|
+
|
|
55
|
+
# Use a venv that inherits system site-packages so apt-installed gi is visible.
|
|
56
|
+
# PyGObject cannot be pip-built without Cairo/GLib headers; use the distro package.
|
|
57
|
+
- name: Create venv with system site-packages
|
|
58
|
+
run: python3 -m venv --system-site-packages .venv
|
|
59
|
+
|
|
60
|
+
- name: Install test dependencies
|
|
61
|
+
run: .venv/bin/pip install pytest pytest-cov
|
|
62
|
+
|
|
63
|
+
- name: Run tests
|
|
64
|
+
run: .venv/bin/pytest --tb=short --cov=nothing_app --cov-report=term-missing
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
name: Release Dev
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [develop]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
id-token: write # for PyPI OIDC trusted publishing
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release-dev:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
|
|
21
|
+
# ── Get version from setuptools-scm ────────────────────────────────
|
|
22
|
+
# After tag v1.7.0, develop automatically produces 1.7.1.devN
|
|
23
|
+
- name: Get dev version
|
|
24
|
+
id: version
|
|
25
|
+
run: |
|
|
26
|
+
pip install setuptools-scm
|
|
27
|
+
DEV_VERSION=$(python3 -m setuptools_scm)
|
|
28
|
+
SHORT_SHA=$(git rev-parse --short HEAD)
|
|
29
|
+
echo "dev_version=$DEV_VERSION" >> $GITHUB_OUTPUT
|
|
30
|
+
echo "short_sha=$SHORT_SHA" >> $GITHUB_OUTPUT
|
|
31
|
+
echo "Dev version: $DEV_VERSION (sha: $SHORT_SHA)"
|
|
32
|
+
|
|
33
|
+
# ── Patch package name for dev channel ─────────────────────────────
|
|
34
|
+
- name: Patch package name
|
|
35
|
+
run: |
|
|
36
|
+
sed -i 's/^name\s*=\s*"something-x"/name = "something-x-dev"/' pyproject.toml
|
|
37
|
+
sed -i 's/^something-x = /something-x-dev = /' pyproject.toml
|
|
38
|
+
grep -E "^name|something-x" pyproject.toml
|
|
39
|
+
|
|
40
|
+
# ── Build wheel + sdist ─────────────────────────────────────────────
|
|
41
|
+
- name: Set up Python
|
|
42
|
+
uses: actions/setup-python@v5
|
|
43
|
+
with:
|
|
44
|
+
python-version: "3.11"
|
|
45
|
+
|
|
46
|
+
- name: Build distribution
|
|
47
|
+
run: |
|
|
48
|
+
pip install build
|
|
49
|
+
python -m build
|
|
50
|
+
ls dist/
|
|
51
|
+
|
|
52
|
+
# ── Generate changelog with git-cliff ──────────────────────────────
|
|
53
|
+
- name: Install git-cliff
|
|
54
|
+
run: pip install git-cliff
|
|
55
|
+
|
|
56
|
+
- name: Generate pre-release notes
|
|
57
|
+
run: |
|
|
58
|
+
git cliff --unreleased --strip all 2>/dev/null > /tmp/cliff_body.md
|
|
59
|
+
if [ ! -s /tmp/cliff_body.md ]; then
|
|
60
|
+
echo "No user-facing changes since last release." > /tmp/cliff_body.md
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
cat > /tmp/release_notes.md <<HEADER
|
|
64
|
+
## something-x-dev ${{ steps.version.outputs.dev_version }}
|
|
65
|
+
|
|
66
|
+
> Pre-release build from \`develop\` — not for production use.
|
|
67
|
+
|
|
68
|
+
**Commit**: \`${{ steps.version.outputs.short_sha }}\`
|
|
69
|
+
|
|
70
|
+
### Changes since last stable release
|
|
71
|
+
|
|
72
|
+
HEADER
|
|
73
|
+
cat /tmp/cliff_body.md >> /tmp/release_notes.md
|
|
74
|
+
cat >> /tmp/release_notes.md <<'FOOTER'
|
|
75
|
+
|
|
76
|
+
### Install
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install something-x-dev==${{ steps.version.outputs.dev_version }}
|
|
80
|
+
|
|
81
|
+
# Or download the wheel below
|
|
82
|
+
pip install something_x_dev-${{ steps.version.outputs.dev_version }}-py3-none-any.whl
|
|
83
|
+
```
|
|
84
|
+
FOOTER
|
|
85
|
+
|
|
86
|
+
# ── GitHub pre-release ──────────────────────────────────────────────
|
|
87
|
+
- name: Create GitHub pre-release
|
|
88
|
+
uses: softprops/action-gh-release@v2
|
|
89
|
+
with:
|
|
90
|
+
tag_name: "dev-${{ steps.version.outputs.short_sha }}"
|
|
91
|
+
prerelease: true
|
|
92
|
+
body_path: /tmp/release_notes.md
|
|
93
|
+
files: dist/*
|
|
94
|
+
|
|
95
|
+
# ── Publish to PyPI (OIDC — requires trusted publisher configured) ──
|
|
96
|
+
- name: Publish to PyPI
|
|
97
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
id-token: write # for PyPI OIDC trusted publishing
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
release:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
with:
|
|
19
|
+
fetch-depth: 0
|
|
20
|
+
token: ${{ secrets.RELEASE_PAT }}
|
|
21
|
+
|
|
22
|
+
# ── Determine version bump from conventional commit ─────────────────
|
|
23
|
+
- name: Parse commit and bump version
|
|
24
|
+
id: version
|
|
25
|
+
run: |
|
|
26
|
+
COMMIT_MSG=$(git log -1 --pretty=%B)
|
|
27
|
+
echo "Commit: $COMMIT_MSG"
|
|
28
|
+
|
|
29
|
+
# Read current version from last vX.Y.Z tag (not pyproject.toml)
|
|
30
|
+
CURRENT=$(git describe --tags --abbrev=0 --match "v[0-9]*.[0-9]*.[0-9]*" 2>/dev/null | sed 's/^v//')
|
|
31
|
+
if [ -z "$CURRENT" ]; then
|
|
32
|
+
CURRENT="0.0.0"
|
|
33
|
+
fi
|
|
34
|
+
echo "Current version (last tag): $CURRENT"
|
|
35
|
+
|
|
36
|
+
MAJOR=$(echo $CURRENT | cut -d. -f1)
|
|
37
|
+
MINOR=$(echo $CURRENT | cut -d. -f2)
|
|
38
|
+
PATCH=$(echo $CURRENT | cut -d. -f3)
|
|
39
|
+
|
|
40
|
+
if echo "$COMMIT_MSG" | grep -qE "(^(feat|fix|refactor|perf)!:)|(BREAKING CHANGE:)"; then
|
|
41
|
+
BUMP=major
|
|
42
|
+
MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0
|
|
43
|
+
elif echo "$COMMIT_MSG" | grep -qE "^feat(\([^)]+\))?:"; then
|
|
44
|
+
BUMP=minor
|
|
45
|
+
MINOR=$((MINOR + 1)); PATCH=0
|
|
46
|
+
elif echo "$COMMIT_MSG" | grep -qE "^(fix|perf|refactor)(\([^)]+\))?:"; then
|
|
47
|
+
BUMP=patch
|
|
48
|
+
PATCH=$((PATCH + 1))
|
|
49
|
+
else
|
|
50
|
+
echo "Commit type does not trigger a release (docs/chore/style/ci/test). Skipping."
|
|
51
|
+
echo "skip=true" >> $GITHUB_OUTPUT
|
|
52
|
+
exit 0
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
NEW="$MAJOR.$MINOR.$PATCH"
|
|
56
|
+
echo "Bump: $BUMP → $CURRENT → $NEW"
|
|
57
|
+
echo "current=$CURRENT" >> $GITHUB_OUTPUT
|
|
58
|
+
echo "new=$NEW" >> $GITHUB_OUTPUT
|
|
59
|
+
echo "bump=$BUMP" >> $GITHUB_OUTPUT
|
|
60
|
+
echo "skip=false" >> $GITHUB_OUTPUT
|
|
61
|
+
|
|
62
|
+
# ── Tag and push (no pyproject.toml commit needed) ──────────────────
|
|
63
|
+
- name: Create and push release tag
|
|
64
|
+
if: steps.version.outputs.skip != 'true'
|
|
65
|
+
run: |
|
|
66
|
+
git config user.name "github-actions[bot]"
|
|
67
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
68
|
+
git tag "v${{ steps.version.outputs.new }}"
|
|
69
|
+
git push origin "v${{ steps.version.outputs.new }}"
|
|
70
|
+
|
|
71
|
+
# ── Generate changelog with git-cliff ──────────────────────────────
|
|
72
|
+
- name: Install git-cliff
|
|
73
|
+
if: steps.version.outputs.skip != 'true'
|
|
74
|
+
run: pip install git-cliff
|
|
75
|
+
|
|
76
|
+
- name: Generate release notes
|
|
77
|
+
if: steps.version.outputs.skip != 'true'
|
|
78
|
+
run: |
|
|
79
|
+
# --latest: commits from the previous vX.Y.Z tag up to the tag we just pushed
|
|
80
|
+
# cliff.toml: skips merge commits, ignores dev-* tags, filters to conventional commits
|
|
81
|
+
git cliff --latest --strip all 2>/dev/null > /tmp/cliff_body.md
|
|
82
|
+
if [ ! -s /tmp/cliff_body.md ]; then
|
|
83
|
+
echo "No user-facing changes in this release." > /tmp/cliff_body.md
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# Prepend the header + install block; cliff body goes in the middle
|
|
87
|
+
cat > /tmp/release_notes.md <<HEADER
|
|
88
|
+
## Something X v${{ steps.version.outputs.new }}
|
|
89
|
+
|
|
90
|
+
HEADER
|
|
91
|
+
cat /tmp/cliff_body.md >> /tmp/release_notes.md
|
|
92
|
+
cat >> /tmp/release_notes.md <<'FOOTER'
|
|
93
|
+
|
|
94
|
+
### Install
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Arch / Omarchy (recommended)
|
|
98
|
+
sudo pacman -S python-gobject python-dbus python-cairo gtk4 libadwaita
|
|
99
|
+
pip install something-x==${{ steps.version.outputs.new }}
|
|
100
|
+
|
|
101
|
+
# Or download the wheel below
|
|
102
|
+
pip install something_x-${{ steps.version.outputs.new }}-py3-none-any.whl
|
|
103
|
+
```
|
|
104
|
+
FOOTER
|
|
105
|
+
|
|
106
|
+
echo "--- Release notes preview ---"
|
|
107
|
+
cat /tmp/release_notes.md
|
|
108
|
+
|
|
109
|
+
# ── Build wheel + sdist ─────────────────────────────────────────────
|
|
110
|
+
- name: Set up Python
|
|
111
|
+
if: steps.version.outputs.skip != 'true'
|
|
112
|
+
uses: actions/setup-python@v5
|
|
113
|
+
with:
|
|
114
|
+
python-version: "3.11"
|
|
115
|
+
|
|
116
|
+
- name: Build distribution
|
|
117
|
+
if: steps.version.outputs.skip != 'true'
|
|
118
|
+
run: |
|
|
119
|
+
pip install build
|
|
120
|
+
python -m build
|
|
121
|
+
ls dist/
|
|
122
|
+
|
|
123
|
+
# ── Generate changelog with git-cliff ──────────────────────────────
|
|
124
|
+
- name: Install git-cliff
|
|
125
|
+
if: steps.version.outputs.skip != 'true'
|
|
126
|
+
run: pip install git-cliff
|
|
127
|
+
|
|
128
|
+
- name: Generate release notes
|
|
129
|
+
if: steps.version.outputs.skip != 'true'
|
|
130
|
+
run: |
|
|
131
|
+
git cliff --latest --strip all 2>/dev/null > /tmp/cliff_body.md
|
|
132
|
+
if [ ! -s /tmp/cliff_body.md ]; then
|
|
133
|
+
echo "No user-facing changes in this release." > /tmp/cliff_body.md
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
cat > /tmp/release_notes.md <<HEADER
|
|
137
|
+
## Something X v${{ steps.version.outputs.new }}
|
|
138
|
+
|
|
139
|
+
HEADER
|
|
140
|
+
cat /tmp/cliff_body.md >> /tmp/release_notes.md
|
|
141
|
+
cat >> /tmp/release_notes.md <<'FOOTER'
|
|
142
|
+
|
|
143
|
+
### Install
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# Arch / Omarchy (recommended)
|
|
147
|
+
sudo pacman -S python-gobject python-cairo gtk4 libadwaita
|
|
148
|
+
pip install something-x==${{ steps.version.outputs.new }}
|
|
149
|
+
|
|
150
|
+
# Or download the wheel below
|
|
151
|
+
pip install something_x-${{ steps.version.outputs.new }}-py3-none-any.whl
|
|
152
|
+
```
|
|
153
|
+
FOOTER
|
|
154
|
+
|
|
155
|
+
# ── GitHub Release ──────────────────────────────────────────────────
|
|
156
|
+
- name: Create GitHub Release
|
|
157
|
+
if: steps.version.outputs.skip != 'true'
|
|
158
|
+
uses: softprops/action-gh-release@v2
|
|
159
|
+
with:
|
|
160
|
+
tag_name: "v${{ steps.version.outputs.new }}"
|
|
161
|
+
body_path: /tmp/release_notes.md
|
|
162
|
+
files: dist/*
|
|
163
|
+
|
|
164
|
+
# ── Publish to PyPI (OIDC trusted publisher) ────────────────────────
|
|
165
|
+
- name: Publish to PyPI
|
|
166
|
+
if: steps.version.outputs.skip != 'true'
|
|
167
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
168
|
+
|
|
169
|
+
# ── Update AUR package ──────────────────────────────────────────────
|
|
170
|
+
- name: Update PKGBUILD and push to AUR
|
|
171
|
+
if: steps.version.outputs.skip != 'true'
|
|
172
|
+
env:
|
|
173
|
+
NEW_VERSION: ${{ steps.version.outputs.new }}
|
|
174
|
+
run: |
|
|
175
|
+
SHA256=$(sha256sum dist/something_x-${NEW_VERSION}.tar.gz | awk '{print $1}')
|
|
176
|
+
sed -i "s/^pkgver=.*/pkgver=${NEW_VERSION}/" PKGBUILD
|
|
177
|
+
sed -i "s/^pkgrel=.*/pkgrel=1/" PKGBUILD
|
|
178
|
+
sed -i "s/sha256sums=('[^']*')/sha256sums=('${SHA256}')/" PKGBUILD
|
|
179
|
+
|
|
180
|
+
- name: Deploy to AUR
|
|
181
|
+
if: steps.version.outputs.skip != 'true'
|
|
182
|
+
uses: KSXGitHub/github-actions-deploy-aur@v3.0.1
|
|
183
|
+
with:
|
|
184
|
+
pkgname: something-x
|
|
185
|
+
pkgbuild: ./PKGBUILD
|
|
186
|
+
commit_username: github-actions[bot]
|
|
187
|
+
commit_email: github-actions[bot]@users.noreply.github.com
|
|
188
|
+
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|
|
189
|
+
commit_message: "Update to ${{ steps.version.outputs.new }}"
|
|
190
|
+
allow_empty_commits: false
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.so
|
|
7
|
+
*.egg
|
|
8
|
+
*.egg-info/
|
|
9
|
+
.eggs/
|
|
10
|
+
MANIFEST
|
|
11
|
+
|
|
12
|
+
# Build / distribution
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
*.whl
|
|
16
|
+
*.tar.gz
|
|
17
|
+
|
|
18
|
+
# Virtualenvs
|
|
19
|
+
.venv/
|
|
20
|
+
venv/
|
|
21
|
+
env/
|
|
22
|
+
.env
|
|
23
|
+
ENV/
|
|
24
|
+
|
|
25
|
+
# Tools
|
|
26
|
+
.cache/
|
|
27
|
+
.mypy_cache/
|
|
28
|
+
.ruff_cache/
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
*~
|
|
35
|
+
|
|
36
|
+
# OS
|
|
37
|
+
.DS_Store
|
|
38
|
+
Thumbs.db
|
|
39
|
+
|
|
40
|
+
# setuptools-scm generated version file (written at install/build time)
|
|
41
|
+
nothing_app/_version.py
|
|
42
|
+
|
|
43
|
+
# APK reverse-engineering artifacts (local research only)
|
|
44
|
+
*apkm*
|
|
45
|
+
apkm_decompiled/
|
|
46
|
+
apkm_extracted/
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Something X — Device & Platform Compatibility
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Supported devices
|
|
6
|
+
|
|
7
|
+
The RFCOMM `0x55` protocol is shared across the entire Nothing Ear lineup. Confirmed working on **Nothing Ear (2)**; the same activation sequence, ANC wire values, and EQ command IDs are present in the APK for all models listed below.
|
|
8
|
+
|
|
9
|
+
| Device | Protocol confirmed | Community reports |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Nothing Ear (2) | ✅ reverse-engineered from APK | ✅ |
|
|
12
|
+
| Nothing Ear (1) | ✅ same APK protocol class | needs field testing |
|
|
13
|
+
| Nothing Ear (a) | ✅ same APK protocol class | needs field testing |
|
|
14
|
+
| Nothing Ear (stick) | ✅ (no ANC cmd) | needs field testing |
|
|
15
|
+
| CMF Buds / Buds Pro | ⚠️ likely same, different cmd IDs possible | needs field testing |
|
|
16
|
+
| Nothing Ear (open) | ❓ ANC not applicable | not yet tested |
|
|
17
|
+
| CMF Watch | ❓ different protocol expected | not started |
|
|
18
|
+
|
|
19
|
+
**If your device doesn't work:** open an issue with the raw RFCOMM dump (run with `SOMETHING_X_DEBUG=1 ./somethingx`).
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Linux distros
|
|
24
|
+
|
|
25
|
+
The app runs on any Linux system with BlueZ. System package names vary:
|
|
26
|
+
|
|
27
|
+
| Distro | Install command |
|
|
28
|
+
|---|---|
|
|
29
|
+
| Arch / Omarchy | `sudo pacman -S python-gobject python-dbus python-cairo gtk4 libadwaita` |
|
|
30
|
+
| Ubuntu 24.04+ | `sudo apt install python3-gi python3-dbus python3-cairo gir1.2-gtk-4.0 gir1.2-adw-1` |
|
|
31
|
+
| Fedora 39+ | `sudo dnf install python3-gobject python3-dbus python3-cairo gtk4 libadwaita` |
|
|
32
|
+
| openSUSE | `sudo zypper install python3-gobject python3-dbus python3-cairo gtk4 libadwaita` |
|
|
33
|
+
| NixOS | see `flake.nix` |
|
|
34
|
+
|
|
35
|
+
Requirements: `bluetoothd` running, BlueZ ≥ 5.6, GTK4 ≥ 4.6, libadwaita ≥ 1.2.
|
|
36
|
+
|
|
37
|
+
Volume control requires `pactl` — available on any PulseAudio or PipeWire system.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Maintainer: Raphael <raphael.girard.iut@gmail.com>
|
|
2
|
+
pkgname=something-x
|
|
3
|
+
pkgver=1.0.0
|
|
4
|
+
pkgrel=1
|
|
5
|
+
pkgdesc="GTK4 device manager for Nothing earbuds on Linux"
|
|
6
|
+
arch=('any')
|
|
7
|
+
url="https://github.com/SoaOaoS/nothingonmarchy"
|
|
8
|
+
license=('MIT')
|
|
9
|
+
depends=('python' 'python-gobject' 'python-dbus' 'gtk4' 'libadwaita')
|
|
10
|
+
makedepends=('python-build' 'python-installer' 'python-wheel' 'python-setuptools')
|
|
11
|
+
optdepends=('libpulse: volume control via pactl')
|
|
12
|
+
source=("https://files.pythonhosted.org/packages/source/s/something-x/something_x-${pkgver}.tar.gz")
|
|
13
|
+
sha256sums=('SKIP')
|
|
14
|
+
|
|
15
|
+
build() {
|
|
16
|
+
cd "something_x-${pkgver}"
|
|
17
|
+
python -m build --wheel --no-isolation
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
package() {
|
|
21
|
+
cd "something_x-${pkgver}"
|
|
22
|
+
python -m installer --destdir="$pkgdir" dist/*.whl
|
|
23
|
+
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
|
|
24
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Something X — Roadmap
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
## Known Issues
|
|
6
|
+
|
|
7
|
+
- Window control buttons (close/minimize/maximize) in the headerbar had a double-hover effect on non-tiling desktops due to app CSS overriding the system theme — fixed on `feat/fix-headerbar-window-controls`.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## v1.x — Near term
|
|
12
|
+
|
|
13
|
+
### Docs
|
|
14
|
+
- [x] **GitHub Pages** — project landing page + full documentation site (`docs/`)
|
|
15
|
+
|
|
16
|
+
### Distribution
|
|
17
|
+
- [x] AUR package — AUR package for Arch users to replace pip
|
|
18
|
+
- [x] **NixOS flake** — `flake.nix` for Nix users
|
|
19
|
+
- [x] **`.desktop` file** — ships and auto-installs so the app appears in Walker/Rofi/GNOME launcher
|
|
20
|
+
|
|
21
|
+
### Features
|
|
22
|
+
- [x] **Low battery desktop notification** — `notify-send` when any bud drops below 20 %
|
|
23
|
+
- [x] **Background mode** — closing the window hides it; relaunch shows it again (Gio single-instance)
|
|
24
|
+
- [x] **Per-device profiles** — ANC + EQ saved per device address to `~/.config/something-x/profiles.json`, restored automatically on reconnect
|
|
25
|
+
- [x] **CLI quick-toggle** — `something-x --anc off|on|transparency`, `something-x --eq bass`, `something-x --battery`
|
|
26
|
+
- [x] **System tray icon** — show battery on hover via StatusNotifierItem (Waybar/SNI)
|
|
27
|
+
- [x] **Wearing detection display** — show L/R in-ear status on the earbud visual
|
|
28
|
+
- [x] **Auto-connect RFCOMM** — connect as soon as BlueZ reports the device connected, no tap needed
|
|
29
|
+
|
|
30
|
+
### Fixes
|
|
31
|
+
- [x] **Headerbar button hover** — window controls now respect the system theme on all desktops
|
|
32
|
+
|
|
33
|
+
### Protocol
|
|
34
|
+
- [x] **Debug mode** — `SOMETHING_X_DEBUG=1` env var dumps raw RFCOMM frames for contributors
|
|
35
|
+
- [x] **Graceful ANC mode detection** — infer supported modes from RFCOMM level response; hide unsupported buttons
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## v2.x — Medium term
|
|
40
|
+
|
|
41
|
+
### Features
|
|
42
|
+
- [ ] **Multiple devices simultaneously** — open two device pages, manage both at once
|
|
43
|
+
- [ ] **Quick-settings panel** — small floating overlay triggered by keybind
|
|
44
|
+
- [ ] **Touch controls remapping** — if the protocol exposes it (found in APK, not yet implemented)
|
|
45
|
+
- [ ] **Equalizer graph** — visual EQ curve instead of preset pills; custom presets with sliders
|
|
46
|
+
- [ ] **Firmware update check** — compare device firmware against latest known version, show badge
|
|
47
|
+
|
|
48
|
+
### Tech
|
|
49
|
+
- [ ] **Async BlueZ** — replace `dbus-python` with `dbus-fast` for non-blocking I/O
|
|
50
|
+
- [ ] **Unit tests** — protocol encode/decode, CRC, ANC mode mapping
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## v3.x — Long term / ideas
|
|
55
|
+
|
|
56
|
+
- [ ] **CMF Watch support** — different protocol; would need fresh APK reverse-engineering
|
|
57
|
+
- [ ] **Nothing Phone integration** — glyph control, notification mirroring
|
|
58
|
+
- [ ] **GNOME Shell extension** — battery indicator in the top bar
|
|
59
|
+
- [ ] **KDE Plasma widget** — same idea for KDE users
|
|
60
|
+
- [ ] **macOS port** — replace BlueZ D-Bus with CoreBluetooth via `pyobjc` (long shot)
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Won't do
|
|
65
|
+
|
|
66
|
+
- **Windows** — no BlueZ, RFCOMM access requires a different stack entirely
|
|
67
|
+
- **Wayland screenshot / screen capture control** — out of scope
|
|
68
|
+
- **Streaming / media playback control** — MPRIS already handles this system-wide
|
|
69
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[changelog]
|
|
2
|
+
header = ""
|
|
3
|
+
body = """
|
|
4
|
+
{% for group, commits in commits | group_by(attribute="group") %}
|
|
5
|
+
### {{ group }}
|
|
6
|
+
{% for commit in commits | sort(attribute="message") %}
|
|
7
|
+
- {% if commit.scope %}**{{ commit.scope }}**: {% endif %}\
|
|
8
|
+
{{ commit.message | upper_first }}\
|
|
9
|
+
{% endfor %}
|
|
10
|
+
{% endfor %}
|
|
11
|
+
"""
|
|
12
|
+
footer = ""
|
|
13
|
+
trim = true
|
|
14
|
+
|
|
15
|
+
[git]
|
|
16
|
+
conventional_commits = true
|
|
17
|
+
filter_unconventional = true
|
|
18
|
+
split_commits = false
|
|
19
|
+
commit_parsers = [
|
|
20
|
+
{ message = "^feat", group = "Features" },
|
|
21
|
+
{ message = "^fix", group = "Bug Fixes" },
|
|
22
|
+
{ message = "^perf", group = "Performance" },
|
|
23
|
+
{ message = "^refactor", group = "Refactoring" },
|
|
24
|
+
{ message = "^docs", group = "Documentation" },
|
|
25
|
+
{ message = "^style", group = "Styling" },
|
|
26
|
+
{ message = "^test", group = "Testing" },
|
|
27
|
+
# skip anything that isn't useful in a user-facing changelog
|
|
28
|
+
{ message = "^chore: release", skip = true },
|
|
29
|
+
{ message = "^chore", skip = true },
|
|
30
|
+
{ message = "^ci", skip = true },
|
|
31
|
+
{ message = "^build", skip = true },
|
|
32
|
+
# skip all merge commits regardless of how they are worded
|
|
33
|
+
{ message = "^[Mm]erge[ /]", skip = true },
|
|
34
|
+
{ message = "^Merged", skip = true },
|
|
35
|
+
]
|
|
36
|
+
filter_commits = false
|
|
37
|
+
# semver release tags only; dev-* tags are ignored for "previous release" calculation
|
|
38
|
+
tag_pattern = "v[0-9]+\\.[0-9]+\\.[0-9]+"
|
|
39
|
+
ignore_tags = "dev-.*"
|
|
40
|
+
topo_order = false
|
|
41
|
+
sort_commits = "oldest"
|