Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
5abd317
feat(Seerr): add QuickConnect API endpoints and models
v3DJG6GL Mar 4, 2026
b87a747
feat(Seerr): add QuickConnect service methods
v3DJG6GL Mar 4, 2026
5b23562
feat(Seerr): add QuickConnect tab to Seerr connection dialog
v3DJG6GL Mar 4, 2026
36ba489
feat(Seerr): integrate QuickConnect into login flow for passwordless …
v3DJG6GL Mar 4, 2026
538ddf4
feat: add SEERR_URL env var support to lock Seerr URL
v3DJG6GL Mar 4, 2026
8b7109f
feat: add toggle to hide password login fields
v3DJG6GL Mar 4, 2026
d868c09
fix(ci): build debug APK to bypass keystore signing issue
v3DJG6GL Mar 4, 2026
7697202
fix(login): hide username field when hidePasswordLogin is enabled
v3DJG6GL Mar 5, 2026
38ab1c7
fix(Seerr): stretch QuickConnect tab and center action button
v3DJG6GL Mar 5, 2026
0adff20
feat(login): copy QuickConnect code to clipboard on tap
v3DJG6GL Mar 5, 2026
84875d9
feat(login): add "Open Jellyfin QuickConnect" link in QC dialogs
v3DJG6GL Mar 5, 2026
1213409
fix(l10n): rename "Local Server URL" to "Local Jellyfin URL"
v3DJG6GL Mar 5, 2026
c5ec30b
fix(ci): run Docker deploy for development builds
v3DJG6GL Mar 5, 2026
e5249c5
fix(login): restart QC polling after in-app browser closes in login d…
v3DJG6GL Mar 5, 2026
39f54c7
fix(login): restart QC polling after in-app browser closes
v3DJG6GL Mar 5, 2026
338b63b
fix(login): prevent QC polling from silently stopping on errors
v3DJG6GL Mar 5, 2026
821c91f
fix(login): show settings gear when password login is hidden
v3DJG6GL Mar 5, 2026
ffcf03f
fix(login): auto-add URL scheme for Jellyfin and Seerr URLs
v3DJG6GL Mar 5, 2026
d35bf09
fix(login): add QC polling timeout after 5 minutes
v3DJG6GL Mar 5, 2026
fec9266
fix(security): clear QC secrets in dispose and add security docs
v3DJG6GL Mar 5, 2026
9dbd5b8
fix(deps): upgrade fvp to 0.35.2 to fix nightly mdk-sdk build
v3DJG6GL Mar 5, 2026
e4b3b7d
fix(ci): allow Docker deploy when create_release is skipped
v3DJG6GL Mar 5, 2026
f5b4428
Revert "fix(deps): upgrade fvp to 0.35.2 to fix nightly mdk-sdk build"
v3DJG6GL Mar 5, 2026
ad0cefc
fix(ci): pin mdk-sdk to stable release to fix broken nightly builds
v3DJG6GL Mar 5, 2026
f9309fb
fix(ci): pin mdk-sdk to stable release to fix broken nightly builds
v3DJG6GL Mar 5, 2026
a4e4667
fix(settings): lock Seerr URL field when SEERR_URL is configured
v3DJG6GL Mar 5, 2026
aae0ee7
fix(login): probe Seerr URL scheme (try https first, then http)
v3DJG6GL Mar 5, 2026
5807cc8
fix(login): try https first for Jellyfin URLs without scheme
v3DJG6GL Mar 5, 2026
33732df
fix(docker): pass SEERR_URL env var into config.json in Dockerfile
v3DJG6GL Mar 5, 2026
edfd393
fix(docker): pass SEERR_URL env var into config.json in Dockerfile-ro…
v3DJG6GL Mar 5, 2026
98d51d1
docs(docker): add SEERR_URL env var to docker-compose.yml
v3DJG6GL Mar 5, 2026
7ca0df8
fix(seerr): handle browser-hidden Set-Cookie header on web with senti…
v3DJG6GL Mar 5, 2026
fe55659
feat(seerr): add default HTTP client factory for Seerr
v3DJG6GL Mar 5, 2026
4d6b822
feat(seerr): add web HTTP client factory with withCredentials
v3DJG6GL Mar 5, 2026
8856b60
feat(seerr): enable withCredentials on web HTTP client for cookie auth
v3DJG6GL Mar 5, 2026
d73318d
ci: trigger rebuild
v3DJG6GL Mar 5, 2026
95ad6f9
ci: retrigger build
v3DJG6GL Mar 5, 2026
eb925bc
feat(docker): wire HIDE_PASSWORD_LOGIN env var in Dockerfile
v3DJG6GL Mar 5, 2026
57af5d8
feat(docker): wire HIDE_PASSWORD_LOGIN env var in Dockerfile-rootless
v3DJG6GL Mar 5, 2026
91a4634
feat(docker): add HIDE_PASSWORD_LOGIN to docker-compose.yml
v3DJG6GL Mar 5, 2026
d32cd6e
fix(login): center Back/Refresh row when server field is hidden
v3DJG6GL Mar 5, 2026
d78abb5
fix(login): hide Advanced button when Seerr URL is set via Docker
v3DJG6GL Mar 5, 2026
ab5a0b6
fix(login): center Advanced button when password login is hidden
v3DJG6GL Mar 5, 2026
0ad22f5
refactor(login): extract shared Advanced button callback into method
v3DJG6GL Mar 5, 2026
61f195c
fix(settings): lock hidePasswordLogin toggle when set via Docker
v3DJG6GL Mar 6, 2026
d7d578c
feat(docker): add entrypoint script for config and nginx proxy genera…
v3DJG6GL Mar 6, 2026
f19e82f
feat(docker): add nginx config template with proxy placeholder
v3DJG6GL Mar 6, 2026
6a28227
refactor(docker): use entrypoint script and add jq for header parsing
v3DJG6GL Mar 6, 2026
f0af456
refactor(docker): use entrypoint script and add jq for header parsing…
v3DJG6GL Mar 6, 2026
c62c297
feat(docker): add SEERR_CUSTOM_HEADERS env var
v3DJG6GL Mar 6, 2026
914ed3e
feat(config): add seerrProxyPath field for nginx proxy routing
v3DJG6GL Mar 6, 2026
00f580b
feat(config): add seerrProxyPath to default config
v3DJG6GL Mar 6, 2026
6421308
feat(seerr): route requests through nginx proxy when seerrProxyPath i…
v3DJG6GL Mar 6, 2026
93cc7a3
fix(docker): replace sed template with cat heredoc in entrypoint
v3DJG6GL Mar 6, 2026
0735825
fix(docker): remove unused nginx.conf.template
v3DJG6GL Mar 6, 2026
7e9ae0a
fix(docker): remove template handling and add PORT env in Dockerfile
v3DJG6GL Mar 6, 2026
3fdc929
fix(docker): remove template handling and add PORT env in Dockerfile-…
v3DJG6GL Mar 6, 2026
0335911
title: refactor(docker): use SEERR_PROXY_PATH variable in nginx locat…
v3DJG6GL Mar 6, 2026
b533317
fix(docker): switch back to nginx user before CMD in rootless Dockerfile
v3DJG6GL Mar 6, 2026
ba66234
chore: reset build.yml and pubspec.lock to develop
v3DJG6GL Mar 6, 2026
304785a
chore: reset build.yml to upstream develop
v3DJG6GL Mar 6, 2026
37444b1
fix: dart formatting issues
v3DJG6GL Mar 6, 2026
66f4c65
fix: add curly braces to if-statements, format with line-length 120
v3DJG6GL Mar 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
FROM nginx:alpine

