| Age | Commit message (Collapse) | Author | Files | Lines |
|
The detached HEAD error sent users to "Settings > Git utils", a screen
the Compose settings no longer have. Every locale now names Settings >
Repository > Local Git config & utilities, and the English quotes are
escaped so they show. The git configuration screen's title reuses that
translated row label instead of an untranslatable English string.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The success dialog showed a literal conflicting-<branch>-... instead of
the branch BreakOutOfDetached pushed. It now reads the newest local
conflicting-<branch>-<millis> ref, which is the one just created.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
AutofillDecryptActivity was its last subclass: it now sets FLAG_SECURE
and injects the settings, crypto repository and dispatchers itself. The
path and clipboard helpers move to CryptoExtensions.kt as top-level
functions (a test pins the path helpers), and the FILE_PATH extra key
moves, unchanged, to LaunchActivity. An invalid or short .gpg-id ID is
reported with a toast: the snackbar never showed in the autofill
decryption, which closes its window at once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The Compose screens use no Fragments or view binding, so
FragmentExtensions (with its four slide animators) and
FragmentViewBindingDelegate have no users, nor do resolveAttribute,
isPermissionGranted, launchActivity and the unused Modifier.conditional.
SearchableRepositoryViewModel keeps one navigateTo: the Compose list owns
the back stack, so the RecyclerView-era navigation stack, stableId,
isFiltered and the unused DirectoriesOnly mode go. PasswordItem loses
the parent overloads, @JvmStatic and the unread NAME extra, and the
leftover sentry.properties goes too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
hasEnabledAutofillServices() still answers true right after
disableAutofillServices(), so the switch stayed on and the next tap
turned autofill off again instead of opening the instructions dialog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The picker decides which entry fills the requesting app, so it drops
touches under another app's overlay, as the publisher warning does.
The entry view now uses cachesPassphrase too, so the cache rule lives in
one place, and the publisher warning's app name gets its closing quote.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The autofill activities cannot join MainActivity's graph, so they keep
opening the PGP key import through the setup intent; the spec and the
ponytail note no longer promise otherwise. The spec gains an Autofill
section.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Autofill re-cached the passphrase it had just read from the cache, and
cached an empty one for keys without a passphrase. Like the entry view,
it now caches only what the user typed into the passphrase dialog.
An unreadable .gpg-id left the transparent window up with a snackbar no
one could see; the activity now finishes and fills nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
AutofillDecryptActivity shows the no keys dialog and the entry view's
passphrase dialog in Compose over its transparent FLAG_SECURE window.
The flow starts once, on the first window focus, instead of on every
onStart: Android 14 evicts a screen lock prompt shown before the
activity is on top, and a restart showed a second passphrase dialog.
After a key import it restarts on the next focus. Dismissing the no
keys dialog now finishes instead of leaving an invisible window.
Rotation and resizing no longer recreate the activity; other
recreations cancel the fill.
The passphrase is now cached only after a successful screen lock
prompt, as the entry view does: a passphrase typed after a cancelled
or unavailable prompt was cached whenever the cache feature was on.
PasswordDialog, its layout, dimens.xml and requireKeysExist lose their
last user and go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The Re-enable button replaced Advanced information in place, so a quick
double tap re-enabled autofill for an app with a changed publisher
(upstream had the same flaw). The package and certificate details now
come first and push Re-enable below them. The title is marked as a
heading and the footer's ponytail note sits on the footer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
- Run the first search during composition with the saved query and
strict switch, so a recreated picker no longer flashes the results
for the initial query under the restored text.
- Scroll the result list back to the top on every new result, as the
old picker did.
- Fall back to the file name when a row has neither identifier nor
account part, instead of an empty label. DirectoryStructure never
returns both null today, so no test can reach it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
AutofillPublisherChangedActivity draws the warning with the shared
theme. Keep Autofill disabled is now the primary button, and the
Possible phishing attempt title replaces the logo. Re-enabling still
takes two taps (Advanced information first) and still clears the
app's matches before returning the prepared fill response; every other
way out fills nothing. Touches that reach the warning through another
app's window are now dropped (filterTouchesWhenObscured on the decor
view), so an overlay cannot trick the user into re-enabling.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
AutofillFilterView draws the picker with the shared theme: origin
header, search field, entry rows in a grouped surface and the three
switches, over the same SearchableRepositoryViewModel search. Rows
name the origin identifier and show the account and folders below it.
The first tap wins, so a double tap no longer starts two decryptions.
PasswordViewHolder, the RecyclerView adapter, the two layouts, their
drawables, the multiselect color and their lint baseline entries go.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
autofillRows turns the picker's search results into list rows: the
origin identifier, the part that must match the site or app, becomes
the row's name, and the account part and the folders above it the
subtitle, as the old picker's bold title and subtitle showed them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
LaunchActivity showed the screen lock prompt from onCreate, before the
activity was on top. Android 14's SystemUI evicts a prompt whose app is
not the top activity ("Evicting client due to top activity is not ..."),
so the prompt closed at once with ERROR_CANCELED and the app quit. This
is upstream issue 2802, which upstream worked around by disabling the
setting on Android 14. The prompt now opens on the first window focus.
LaunchActivity also used a translucent theme, so after unlocking the
home screen showed through until MainActivity drew. It now uses the
app's opaque theme.
Verified on an Android 14 tablet with a PIN-only screen lock: unlock
opens the app without a flash of the home screen, cancel closes it, and
turning the lock off asks for the PIN.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
- A host with an empty port was saved, but ProxySelector treats port -1
as no proxy, so git silently connected directly. The port is now
required while a host is set.
- Patterns.WEB_URL accepted "http://proxy.example.org:3128/" as a host,
which then broke every HTTPS operation. The host must be a numeric
address or a plain domain name, without scheme, port or path.
- setDefaultProxy copied the proxy password into the process-wide
http.proxyPassword system property. The Authenticator already supplies
the credentials, so the properties are only cleared now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The Compose settings, git config, commit log and proxy screens replace
SettingsActivity with its six preference providers, GitConfigActivity
with TextInputDialog, GitLogActivity with its adapter and GitLogModel,
and ProxySelectorActivity, with their layouts and manifest entries.
The dead OpenKeystore key ID row goes with its string, the Android 14
platform bug summary and normal_margin lose their last users, and the
setup intent loses the two starts only Settings used.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The list and the welcome screen open the Compose settings; their rows
open the git server, SSH key, key generation, PGP keys, proxy and git
config screens within the graph. Deleting the repository returns to the
welcome screen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
executeAfterAuthentication waited for another result whenever the
prompt reported Failure, on the assumption that Failure meant a failed
attempt with the prompt still open. Failure comes from error callbacks
(lockout, timeout, unable to process), which always close the prompt,
so the operation hung forever. Only Retry keeps the prompt open; every
other result now ends the wait, and Failure and CanceledBySystem fail
the operation with the generic screen lock error, like the other
non-success results.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
BiometricAuthenticator mapped onAuthenticationError(ERROR_UNABLE_TO_PROCESS)
to Retry, but an error callback always closes the prompt. The settings
screen keeps its one-prompt-at-a-time guard set on Retry, so the gated
switches stayed locked until the section was left. The error now maps to
Failure; Retry comes only from onAuthenticationFailed, while the prompt is
still open.
Once the device screen lock is removed, the biometric app lock could not
be turned off: the prompt returns HardwareUnavailableOrDisabled and nothing
was written. Turning it off without a usable screen lock now writes the
value directly, as the passphrase cache row already does.
The settings category rows and PreferenceAction rows get Role.Button for
accessibility services.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Author name and email, HEAD status, commit log, abort rebase, hard
reset and gc. The hard reset now warns and prefills the current branch;
a finished reset or gc stays on the screen with a snackbar, and a
failed operation keeps the screen too. The commit log is read off the
main thread. BreakOutOfDetached's not-rebasing dialog no longer
finishes the calling activity.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Host, port, user name and password. An invalid host or port blocks the
save, an emptied port is cleared, the proxy applies at once, and the
screen is FLAG_SECURE while the saved password is on it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The categories and one screen per category, with the old rows over the
same keys. Screen lock gated switches store their value only after a
successful prompt. Clearing a saved HTTPS password or SSH passphrase,
which never removed anything, now asks and removes it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Switch, single choice, text and action rows over the existing
preference keys, and a ViewModel that reads every displayed value,
follows preference changes, deletes the store without following
symlinks, and clears saved credentials and the passphrase cache.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The Compose list shows folders and entries in separate groups, so the
files first and type independent sort orders did nothing visible. They
are removed; a stored one migrates to folders first, and any unknown
value reads as folders first instead of throwing. The OpenKeychain SSH
key ID, which nothing reads any more, is removed once.
GitSettings wrote the proxy user name to the proxy preferences but read
it from the main settings, so ProxyUtils never authenticated.
Adds the pure parts of the settings port: proxy port parsing, HEAD
status and the commit log.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
- A store a cancelled attempt already made for the chosen key (its
.gpg-id names exactly that key) no longer counts as occupied:
choosing the key again commits and moves on instead of refusing.
- SSH key import reads at most 100 kB whatever the provider reports,
like the PGP import, instead of reading the stream whole.
- PGPKeyManager replaces a key through a temporary file moved over it
atomically, so a failed write keeps the old key; listings only read
.key files, so a stray temporary file is never taken for a key.
- "View generated public SSH key" goes through the settings result
launcher, so the preference visibility refreshes afterwards.
- A plain start from LaunchActivity replaces the task: an open
MainActivity (e.g. one whose store vanished) is no longer left
below the new one, and one back leaves the app.
- The PGP keys screen's import FAB carries its content description
itself; M3 cleared the icon's.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The Compose welcome, git server, SSH key, key generation and PGP keys
screens replace OnboardingActivity with its fragments,
GitServerConfigActivity with BasicBottomSheet, SshKeyImportActivity,
SshKeyGenActivity, ShowSshKeyFragment, PGPKeyImportActivity and
PGPKeyListActivity with KeyList and PGPKeyListViewModel, their layouts
and manifest entries, and ui:compose's APSAppBar. Resources only they
used are removed too.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
- createStore refuses a non-empty store folder (only .git allowed), so a
restored, cloned store keeps its .gpg-id
- failed store creation cleans up with deleteWithoutFollowingLinks, which
also removes a fresh .git
- PGP keys screen: Later goes through the guarded leave path
- Import SSH key row launches via the result launcher so the public key
row refreshes
- GitServerViewModel.changeUrl always refits the auth mode, also for an
empty URL
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The welcome screen starts the app without a store, the list sends a
vanished store back to it, and its clone prompt opens the git server
screen. A clone asks for the store's PGP key when none matches it.
Settings, the entry view, autofill decryption and git operations open
the setup screens through MainActivity.setupIntent. The No SSH key
dialog's Cancel and the unusable screen lock prompt no longer finish
the calling activity, which is now the app's main screen.
KeysMode is a route argument, so it is kept from minification (lint
MissingKeepAnnotation).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
One screen for managing keys, choosing the key of a new local store
and importing the key a store needs. Rows show user ID and key ID;
the import keeps the old success, replace and failure dialogs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The SSH key screen shows the key's state and, for a generated key, the
public key with copy and share, and imports a key file after the old
replace confirmation. The generation screen ports the old one; the
key is generated in the ViewModel after the screen lock prompt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The welcome screen merges the old welcome and repository type screens.
The git server screen serves clone and edit: the old URL checks as
dialogs, authentication mode buttons, the SSH key's state with Manage,
the host key reset, and a clone that keeps the screen on failure.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
- PGP key import reads at most 1 MiB (bounded read, buffer zeroed) and
refuses larger files with a new message.
- SshKeyViewModel catches any Exception from import and generation
(CancellationException rethrown) instead of a short list, so an
unexpected provider or sshj error no longer crashes the app.
- Pending PGP key bytes are zeroed in a finally block, also on
cancellation during addKey after a replace, and an earlier pending
pick is zeroed before a new one takes its place.
- PGPKeyManager never replaces a stored secret key with a public-only
key of the same ID, with or without replace (KeyDowngradeException);
the setup ViewModel shows a localized message for it. Unit test added.
- storeRecipients strips '#' comments and a trailing '!' as pass reads
.gpg-id; tests added.
- GitServerViewModel.clearStore returns the failure when the store
folder cannot be emptied, so the clone does not start; the plan's
Task 3 call site reports it.
- readGpgId opens the file with NOFOLLOW_LINKS and reads at most
64 KiB + 1 bytes, refusing more.
- SshKey.import writes the new private key to a temp file and moves it
over atomically before dropping the old key's Keystore entry, public
key and passphrase, so an I/O error keeps the old key.
- KeyUtils.isSecretKey notes (ponytail) that GnuPG stub and smartcard
keyrings count as secret.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Git server (URL, mode, clone state, the after-clone key check), SSH
key (import and generation off the main thread, outcome kept across
recreation) and PGP keys (rows with key IDs, import with the replace
question, delete by key ID, creation of a local store).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
URL checks and fixes, authentication modes per URL, the clone target,
the store's recipients, a size- and symlink-checked .gpg-id read and
the .gpg-id text for a new store (uppercase long key IDs), as pure
functions for the Compose setup screens. The SSH key import now also
requires a format sshj recognizes (an OpenPGP private key block
matched the old marker check and was imported as the SSH key) and no
longer crashes on an empty size cursor. KeyUtils tells secret keys
apart and no longer throws on a key without user ID.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Recent Conscrypt (Android 14 mainline updates) registers a KeyFactory
for Ed25519. With sshj leaving provider selection to the JCA, its
Ed25519KeyFactory now gets Conscrypt's key class, whose algorithm name
sshj does not map to ssh-ed25519: KeyType.fromKey returns UNKNOWN and
every Ed25519 host key fails with "Don't know how to encode key", so
clone and sync over SSH break. 0.1.4 is affected since the sshj 0.41.2
update.
Register a provider at position 1 that serves only KeyFactory.Ed25519
from Bouncy Castle (kept by the existing R8 rule). Everything else,
including signatures with Android Keystore keys, still goes through
normal JCA provider selection.
Verified on an Android 14 tablet: clone over SSH failed before and
works with the fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit ad3c63f665e6264ed1db42d6ae2dfc0947e33393)
|
|
- Look up the .gpg-id from the normalized target's folder, so a
prefilled folder such as a/../b cannot pick a/'s recipients.
- Derive the edited entry's folder from its canonical parent, so a
store path spelled differently does not show as ../../data/...;
the file name still comes from the link.
- Drop the REPO_PATH shortcut extra nothing reads any more.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The Compose editor, generator sheet, OTP dialog and folder picker
replace PasswordCreationActivity, the generator and manual OTP dialog
fragments, SelectFolderActivity with its fragment and adapter, their
layouts and menus, and upstream's unused EditPasswordScreen with the
PasswordField it used. flowbinding and swiperefreshlayout had no other
users. BasePGPActivity keeps what autofill decryption still needs.
Also drops two stale SshKey baseline entries, the snackbar FAB anchor
whose view is gone, and resources only the deleted files used.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
AutofillSaveActivity shows the editor itself, prefilled from the form
and FLAG_SECURE, instead of starting the legacy editor for a result. The
autofill match and the generated-password fill work as before: the
username and password are read back from the saved content, as the old
editor did.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A successful save left saving set while the destination committed in
the activity's lifecycleScope. An activity recreated then (theme,
locale, split-screen resize) cancelled that scope: onSaved never ran,
and the surviving ViewModel kept Save disabled and back swallowed.
The ViewModel now keeps the success in a memory-only saved state, set
inside the NonCancellable write so a cancelled caller cannot lose it.
A LaunchedEffect on it runs the commit and onSaved, so a recreated
editor finishes the job; "Save and copy" and the stale-original notice
run once only, and left() clears it before onSaved navigates.
Editing a symlinked entry derived its folder from the canonical path
but its name from the link, saving a new entry next to the target. The
folder is now relative to the non-canonical repository directory; the
save still checks the target is inside the store.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
EditRoute replaces the legacy editor for new entries and edits. An edit
copies its plaintext from the entry view's ViewModel below it, never
through the route or saved state. Saving returns to the list, closing
returns to where the editor was opened. FLAG_SECURE is now counted in
MainActivity, so moving between the entry view and the editor never
clears it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Stateless editor: name, folder breadcrumbs with Change, password with
reveal and generator, username, extra content and the OTP actions. The
generator sheet has random and diceware tabs with the old options; the
manual OTP dialog and the sheet are FLAG_SECURE.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
- Run the save's write, original delete, autofill and history updates
under NonCancellable so a recreated activity cannot leave a half
done rename.
- fsync the temporary file before the atomic move.
- Move dialog: refuse targets outside the store (symlinks) and moving
a folder into itself or a descendant, with a toast.
- Folder picker: do not navigate into a new folder whose mkdirs failed;
show a toast (new string, en and it).
- Normalize entryFile so "./" and "a/../b" give the same keys as the
list; covered in EditorModelTest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Holds the form in memory only, generates passwords with the stored
generator options, decodes QR images and saves off the main thread:
nothing is written when the target would replace another entry or when
encryption fails, the file is written through a temporary file, and a
renamed or moved entry takes its autofill matches and recently-used time
along.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A dialog with breadcrumbs, subfolder rows and New folder replaces the
legacy folder picker activity for the list's move action; the editor will
share it. New folder reuses the list's name dialog and checks. A second
tap on Select no longer moves twice.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Pure functions for the Compose editor: the form and the pass file it
writes, validation, the target file, the overwrite check, an atomic
write, OTP URI building and the random generator's options. The folder
picker lists subfolders with the list's hidden filter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The Compose entry view replaces DecryptActivity, its layouts, menu and
field adapter, and upstream's unused ViewPasswordScreen. BasePGPActivity
keeps what the editor and autofill still need.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Ignore a submit while no prompt is showing, so OK plus IME Done cannot start
two decrypts. Key the passphrase dialog on the retry count so each attempt
gets a fresh field and shows the wrong password error. Note the process
death gap around key import and the editor. Record the TotpModule,
text selection and file IO decisions in the plan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
The list navigates to EntryRoute and shortcuts start on it, replacing the
legacy decrypt screen. FLAG_SECURE is on while an entry is composed and
off on the list; the route is checked with isFileInRepo again before
decrypting. Saving in the editor returns to the list. Password and one-time
code copies start the clipboard clear timer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|