File share - #254
Draft
pappz wants to merge 183 commits into
Draft
File share#254pappz wants to merge 183 commits into
pappz wants to merge 183 commits into
Conversation
Replace the side drawer + collapsible bottom-sheet pattern with a bottom navigation bar (4 tabs: Home, Peers, Resources, Settings) to mirror the iOS client's TabView. Sub-screens (Advanced, Profiles, Change Server, Troubleshoot, About) are reached from the Settings tab and use an iOS-style sectioned list layout. - New SettingsFragment (sectioned list mirroring iOSSettingsView) - Promote PeersFragment / NetworksFragment to top-level destinations; drop the modal BottomDialogFragment + PagerAdapter - Profile chip on Home opens a ProfilePickerSheet (one-tap switch + Manage profiles link), echoing the iOS ProfileBadge - Restyle AdvancedFragment + TroubleshootFragment as sectioned lists; Theme Mode now opens a bottom-sheet picker - Refresh menu icons to thinner outlined Material Symbols - NavigationRailView via layout-w960dp for large screens / TV - Toolbar hidden on top-level destinations; visible on sub-screens - Profile cards adopt PR #137 dark-mode contrast fix - Treat the empty-profile-state JSON read as a normal first-launch case in ProfileManagerWrapper instead of logging at error level
The destination listener was hiding the bottom nav on the first-launch fragment but still falling through to the top-level toolbar logic, so the toolbar stayed visible. Treat firstInstallFragment as a full-screen take-over and bypass the rest of the listener.
ProfilePickerSheet validated the input via sanitizeProfileName() but still wrote the raw user string, so disallowed characters (anything outside [A-Za-z0-9_-]) made it into the engine. Pass the sanitized value to addProfile() and the success/duplicate toasts so what the user sees matches what was stored.
On a TV or stripped-down build there may not be an Activity that handles ACTION_VIEW for an https URL. Catch ActivityNotFoundException and surface a toast instead of crashing the app.
Hardcoded #FFFFFFFF prevents these icons from adapting to theme overlays (e.g. dark mode, focus inversions on TV). Switch to ?attr/colorControlNormal so each icon picks up the correct tint from its host theme. Affects ic_nav_home, ic_nav_peers, ic_nav_networks, ic_nav_settings, ic_add, ic_check, ic_chevron_right, ic_arrow_drop_down, ic_open_in_new — all custom icons introduced in this branch.
Theme picker rows now expose: - contentDescription with the theme label - stateDescription "Selected" on the active row (Android R+) - isSelected=true on the active row for accessibility services After picking, announce "<theme> theme selected" on the sheet root so TalkBack confirms the change before the sheet dismisses.
On large screens the bottom navigation moves to a side rail (layout-w960dp/activity_main.xml). The 80dp bottom padding fragments add to clear the bottom bar is therefore wasted vertical space — set the dimen to 0dp at the same qualifier so layouts pick the right value automatically without per-layout overrides.
A long profile name was wrapping and pushing the picker row taller than the others, breaking the row rhythm. maxLines=1 + ellipsize=end truncates the overflow with "…" so picker rows stay uniform.
list_item_setting_section.xml duplicated the same padding / text size / caps attributes already defined in @style/SettingsSectionHeader, which the section headers inside fragment_settings.xml etc. already apply via the style. Replace the inline attributes with a single style= reference so the section template is the same source of truth.
CodeRabbit suggested catching a typed exception or pre-checking the state file length. The gomobile binding flattens the Go error chain into go.Universe$proxyerror without surfacing the underlying type, and the state-file path is a Go-side constant not exposed to Java, so neither approach is available without a gomobile API change. Expand the comment to make that trade-off explicit so the next reader doesn't try the same refactor.
Squash-merge the four commits from PR #189 (profile-id branch) onto the redesign branch, adapting the profile-id migration to the new bottom-nav UI instead of the old drawer/NavigationView layout: - getActiveProfile() now returns a Profile (with ID) instead of a String; update SettingsFragment and HomeFragment callers to use getName(). - Drop the PR's drawer-specific MainActivity changes (updateProfileMenuItem, drawer onKeyDown) — the redesign replaced the drawer with bottom nav. - Graft the new disable-IPv6 switch listener into AdvancedFragment and add the IPv6 settings row to fragment_advanced.xml in the redesign row style. - Bump netbird submodule to 62afff6 (adds Profile.ID to the gomobile binding).
Replace the Lottie connect button and background mask with a custom pill-shaped SwitchMaterial toggle (white thumb, orange track when connected), and restructure the home layout to match the iOS client: centered profile chip, NetBird logo, status text, hostname with a tappable IP/IPv6 detail section. - Remove Lottie dependency, ButtonAnimation and unused JSON assets - Add Inter and JetBrains Mono fonts; logo from the iOS client - Hostname shown emphasized, IPv4 in the muted summary (with chevron) - Info rows (IPv4 + IPv6) expand on tapping the summary; IPv6 row only shown when an IPv6 address is available; copy-to-clipboard buttons - Append ellipsis to Connecting/Disconnecting status - Make bottom nav unselected items white in night mode - Drop the 'profile created'/'switched to profile' success toasts
* Add profile id migration * Check if ID is set on Profile * Bump netbird * Update profile-id-name branch * Fix active profile errors, bump netbird * Bump netbird to v0.74.0
Resolve conflicts in favor of the iOS-style bottom-nav redesign: - MainActivity: keep bottom-nav AppBarConfiguration; drop drawer setup, updateProfileMenuItem and drawer-based onKeyDown (drawer no longer exists) - AdvancedFragment: keep compact row-click listeners; drop redundant main block and a duplicate layoutDisableIpv6 listener - fragment_advanced.xml: keep settings_row_bg IPv6/firewall rows; drop main's ConstraintLayout variant that duplicated @+id/layout_force_relay_connection - ProfilesFragment: keep no success toast on profile switch - ProfileManagerWrapper: take main's getActiveProfile (getIsActive + throw); fresh-install empty state is now handled inside the engine - netbird submodule: advance to current main pointer (3aa6c02) Note: gomobile netbird.aar must be regenerated from the new submodule so the Profile.getIsActive() binding is available.
- Rework the connect toggle thumb as a centred layer so the white circle size is independent of the track height - Give the disconnected track a light grey fill with a thin darker border and disable Material auto-tint so the custom per-state colours render - Make the bottom nav background white and drive item icon/text colour off state_checked; use opaque icon fills so itemIconTint applies at full strength - Lighten the home background
- Give the connect toggle thumb a soft drop shadow (baked into the drawable; drop thumbTint so the shadow is not tinted white) - Merge the two info rows (IP / secondary value) into a single bordered box with a middle divider; showDividers hides the separator when the secondary row is gone
Revert to a plain white circle for the connect toggle thumb.
The recent white-surface tweaks hardcoded @color/white and #4A4A4A, which have no night variant, breaking dark mode (white bottom nav, white profile chip, invisible unselected icons). Introduce theme-aware semantic colours instead: - nb_bottom_nav_bg / nb_chip_bg: white in light, dark surface in night - tab_icon_unselected: #4A4A4A in light, white in night
- Reduce row height (52->40dp), text (15->12sp) and copy buttons (40->34dp) - Middle-ellipsize the IPv6 row so a long address is truncated in the centre while the copy button still copies the full value
Use opaque fillColor so app:tint renders the profile picker + and check icons at full nb_orange intensity, matching the manage icon.
Replace the default circular ripple mask on bottom nav / navigation rail items with a rounded-rect (8dp) mask.
Navigating back to home re-inflates the fragment, so the hardcoded android:text default painted "Disconnected" before the real state arrived — and the state update was deferred by two nested post() calls even though registration replays it on the main thread. Move the layout default to tools:text, and apply view updates inline when already on the main thread (engine callbacks, which arrive off the main thread, still post). Snap the toggle thumb after setChecked so it doesn't animate into place on a fresh view.
The sheet listed every profile in a wrap_content RecyclerView, so past a handful of profiles the list grew past the screen and pushed the "Add profile" and "Manage profiles" rows out of reach. Cap the list height, show only the five most recently used profiles, and surface a "Show all profiles (N)" row into the manage screen when there are more. Expand the sheet on open so a long list no longer parks at peek height. Recency is tracked in SharedPreferences since the gomobile Profile has no last-used field. The store prunes entries for profiles that no longer exist on every read, so deleting a profile needs no bookkeeping from the caller and the store cannot outgrow the profile count. Also fix the sheet passing a profile name where switchProfile expects an ID, which made switching from the sheet fail whenever the two differed.
Picks up 78 upstream commits, including the client-side profile work
("Always connect on profile selection except in manage profiles") that
this branch's picker sheet sits on top of.
Adds an edit affordance next to each profile name, opening a dialog prefilled with the current name. Renaming only rewrites the "name" field in the profile config; the ID and its on-disk filename stay put, so the default profile can be renamed too. The picker sheet is unaffected: it reads the name fresh and its most-recently-used ordering is keyed on ID. Because the default profile is now renameable, the adapter's "can this be removed" check moves from name to ID, which no longer identifies it. Renaming and adding also enforce different limits, matching the Go core: a new profile's name doubles as its filename (64 chars), while a rename sets a display name only (128 chars). Requires the submodule bump, which exposes RenameProfile on the Android gomobile binding.
The profiles list reserved bottom_nav_inset, which covers the nav bar but not the add button sitting above it, so the final card stayed partly hidden. Reserve the nav bar, the button, and a gap instead. Left bottom_nav_inset alone since seven other fragments share it and none of them have a FAB.
Tapping a peer opens a full-screen view of everything the client knows about it, following the desktop app's panel: the same rows in the same order, icons per row, latency coloured by band, and transfer counters split into received and sent. Rows are hidden rather than filled with a meaningless value, as on desktop. That matters most for the connection type: "relayed" is a plain bool with no not-connected state, so an idle peer would otherwise read as P2P. Latency, transfer and the ICE rows drop out the same way when there is nothing to report. The screen re-renders from each peer-list snapshot instead of a copy taken when the row was tapped, so it tracks status changes live and closes itself if the peer disappears. Transfer counters and latency move without the list firing a change event, so it also polls once a second while in the foreground, and Peer gains value equality to skip rebuilding rows on the ticks that bring identical data. Requires the submodule bump: PeersList now refreshes WireGuard stats before reading the recorder, without which the counters read as zero.
Network changes no longer restart the engine; they are handled as events. No network: the reconnect loops suspend instead of retrying against an unreachable network, and the UI and the notification show "No network available". The loops resume with a fresh backoff when connectivity returns. Network switch: stale management, signal and relay connections are swept and re-dialed immediately on the new network (cross-transport handover fast path: fix: notify Go core on seamless network handover (cellular → WiFi) while VPN is active #243). WiFi-to-WiFi handovers are detected by network identity, so a same-transport switch triggers the same reconnect path. Availability is seeded from non-VPN internet networks, so an up tunnel cannot mask a missing underlying network. New instrumented e2e suites (NetworkTransitionTest, ExitNodeNetworkTransitionTest) cover blackout, transport-switch and handover scenarios with outage budgets. --------- Co-authored-by: hchengting <74168694+hchengting@users.noreply.github.com>
# Conflicts: # app/src/main/java/io/netbird/client/MainActivity.java # app/src/main/java/io/netbird/client/ServiceAccessor.java # app/src/main/java/io/netbird/client/ui/ssh/SshSessionsFragment.java # app/src/main/res/navigation/mobile_navigation.xml # app/src/main/res/values-de/strings.xml # app/src/main/res/values-es/strings.xml # app/src/main/res/values-fr/strings.xml # app/src/main/res/values-hu/strings.xml # app/src/main/res/values-it/strings.xml # app/src/main/res/values-ja/strings.xml # app/src/main/res/values-pt/strings.xml # app/src/main/res/values-ru/strings.xml # app/src/main/res/values-zh-rCN/strings.xml # app/src/main/res/values/dimens.xml # app/src/main/res/values/strings.xml # netbird # tool/src/main/java/io/netbird/client/tool/EngineRunner.java # tool/src/main/java/io/netbird/client/tool/VPNService.java # tool/src/main/res/values/strings.xml
The Resources view rendered its own connected counter below the segmented control while the header still showed the peers counter. NetworksFragment now reports its counts to the hosting PeersFragment, which swaps the single header line between the peers and resources counters with the toggle.
…lete session dialog
…l it A theme change relaunches MainActivity; the old instance's unbindService reaches the service after the new instance has already bound, so the service's stopSelf destroys it under the fresh binding. Without BIND_AUTO_CREATE the binding neither keeps the service alive nor brings it back, and onServiceDisconnected silently nulls mBinder — every action afterwards fails with "VPN binder is null" until a full stop/start cycle. AUTO_CREATE keeps the service alive while bound and rebinds it after any real death; onServiceDisconnected now logs a warning too.
# Conflicts: # app/src/main/res/layout/fragment_peer_detail.xml
Contributor
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…the desktop The outcome column marked a completed send green but left a received file grey, so green meant one thing on the icon, incoming, and a different, asymmetric thing on the label. Completed is now green in either direction; the label's legend is green arrived, red refused or broke, grey everything else, a transfer in flight included. The row's icon moves from a bare arrow to the desktop's three glyphs: a document carrying the arrow for a file, up or down by direction, and a quote mark for a text snippet. Drawn as 2px round strokes like the Files menu icon. The bare arrows stay where they still mean network traffic, on the peer detail row.
Both carried the paper plane, which says "send" and nothing else: the feature receives as well, and the settings row it sat on is about the receiving policy. Each icon now follows its own label. The segment gets a folder at the 16dp the other segment icons use, since a compound drawable shows at its intrinsic size; the settings row gets the three-node share glyph Android itself uses for sharing. The plane stays on the send button and the share target, where it means what it says.
main received the redesign as a single squashed commit (#179) while this branch carries the same work as individual commits plus file sharing, so git could not match them up and flagged nearly every shared file. Kept from this branch: the file sharing feature, the four-item bottom navigation (Networks folded into the Peers segmented switch, Files and SSH merged into Apps) and the activity-scoped nav lookup the SSH list needs inside the Apps screen. Taken from main: split tunneling and its wiring, the SSH terminal fixes (application cursor keys, IME composition, modifier dimming, no-peek password), IPv6 and cleartext handling in ManagementUrl, the forced TUN rebuild, the remote debug bundle row and the tablet toolbar divider. Translations were union-merged; the unused menu_ssh string was dropped. The submodule pointer stays on this branch's commit.
NewAuth takes a PolicyFetcher for MDM enforcement; a nil one disables it, which is what the client does until it grows a managed configuration source. Preferences.getPreSharedKey is gone in favour of hasPreSharedKey, which also counts a key the MDM policy supplies.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.