RUN apk add --no-cache jq

EXPOSE 80

ENV BASE_URL=""
ENV SEERR_URL=""
ENV HIDE_PASSWORD_LOGIN=""
ENV SEERR_CUSTOM_HEADERS=""
ENV PORT=80

COPY build/web /usr/share/nginx/html
COPY docker/docker-entrypoint.sh /docker-entrypoint.sh

RUN echo '{"baseUrl": "${BASE_URL}"}' > /usr/share/nginx/html/assets/config/config.json
RUN chmod +x /docker-entrypoint.sh

CMD /bin/sh -c 'sed -i "s|\${BASE_URL}|${BASE_URL}|g" /usr/share/nginx/html/assets/config/config.json && nginx -g "daemon off;"'
CMD ["/docker-entrypoint.sh"]
17 changes: 11 additions & 6 deletions Dockerfile-rootless
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ FROM ghcr.io/nginxinc/nginx-unprivileged:stable-alpine-slim
EXPOSE 8080

ENV BASE_URL=""
ENV SEERR_URL=""
ENV HIDE_PASSWORD_LOGIN=""
ENV SEERR_CUSTOM_HEADERS=""
ENV PORT=8080

USER root
RUN apk add --no-cache jq
COPY build/web /usr/share/nginx/html
RUN chown -R nginx:nginx /usr/share/nginx/html
COPY docker/docker-entrypoint.sh /docker-entrypoint.sh

