plex-tui 0.4.2__tar.gz → 0.4.4__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.
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/post-release-homebrew.yml +120 -3
- {plex_tui-0.4.2 → plex_tui-0.4.4}/AGENTS.md +9 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/CHANGELOG.md +27 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/PACKAGING.md +16 -6
- {plex_tui-0.4.2 → plex_tui-0.4.4}/PKG-INFO +28 -6
- {plex_tui-0.4.2 → plex_tui-0.4.4}/README.md +27 -5
- {plex_tui-0.4.2 → plex_tui-0.4.4}/RELEASE.md +11 -4
- {plex_tui-0.4.2 → plex_tui-0.4.4}/ROADMAP.md +21 -8
- {plex_tui-0.4.2 → plex_tui-0.4.4}/config.example.toml +9 -1
- plex_tui-0.4.4/docs/homebrew-install-time.md +171 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/docs/plex-integration-research.md +8 -17
- {plex_tui-0.4.2 → plex_tui-0.4.4}/packaging/aur/.SRCINFO +3 -3
- {plex_tui-0.4.2 → plex_tui-0.4.4}/packaging/aur/PKGBUILD +2 -2
- {plex_tui-0.4.2 → plex_tui-0.4.4}/packaging/homebrew/README.md +12 -3
- {plex_tui-0.4.2 → plex_tui-0.4.4}/pyproject.toml +1 -1
- {plex_tui-0.4.2 → plex_tui-0.4.4}/scripts/check_release.py +38 -0
- plex_tui-0.4.4/scripts/measure_homebrew_install.py +154 -0
- plex_tui-0.4.4/scripts/prepare_homebrew_bottle_assets.py +70 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/__init__.py +1 -1
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/app.py +295 -32
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/config.py +10 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/player.py +39 -4
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/plex_service.py +134 -5
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_app_helpers.py +70 -9
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_app_navigation.py +282 -19
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_config.py +6 -1
- plex_tui-0.4.4/tests/test_homebrew_bottle_assets.py +72 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_player.py +36 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_plex_service.py +71 -1
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_release_checks.py +27 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/aur.yml +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/bump.yml +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/ci.yml +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/post-release-aur.yml +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/publish-aur.yml +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/publish-pypi.yml +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.github/workflows/publish-testpypi.yml +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/.gitignore +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/LICENSE +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/Makefile +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/docs/assets/grid-view.png +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/docs/assets/list-view.png +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/packaging/aur/README.md +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/scripts/stage_release.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/scripts/update_aur_package.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/scripts/update_homebrew_formula.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/__main__.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/artwork.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/auth.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/models.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/src/plextui/smoke.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_artwork.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_auth.py +0 -0
- {plex_tui-0.4.2 → plex_tui-0.4.4}/tests/test_cli.py +0 -0
|
@@ -13,6 +13,7 @@ on:
|
|
|
13
13
|
|
|
14
14
|
env:
|
|
15
15
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
16
|
+
HOMEBREW_NO_REQUIRE_TAP_TRUST: "1"
|
|
16
17
|
|
|
17
18
|
jobs:
|
|
18
19
|
publish-tap:
|
|
@@ -133,14 +134,127 @@ jobs:
|
|
|
133
134
|
"${{ steps.tap.outputs.path }}/Formula/plex-tui.rb" \
|
|
134
135
|
"${{ steps.release.outputs.version }}"
|
|
135
136
|
|
|
136
|
-
- name:
|
|
137
|
+
- name: Check tap update need
|
|
137
138
|
if: steps.release.outputs.publish == 'true'
|
|
139
|
+
id: tap-update
|
|
140
|
+
working-directory: ${{ steps.tap.outputs.path }}
|
|
141
|
+
env:
|
|
142
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
143
|
+
run: |
|
|
144
|
+
set -euo pipefail
|
|
145
|
+
|
|
146
|
+
bottle_release="plex-tui-${VERSION}"
|
|
147
|
+
bottle_root_url="https://github.com/so1omon563/homebrew-plex-tui/releases/download/${bottle_release}"
|
|
148
|
+
needed=false
|
|
149
|
+
|
|
150
|
+
if ! git diff --quiet -- Formula/plex-tui.rb; then
|
|
151
|
+
needed=true
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
if ! grep -Fq "root_url \"${bottle_root_url}\"" Formula/plex-tui.rb; then
|
|
155
|
+
needed=true
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
{
|
|
159
|
+
echo "needed=${needed}"
|
|
160
|
+
echo "bottle_release=${bottle_release}"
|
|
161
|
+
echo "bottle_root_url=${bottle_root_url}"
|
|
162
|
+
} >> "$GITHUB_OUTPUT"
|
|
163
|
+
|
|
164
|
+
if [ "$needed" = "false" ]; then
|
|
165
|
+
echo "Homebrew tap is already up to date with bottle metadata."
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
- name: Build Homebrew bottle
|
|
169
|
+
if: steps.release.outputs.publish == 'true' && steps.tap-update.outputs.needed == 'true'
|
|
170
|
+
id: bottle
|
|
171
|
+
timeout-minutes: 60
|
|
172
|
+
working-directory: ${{ steps.tap.outputs.path }}
|
|
173
|
+
env:
|
|
174
|
+
BOTTLE_ROOT_URL: ${{ steps.tap-update.outputs.bottle_root_url }}
|
|
175
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
176
|
+
run: |
|
|
177
|
+
set -euo pipefail
|
|
178
|
+
|
|
179
|
+
brew --version
|
|
180
|
+
brew config
|
|
181
|
+
brew info so1omon563/plex-tui/plex-tui
|
|
182
|
+
|
|
183
|
+
(
|
|
184
|
+
while true; do
|
|
185
|
+
sleep 60
|
|
186
|
+
echo "Still building Homebrew bottle for plex-tui ${VERSION} at $(date -u +%Y-%m-%dT%H:%M:%SZ)."
|
|
187
|
+
done
|
|
188
|
+
) &
|
|
189
|
+
heartbeat_pid=$!
|
|
190
|
+
trap 'kill "$heartbeat_pid" 2>/dev/null || true' EXIT
|
|
191
|
+
|
|
192
|
+
brew uninstall --ignore-dependencies so1omon563/plex-tui/plex-tui >/dev/null 2>&1 || true
|
|
193
|
+
brew install --verbose --build-bottle so1omon563/plex-tui/plex-tui
|
|
194
|
+
kill "$heartbeat_pid" 2>/dev/null || true
|
|
195
|
+
trap - EXIT
|
|
196
|
+
|
|
197
|
+
rm -f plex-tui--*.bottle.json plex-tui--*.bottle.tar.gz
|
|
198
|
+
brew bottle \
|
|
199
|
+
--json \
|
|
200
|
+
--no-rebuild \
|
|
201
|
+
--root-url "$BOTTLE_ROOT_URL" \
|
|
202
|
+
so1omon563/plex-tui/plex-tui
|
|
203
|
+
|
|
204
|
+
bottle_json="$(find "$PWD" -maxdepth 1 -name 'plex-tui--*.bottle.json' -print -quit)"
|
|
205
|
+
if [ -z "$bottle_json" ]; then
|
|
206
|
+
echo "brew bottle did not produce bottle JSON" >&2
|
|
207
|
+
exit 1
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
bottle_dir="${RUNNER_TEMP}/homebrew-bottles"
|
|
211
|
+
rm -rf "$bottle_dir"
|
|
212
|
+
mkdir -p "$bottle_dir"
|
|
213
|
+
python "${GITHUB_WORKSPACE}/scripts/prepare_homebrew_bottle_assets.py" \
|
|
214
|
+
"$bottle_json" \
|
|
215
|
+
--output-dir "$bottle_dir"
|
|
216
|
+
|
|
217
|
+
brew bottle --merge --write --no-commit "$bottle_json"
|
|
218
|
+
|
|
219
|
+
{
|
|
220
|
+
echo "json_path=${bottle_json}"
|
|
221
|
+
echo "upload_dir=${bottle_dir}"
|
|
222
|
+
} >> "$GITHUB_OUTPUT"
|
|
223
|
+
|
|
224
|
+
- name: Publish Homebrew bottle assets
|
|
225
|
+
if: steps.release.outputs.publish == 'true' && steps.tap-update.outputs.needed == 'true'
|
|
226
|
+
working-directory: ${{ steps.bottle.outputs.upload_dir }}
|
|
227
|
+
env:
|
|
228
|
+
GH_TOKEN: ${{ secrets.PACKAGING_PR_TOKEN }}
|
|
229
|
+
VERSION: ${{ steps.release.outputs.version }}
|
|
230
|
+
BOTTLE_RELEASE: ${{ steps.tap-update.outputs.bottle_release }}
|
|
231
|
+
run: |
|
|
232
|
+
set -euo pipefail
|
|
233
|
+
|
|
234
|
+
if gh release view "$BOTTLE_RELEASE" --repo so1omon563/homebrew-plex-tui >/dev/null 2>&1; then
|
|
235
|
+
gh release edit "$BOTTLE_RELEASE" \
|
|
236
|
+
--repo so1omon563/homebrew-plex-tui \
|
|
237
|
+
--title "plex-tui ${VERSION} Homebrew bottle"
|
|
238
|
+
else
|
|
239
|
+
gh release create "$BOTTLE_RELEASE" \
|
|
240
|
+
--repo so1omon563/homebrew-plex-tui \
|
|
241
|
+
--target main \
|
|
242
|
+
--title "plex-tui ${VERSION} Homebrew bottle" \
|
|
243
|
+
--notes "Homebrew bottle assets for plex-tui ${VERSION}."
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
gh release upload "$BOTTLE_RELEASE" ./* \
|
|
247
|
+
--repo so1omon563/homebrew-plex-tui \
|
|
248
|
+
--clobber
|
|
249
|
+
|
|
250
|
+
- name: Audit formula
|
|
251
|
+
if: steps.release.outputs.publish == 'true' && steps.tap-update.outputs.needed == 'true'
|
|
138
252
|
working-directory: ${{ steps.tap.outputs.path }}
|
|
139
253
|
run: |
|
|
140
254
|
brew audit --strict --online so1omon563/plex-tui/plex-tui
|
|
141
255
|
|
|
142
256
|
- name: Commit tap update
|
|
143
|
-
if: steps.release.outputs.publish == 'true'
|
|
257
|
+
if: steps.release.outputs.publish == 'true' && steps.tap-update.outputs.needed == 'true'
|
|
144
258
|
id: commit
|
|
145
259
|
working-directory: ${{ steps.tap.outputs.path }}
|
|
146
260
|
env:
|
|
@@ -172,15 +286,18 @@ jobs:
|
|
|
172
286
|
GH_TOKEN: ${{ secrets.PACKAGING_PR_TOKEN }}
|
|
173
287
|
VERSION: ${{ steps.release.outputs.version }}
|
|
174
288
|
BRANCH: ${{ steps.commit.outputs.branch }}
|
|
289
|
+
BOTTLE_RELEASE: ${{ steps.tap-update.outputs.bottle_release }}
|
|
175
290
|
run: |
|
|
176
291
|
set -euo pipefail
|
|
177
292
|
|
|
293
|
+
pr_body="$(printf 'Automated Homebrew tap update for plex-tui %s.\n\nIncludes the generated bottle metadata for %s.\n' "$VERSION" "$BOTTLE_RELEASE")"
|
|
294
|
+
|
|
178
295
|
pr_url="$(gh pr create \
|
|
179
296
|
--repo so1omon563/homebrew-plex-tui \
|
|
180
297
|
--base main \
|
|
181
298
|
--head "$BRANCH" \
|
|
182
299
|
--title "Update plex-tui to ${VERSION}" \
|
|
183
|
-
--body "
|
|
300
|
+
--body "$pr_body")"
|
|
184
301
|
|
|
185
302
|
gh pr merge "$pr_url" \
|
|
186
303
|
--repo so1omon563/homebrew-plex-tui \
|
|
@@ -184,6 +184,11 @@ Pull requests should include:
|
|
|
184
184
|
Use PRs for repository changes. When publishing local commits, branch from
|
|
185
185
|
`main` with a scoped name such as `codex/release-prep`, push that branch, and
|
|
186
186
|
open a draft PR instead of pushing directly to `main`.
|
|
187
|
+
Create or switch to a scoped branch before doing repo work; do not keep feature
|
|
188
|
+
work in the local `main` working tree.
|
|
189
|
+
Repo work is not complete when a branch is merely pushed. Treat the workflow as
|
|
190
|
+
open until there is a draft PR for the branch or the work is explicitly
|
|
191
|
+
canceled.
|
|
187
192
|
|
|
188
193
|
`main` is protected by repository rulesets. Changes must flow through PRs; force
|
|
189
194
|
pushes and branch deletion are blocked. `plex-tui` requires the Python 3.11 and
|
|
@@ -198,6 +203,10 @@ merge should create the GitHub Release and publish package channels. Exceptions
|
|
|
198
203
|
are allowed for packaging-only follow-ups, automation repair, docs-only
|
|
199
204
|
maintenance, or other changes that should not create a new version tag; call out
|
|
200
205
|
the reason in the PR body when omitting a bump marker.
|
|
206
|
+
When a change is judged release-worthy, do not only add `#release`: run the
|
|
207
|
+
scripted release prep in the same branch and keep the release marker in the PR
|
|
208
|
+
title. A release decision means both staged release files and a publishing
|
|
209
|
+
marker are required unless the release is explicitly canceled.
|
|
201
210
|
|
|
202
211
|
When preparing or estimating a release version, fetch remote tags first with
|
|
203
212
|
`git fetch --tags origin` and base the decision on the latest origin tag, not
|
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.4.4 - 2026-06-18
|
|
6
|
+
|
|
7
|
+
- Added a keyboard action to mark the selected playable Plex item watched or
|
|
8
|
+
unwatched from the browse view.
|
|
9
|
+
- Added Plex library Categories browsing, visible movie-edition variants, and
|
|
10
|
+
live mpv audio/subtitle switching when the active playback exposes matching
|
|
11
|
+
tracks.
|
|
12
|
+
- Made library rows open the full Library view by default, with Space opening
|
|
13
|
+
the browse-mode menu as the alternate action, and added a Settings option to
|
|
14
|
+
swap those actions.
|
|
15
|
+
- Added a Backspace/Delete Continue Watching removal action for selected items
|
|
16
|
+
in the Continue Watching view.
|
|
17
|
+
- Improved episode readability by showing show, season, and episode context in
|
|
18
|
+
episode rows and directly under the episode title in details.
|
|
19
|
+
|
|
20
|
+
## 0.4.3 - 2026-06-18
|
|
21
|
+
|
|
22
|
+
- Made the default `mpv` window open with `--autofit=80%`, keeping custom
|
|
23
|
+
Settings overrides for exact pixel sizes or other percentage presets, and
|
|
24
|
+
made the old `1280x720` preset cycle back to Default.
|
|
25
|
+
- Added Homebrew bottle publishing to the post-release tap automation so macOS
|
|
26
|
+
installs can pour a prebuilt `plex-tui` virtualenv instead of rebuilding
|
|
27
|
+
Python resources from source, with bounded verbose CI diagnostics for bottle
|
|
28
|
+
builds.
|
|
29
|
+
- Documented that Homebrew bottles are published for Apple Silicon macOS, while
|
|
30
|
+
Intel macOS remains supported through Homebrew's source-build path.
|
|
31
|
+
|
|
5
32
|
## 0.4.2 - 2026-06-18
|
|
6
33
|
|
|
7
34
|
- Prefer episode stills and season posters for TV artwork while keeping show art
|
|
@@ -51,8 +51,12 @@ brew install plex-tui
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
The formula depends on `mpv` and `python@3.13`, then installs the Python app in
|
|
54
|
-
a Homebrew-managed virtualenv.
|
|
55
|
-
|
|
54
|
+
a Homebrew-managed virtualenv. Post-release automation publishes Homebrew
|
|
55
|
+
bottles for Apple Silicon macOS so supported installs can pour the prebuilt app
|
|
56
|
+
virtualenv instead of rebuilding Python resources such as `pillow` from source.
|
|
57
|
+
Intel macOS remains supported through Homebrew's source install path while that
|
|
58
|
+
platform continues to be supported. If no matching bottle is available,
|
|
59
|
+
Homebrew falls back to the source install path.
|
|
56
60
|
Homebrew 6 requires non-official taps to be trusted before Homebrew loads
|
|
57
61
|
formulae from them. The `plex-tui` formula only uses Homebrew/core formula
|
|
58
62
|
dependencies, so users do not need to trust any additional taps for `mpv`,
|
|
@@ -65,6 +69,10 @@ brew test so1omon563/plex-tui/plex-tui
|
|
|
65
69
|
brew audit --strict --online so1omon563/plex-tui/plex-tui
|
|
66
70
|
```
|
|
67
71
|
|
|
72
|
+
Install-time investigation lives in `docs/homebrew-install-time.md`. Use
|
|
73
|
+
`scripts/measure_homebrew_install.py` to capture no-op upgrade, reinstall,
|
|
74
|
+
fresh-install, and bottle-pour timings before changing the tap formula.
|
|
75
|
+
|
|
68
76
|
### Arch AUR
|
|
69
77
|
|
|
70
78
|
AUR package:
|
|
@@ -95,8 +103,8 @@ Validation is handled by `.github/workflows/aur.yml`, which runs inside
|
|
|
95
103
|
For each new app release:
|
|
96
104
|
|
|
97
105
|
1. Publish and validate PyPI.
|
|
98
|
-
2. Let the `Post-release Homebrew Publish` workflow update, validate,
|
|
99
|
-
the Homebrew tap formula.
|
|
106
|
+
2. Let the `Post-release Homebrew Publish` workflow update, bottle, validate,
|
|
107
|
+
and merge the Homebrew tap formula.
|
|
100
108
|
3. Let the `Post-release AUR Update` workflow update AUR metadata, open the
|
|
101
109
|
packaging PR, approve it, and enable auto-merge.
|
|
102
110
|
4. After the packaging PR merges and the `AUR Package` workflow passes on
|
|
@@ -111,9 +119,11 @@ The AUR automation requires:
|
|
|
111
119
|
`ssh://aur@aur.archlinux.org/plex-tui.git`.
|
|
112
120
|
|
|
113
121
|
The Homebrew automation uses `PACKAGING_PR_TOKEN`; that token must also be able
|
|
114
|
-
to
|
|
122
|
+
to create or update GitHub Releases, upload bottle assets, push branches, and
|
|
123
|
+
merge pull requests in `so1omon563/homebrew-plex-tui`.
|
|
115
124
|
|
|
116
125
|
## Known Follow-Up
|
|
117
126
|
|
|
118
|
-
-
|
|
127
|
+
- Continue validating Homebrew bottle publishing on release dry-runs and
|
|
128
|
+
follow-up packaging PRs.
|
|
119
129
|
- Consider standalone artifacts only after the app behavior stabilizes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plex-tui
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: A small standalone Plex terminal UI.
|
|
5
5
|
Project-URL: Homepage, https://github.com/so1omon563/plex-tui
|
|
6
6
|
Project-URL: Issues, https://github.com/so1omon563/plex-tui/issues
|
|
@@ -108,9 +108,11 @@ brew install plex-tui
|
|
|
108
108
|
plex-tui --smoke
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
-
The Homebrew formula installs `mpv` automatically.
|
|
112
|
-
|
|
113
|
-
from source.
|
|
111
|
+
The Homebrew formula installs `mpv` automatically. Apple Silicon macOS installs
|
|
112
|
+
use prebuilt bottles when available so Homebrew can pour the app virtualenv
|
|
113
|
+
instead of rebuilding native Python dependencies such as `pillow` from source.
|
|
114
|
+
Intel macOS installs still use Homebrew's source-build path while that platform
|
|
115
|
+
continues to be supported.
|
|
114
116
|
Homebrew 6 requires non-official taps to be trusted before Homebrew loads
|
|
115
117
|
formulae from them. `plex-tui` only depends on formulae from Homebrew/core, so no
|
|
116
118
|
additional tap trust is required for its dependencies.
|
|
@@ -204,7 +206,15 @@ preferences are applied when matching streams are available, and the details
|
|
|
204
206
|
pane shows the effective playback choices. Playback mode defaults to
|
|
205
207
|
direct/default behavior and can be changed in Settings to force Plex
|
|
206
208
|
transcoding with Original, 1080p 8 Mbps, 720p 4 Mbps, or 480p 2 Mbps quality
|
|
207
|
-
presets.
|
|
209
|
+
presets. The default `mpv` launch uses `--autofit=80%` so videos open at a
|
|
210
|
+
comfortable size on modern displays; Settings can override this with values
|
|
211
|
+
such as `90%`, `1280x720`, or `80%x80%`. If an older config has an exact
|
|
212
|
+
`mpv_window_size = "1280x720"` override, cycle the mpv window-size setting once
|
|
213
|
+
to return to the Default preset.
|
|
214
|
+
Use `w` from a playable movie or episode to toggle its Plex watched state.
|
|
215
|
+
When playback is active, choosing an audio or subtitle track from the picker
|
|
216
|
+
also asks mpv to switch the active track when the launched stream exposes a
|
|
217
|
+
matching track.
|
|
208
218
|
|
|
209
219
|
## Key Bindings
|
|
210
220
|
|
|
@@ -218,6 +228,7 @@ presets.
|
|
|
218
228
|
| `tab` / `shift+tab` | Move focus |
|
|
219
229
|
| `l` | Focus libraries |
|
|
220
230
|
| `m` | Focus media |
|
|
231
|
+
| `space` | Run the alternate action for a selected library |
|
|
221
232
|
| `v` | Toggle list/grid view |
|
|
222
233
|
| `pageup` / `pagedown` | Move one page in grid view |
|
|
223
234
|
| `,` | Show settings |
|
|
@@ -225,6 +236,8 @@ presets.
|
|
|
225
236
|
| `enter` | Open selected item |
|
|
226
237
|
| `p` | Play selected item from the beginning |
|
|
227
238
|
| `r` | Resume selected item from the saved Plex position |
|
|
239
|
+
| `w` | Mark selected item watched / unwatched |
|
|
240
|
+
| `backspace` / `delete` | Remove selected item from Continue Watching |
|
|
228
241
|
| `a` / `s` | Choose audio / subtitle preference |
|
|
229
242
|
| `A` / `S` | Clear audio preference / cycle subtitle mode |
|
|
230
243
|
| `x` | Stop launched `mpv` |
|
|
@@ -233,14 +246,23 @@ presets.
|
|
|
233
246
|
|
|
234
247
|
- Plex PIN login and server selection.
|
|
235
248
|
- Paged library browsing with automatic loading near the end of loaded items.
|
|
249
|
+
- Library submenu entrypoints for all items, Recommended, Collections,
|
|
250
|
+
Playlists, and Categories. Library rows open all items by default; Space
|
|
251
|
+
opens the browse-mode menu, and Settings can swap the primary and alternate
|
|
252
|
+
actions.
|
|
236
253
|
- Current-library search and bounded global search.
|
|
237
254
|
- List view plus configurable-density grid view with terminal poster artwork.
|
|
238
255
|
- External subtitle support and direct playback for embedded PGS/VOBSUB tracks.
|
|
239
256
|
- Audio and subtitle pickers with saved language preferences.
|
|
240
257
|
- Separate play-from-start and resume actions with Plex progress reporting.
|
|
258
|
+
- Watched/unwatched toggling for selected playable Plex items.
|
|
259
|
+
- Continue Watching episode rows show their show, season, and episode context,
|
|
260
|
+
and items can be removed from the Continue Watching view.
|
|
261
|
+
- Movie editions appear as distinct variants when Plex reports multiple
|
|
262
|
+
editions for a selected movie.
|
|
241
263
|
- Settings screen for stream preferences, playback mode and transcode quality,
|
|
242
264
|
artwork modes, grid density, page size, auto-load threshold, grid artwork
|
|
243
|
-
prefetching, media view, and `mpv` window size.
|
|
265
|
+
prefetching, media view, library Enter behavior, and `mpv` window size.
|
|
244
266
|
- App diagnostics view for version, paths, `mpv`, Plex connection, artwork, and
|
|
245
267
|
browsing settings.
|
|
246
268
|
|
|
@@ -71,9 +71,11 @@ brew install plex-tui
|
|
|
71
71
|
plex-tui --smoke
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
The Homebrew formula installs `mpv` automatically.
|
|
75
|
-
|
|
76
|
-
from source.
|
|
74
|
+
The Homebrew formula installs `mpv` automatically. Apple Silicon macOS installs
|
|
75
|
+
use prebuilt bottles when available so Homebrew can pour the app virtualenv
|
|
76
|
+
instead of rebuilding native Python dependencies such as `pillow` from source.
|
|
77
|
+
Intel macOS installs still use Homebrew's source-build path while that platform
|
|
78
|
+
continues to be supported.
|
|
77
79
|
Homebrew 6 requires non-official taps to be trusted before Homebrew loads
|
|
78
80
|
formulae from them. `plex-tui` only depends on formulae from Homebrew/core, so no
|
|
79
81
|
additional tap trust is required for its dependencies.
|
|
@@ -167,7 +169,15 @@ preferences are applied when matching streams are available, and the details
|
|
|
167
169
|
pane shows the effective playback choices. Playback mode defaults to
|
|
168
170
|
direct/default behavior and can be changed in Settings to force Plex
|
|
169
171
|
transcoding with Original, 1080p 8 Mbps, 720p 4 Mbps, or 480p 2 Mbps quality
|
|
170
|
-
presets.
|
|
172
|
+
presets. The default `mpv` launch uses `--autofit=80%` so videos open at a
|
|
173
|
+
comfortable size on modern displays; Settings can override this with values
|
|
174
|
+
such as `90%`, `1280x720`, or `80%x80%`. If an older config has an exact
|
|
175
|
+
`mpv_window_size = "1280x720"` override, cycle the mpv window-size setting once
|
|
176
|
+
to return to the Default preset.
|
|
177
|
+
Use `w` from a playable movie or episode to toggle its Plex watched state.
|
|
178
|
+
When playback is active, choosing an audio or subtitle track from the picker
|
|
179
|
+
also asks mpv to switch the active track when the launched stream exposes a
|
|
180
|
+
matching track.
|
|
171
181
|
|
|
172
182
|
## Key Bindings
|
|
173
183
|
|
|
@@ -181,6 +191,7 @@ presets.
|
|
|
181
191
|
| `tab` / `shift+tab` | Move focus |
|
|
182
192
|
| `l` | Focus libraries |
|
|
183
193
|
| `m` | Focus media |
|
|
194
|
+
| `space` | Run the alternate action for a selected library |
|
|
184
195
|
| `v` | Toggle list/grid view |
|
|
185
196
|
| `pageup` / `pagedown` | Move one page in grid view |
|
|
186
197
|
| `,` | Show settings |
|
|
@@ -188,6 +199,8 @@ presets.
|
|
|
188
199
|
| `enter` | Open selected item |
|
|
189
200
|
| `p` | Play selected item from the beginning |
|
|
190
201
|
| `r` | Resume selected item from the saved Plex position |
|
|
202
|
+
| `w` | Mark selected item watched / unwatched |
|
|
203
|
+
| `backspace` / `delete` | Remove selected item from Continue Watching |
|
|
191
204
|
| `a` / `s` | Choose audio / subtitle preference |
|
|
192
205
|
| `A` / `S` | Clear audio preference / cycle subtitle mode |
|
|
193
206
|
| `x` | Stop launched `mpv` |
|
|
@@ -196,14 +209,23 @@ presets.
|
|
|
196
209
|
|
|
197
210
|
- Plex PIN login and server selection.
|
|
198
211
|
- Paged library browsing with automatic loading near the end of loaded items.
|
|
212
|
+
- Library submenu entrypoints for all items, Recommended, Collections,
|
|
213
|
+
Playlists, and Categories. Library rows open all items by default; Space
|
|
214
|
+
opens the browse-mode menu, and Settings can swap the primary and alternate
|
|
215
|
+
actions.
|
|
199
216
|
- Current-library search and bounded global search.
|
|
200
217
|
- List view plus configurable-density grid view with terminal poster artwork.
|
|
201
218
|
- External subtitle support and direct playback for embedded PGS/VOBSUB tracks.
|
|
202
219
|
- Audio and subtitle pickers with saved language preferences.
|
|
203
220
|
- Separate play-from-start and resume actions with Plex progress reporting.
|
|
221
|
+
- Watched/unwatched toggling for selected playable Plex items.
|
|
222
|
+
- Continue Watching episode rows show their show, season, and episode context,
|
|
223
|
+
and items can be removed from the Continue Watching view.
|
|
224
|
+
- Movie editions appear as distinct variants when Plex reports multiple
|
|
225
|
+
editions for a selected movie.
|
|
204
226
|
- Settings screen for stream preferences, playback mode and transcode quality,
|
|
205
227
|
artwork modes, grid density, page size, auto-load threshold, grid artwork
|
|
206
|
-
prefetching, media view, and `mpv` window size.
|
|
228
|
+
prefetching, media view, library Enter behavior, and `mpv` window size.
|
|
207
229
|
- App diagnostics view for version, paths, `mpv`, Plex connection, artwork, and
|
|
208
230
|
browsing settings.
|
|
209
231
|
|
|
@@ -124,9 +124,15 @@ be run manually with a release tag. It updates:
|
|
|
124
124
|
- Formula URL and sha256.
|
|
125
125
|
- Python resource blocks if dependencies changed.
|
|
126
126
|
- Formula test expectations if version output changed.
|
|
127
|
+
- Homebrew bottle assets and the generated formula `bottle do` block.
|
|
127
128
|
|
|
128
|
-
It
|
|
129
|
-
|
|
129
|
+
It builds the formula with `brew install --build-bottle`, generates bottle
|
|
130
|
+
metadata with `brew bottle --json`, uploads the bottle tarball to a
|
|
131
|
+
`plex-tui-X.Y.Z` GitHub Release in the tap repository, merges the generated
|
|
132
|
+
`bottle do` block into the formula, runs `brew audit --strict --online`, opens a
|
|
133
|
+
tap PR, and merges it. This uses `PACKAGING_PR_TOKEN`, which must have access to
|
|
134
|
+
create releases, upload assets, push branches, and merge pull requests in the
|
|
135
|
+
tap repository.
|
|
130
136
|
|
|
131
137
|
If the automated workflow cannot run, update and validate manually:
|
|
132
138
|
|
|
@@ -186,8 +192,9 @@ To verify post-release packaging without publishing a new app release, manually
|
|
|
186
192
|
dispatch the post-release workflows with the latest real release tag, for
|
|
187
193
|
example `v0.3.6`. A healthy idempotent run should:
|
|
188
194
|
|
|
189
|
-
- update and audit the Homebrew formula
|
|
190
|
-
|
|
195
|
+
- update, bottle, and audit the Homebrew formula when bottle metadata is
|
|
196
|
+
missing; then skip tap PR creation on later reruns when the formula and bottle
|
|
197
|
+
block are already current;
|
|
191
198
|
- regenerate and validate AUR metadata, then skip packaging PR auto-merge when
|
|
192
199
|
there is no diff.
|
|
193
200
|
|
|
@@ -32,8 +32,10 @@
|
|
|
32
32
|
requires the Python 3.11 and 3.13 checks before merge. Rulesets require PRs
|
|
33
33
|
with zero approving reviews so automation branches can merge after checks
|
|
34
34
|
without self-approval.
|
|
35
|
-
- Improve Homebrew install time; the current
|
|
36
|
-
|
|
35
|
+
- Improve Homebrew install time; baseline the current install/update paths with
|
|
36
|
+
`scripts/measure_homebrew_install.py`, then prioritize tap bottle automation.
|
|
37
|
+
The current formula works but builds Python resources from source, with
|
|
38
|
+
native compilation concentrated in `pillow`.
|
|
37
39
|
- Keep post-release package publishing fully automated across PyPI, Homebrew,
|
|
38
40
|
and AUR. Periodically dry-run existing release tags through the post-release
|
|
39
41
|
workflows to confirm Homebrew and AUR no-op cleanly when already current.
|
|
@@ -45,19 +47,30 @@
|
|
|
45
47
|
[`anthonycaccese/240-MP`](https://github.com/anthonycaccese/240-MP/tree/main)
|
|
46
48
|
live in `docs/plex-integration-research.md`.
|
|
47
49
|
- Continue Watching now has a sidebar browse entrypoint backed by Plex on-deck
|
|
48
|
-
data;
|
|
50
|
+
data; selected items can be removed from Continue Watching. Watch for
|
|
51
|
+
real-library edge cases around ordering and pagination.
|
|
49
52
|
- Selective library visibility is available in Settings so noisy Plex libraries
|
|
50
53
|
can be hidden from the sidebar.
|
|
51
|
-
- Library submenus are available for Library, Recommended, Collections,
|
|
52
|
-
Playlists
|
|
53
|
-
|
|
54
|
+
- Library submenus are available for Library, Recommended, Collections,
|
|
55
|
+
Playlists, and Categories. Categories use PlexAPI category helpers when
|
|
56
|
+
present and genre filter choices as the fallback. Library rows open all items
|
|
57
|
+
by default, Space opens the browse-mode menu, and Settings can swap those
|
|
58
|
+
primary/alternate actions.
|
|
54
59
|
- Alphabet navigation is available for loaded browse lists and grids with
|
|
55
60
|
previous/next section jumps.
|
|
56
61
|
- Explicit playback controls are available for play-from-start versus resume,
|
|
57
62
|
direct/default playback versus selected transcode quality presets, and
|
|
58
63
|
Plex-side resume offsets for transcoded streams.
|
|
59
|
-
-
|
|
60
|
-
|
|
64
|
+
- Watched/unwatched toggling is available for selected playable movies and
|
|
65
|
+
episodes.
|
|
66
|
+
- Movie editions are visible as distinct variants when Plex reports multiple
|
|
67
|
+
editions for a selected movie.
|
|
68
|
+
- In-playback audio/subtitle switching uses mpv IPC when the active stream
|
|
69
|
+
exposes matching tracks; Plex-transcoded streams may still require relaunching
|
|
70
|
+
with the saved preference.
|
|
71
|
+
- Design playlist management before implementation: adding/removing media from
|
|
72
|
+
playlists and creating playlists are intentionally out of PR #80 scope.
|
|
73
|
+
- Later design passes: profile switching with auto sign-in.
|
|
61
74
|
|
|
62
75
|
## Technical Follow-Up
|
|
63
76
|
|
|
@@ -14,7 +14,11 @@ client_identifier = "plex-tui-your-stable-client-id"
|
|
|
14
14
|
# preferred_subtitle_language = "eng"
|
|
15
15
|
# subtitle_mode can be "auto", "none", or "preferred".
|
|
16
16
|
# subtitle_mode = "preferred"
|
|
17
|
-
# Optional mpv window size passed as --autofit.
|
|
17
|
+
# Optional mpv window size passed as --autofit. Empty uses the app default
|
|
18
|
+
# "80%" for a more comfortable window on modern displays.
|
|
19
|
+
# Examples: "90%", "1280x720", "80%x80%".
|
|
20
|
+
# Existing exact-size overrides such as "1280x720" stay exact until reset or
|
|
21
|
+
# changed in Settings.
|
|
18
22
|
# mpv_window_size = "1280x720"
|
|
19
23
|
# playback_mode can be "auto" for direct/default playback or "transcode" to
|
|
20
24
|
# force Plex transcoding.
|
|
@@ -48,6 +52,10 @@ client_identifier = "plex-tui-your-stable-client-id"
|
|
|
48
52
|
# detail_artwork_mode = "list_only"
|
|
49
53
|
# media_view can be "list" or "grid".
|
|
50
54
|
# media_view = "list"
|
|
55
|
+
# library_enter_action can be "library" or "browse_modes". The default
|
|
56
|
+
# "library" opens all items with Enter and uses Space for browse modes.
|
|
57
|
+
# "browse_modes" swaps those two actions.
|
|
58
|
+
# library_enter_action = "library"
|
|
51
59
|
# grid_density can be "compact", "comfortable", or "large".
|
|
52
60
|
# grid_density = "comfortable"
|
|
53
61
|
# Textual theme selected from the command palette.
|