USER nginx
RUN mkdir -p /usr/share/nginx/html/assets/config && \
echo '{"baseUrl": "${BASE_URL}"}' > /usr/share/nginx/html/assets/config/config.json
RUN chmod +x /docker-entrypoint.sh && \
chown -R nginx:nginx /usr/share/nginx/html && \
chown -R nginx:nginx /etc/nginx/conf.d

USER root
CMD /bin/sh -c 'sed -i "s|\${BASE_URL}|${BASE_URL}|g" /usr/share/nginx/html/assets/config/config.json && nginx -g "daemon off;"'
USER nginx
CMD ["/docker-entrypoint.sh"]
7 changes: 5 additions & 2 deletions config/config.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"baseUrl": null
}
"baseUrl": null,
"seerrUrl": null,
"hidePasswordLogin": null,
"seerrProxyPath": null
}
3 changes: 3 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ services:
- 80:80
environment:
- BASE_URL=https://server-url #OPTIONAL: Locks the Fladder front-end to a certain jellyfin server
- SEERR_URL= #OPTIONAL: Pre-fills and locks the Seerr URL in settings
- HIDE_PASSWORD_LOGIN= #OPTIONAL: Set to "true" to hide password fields and only show QuickConnect
- SEERR_CUSTOM_HEADERS= #OPTIONAL: JSON object of headers injected server-side via nginx proxy, e.g. '{"X-Auth": "secret"}'
60 changes: 60 additions & 0 deletions docker/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/sh
set -e

CONFIG="/usr/share/nginx/html/assets/config/config.json"
NGINX_CONF="/etc/nginx/conf.d/default.conf"

# --- Build config.json ---

HIDE_PW_VAL=$([ "$HIDE_PASSWORD_LOGIN" = "true" ] && echo true || echo null)

# Determine seerrProxyPath: set when both SEERR_URL and SEERR_CUSTOM_HEADERS are provided
if [ -n "$SEERR_URL" ] && [ -n "$SEERR_CUSTOM_HEADERS" ]; then
SEERR_PROXY_PATH="/seerr-proxy"
else
SEERR_PROXY_PATH=""
fi

SEERR_PROXY_JSON=$([ -n "$SEERR_PROXY_PATH" ] && echo "\"$SEERR_PROXY_PATH\"" || echo null)

cat > "$CONFIG" <<EOF
{
"baseUrl": $([ -n "$BASE_URL" ] && echo "\"$BASE_URL\"" || echo null),
"seerrUrl": $([ -n "$SEERR_URL" ] && echo "\"$SEERR_URL\"" || echo null),
"hidePasswordLogin": $HIDE_PW_VAL,
"seerrProxyPath": $SEERR_PROXY_JSON
}
EOF

# --- Build nginx config ---

PROXY_BLOCK=""
if [ -n "$SEERR_URL" ] && [ -n "$SEERR_CUSTOM_HEADERS" ]; then
# Build proxy_set_header directives from JSON object
HEADER_DIRECTIVES=$(echo "$SEERR_CUSTOM_HEADERS" | jq -r 'to_entries[] | " proxy_set_header \(.key) \"\(.value)\";"')

PROXY_BLOCK="
location ${SEERR_PROXY_PATH}/ {
proxy_pass ${SEERR_URL}/;
proxy_set_header Host \$proxy_host;
proxy_ssl_server_name on;
${HEADER_DIRECTIVES}
}"
fi

cat > "$NGINX_CONF" <<EOF
server {
listen ${PORT};
root /usr/share/nginx/html;
index index.html;

location / {
try_files \$uri \$uri/ /index.html;
}
${PROXY_BLOCK}
}
EOF

# --- Start nginx ---

exec nginx -g "daemon off;"
14 changes: 11 additions & 3 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,8 @@
"quickConnectPostFailed": "Failed to get quick connect code",
"quickConnectLoginUsingCode": "Using quick connect",
"quickConnectEnterCodeDescription": "Enter the code below to login",
"openJellyfinQuickConnect": "Open Jellyfin QuickConnect",
"@openJellyfinQuickConnect": {},
"showMore": "Show more",
"showLess": "Show less",
"itemColorsTitle": "Item colors",
Expand Down Expand Up @@ -1563,9 +1565,9 @@
"screensaverBlack": "Black",
"playerSettingsScreensaverTitle": "Screensaver",
"playerSettingsScreensaverDesc": "Select screen saver that will be shown after no player activity",
"settingsLocalUrlTitle": "Local Server URL",
"settingsLocalUrlSetTitle": "Configure Local URL",
"settingsLocalUrlSetDesc": "Specify the local server address. Fladder will automatically use this URL when your device is on the same network.",
"settingsLocalUrlTitle": "Local Jellyfin URL",
"settingsLocalUrlSetTitle": "Configure Local Jellyfin URL",
"settingsLocalUrlSetDesc": "Specify the local Jellyfin address. Fladder will automatically use this URL when your device is on the same network.",
"regenerateTrickplayImages": "Regenerate trickplay images",
"controlPanel": "Control Panel",
"@controlPanel": {},
Expand Down Expand Up @@ -2129,6 +2131,12 @@
"@seerrAuthLocal": {},
"seerrAuthJellyfin": "Jellyfin",
"@seerrAuthJellyfin": {},
"seerrAuthQuickConnect": "QuickConnect",
"@seerrAuthQuickConnect": {},
"hidePasswordLogin": "Hide password login",
"@hidePasswordLogin": {},
"hidePasswordLoginDescription": "Only show QuickConnect on the login screen",
"@hidePasswordLoginDescription": {},
"seerrUserFetchFailed": "Failed to fetch user from Seerr",
"@seerrUserFetchFailed": {},
"seerrEnterServerUrlFirst": "Enter a Seerr server URL first",
Expand Down
2 changes: 2 additions & 0 deletions lib/models/login_screen_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ abstract class LoginScreenModel with _$LoginScreenModel {
ServerLoginModel? serverLoginModel,
String? errorMessage,
@Default(false) bool hasBaseUrl,
@Default(false) bool hasSeerrUrl,
@Default(false) bool hidePasswordLogin,
@Default(false) bool loading,
String? tempSeerrUrl,
String? tempSeerrSessionCookie,
Expand Down
50 changes: 48 additions & 2 deletions lib/models/login_screen_model.freezed.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/models/settings/client_settings_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ abstract class ClientSettingsModel with _$ClientSettingsModel {
@Default(false) bool usePosterForLibrary,
@Default(false) bool useSystemIME,
@Default(false) bool useTVExpandedLayout,
@Default(false) bool hidePasswordLogin,
String? lastViewedUpdate,
int? libraryPageSize,
@Default({}) Map<GlobalHotKeys, KeyCombination> shortcuts,
Expand Down
Loading