CodeAssist 3.11.0
🚀 CodeAssist 3.11.0
Git runs on the phone now, with GitHub sign-in, branches, history and diffs. Plugins can finally draw a full screen instead of a narrow drawer, and there is a guide for writing one.
VERSION CONTROL
- Git works on the device. A project written and built here had nowhere to go: no history, no branches, nothing to push, and the source-control panel in the rail just said "Coming Soon". It is a real panel now.
- Stage and unstage files, commit, pull and push, with the ahead and behind counts printed on the buttons themselves.
- Branches, history, diffs and stashes each open as their own screen, because a branch list does not fit in a sidebar on a phone.
- Sign in to GitHub from the app: it opens the normal GitHub device flow (a code you confirm in the browser), or you can paste an access token. Signed in, you can browse and clone your repositories.
- Clone a repository from the project picker, so you do not need an open project to get one.
- The panel is worded rather than drawn. Groups of files say what they are ("Ready to commit", "Edited but not included yet"), every icon has a tooltip, and committing is one button whose label follows a "Push after committing" checkbox.
- Accounts live outside any project and every secret is encrypted on disk, so exporting or sharing a project never carries your token.
- It is a plugin like the others: one toggle in Settings ▸ Plugins removes the panel and the Git engine together.
PLUGINS
- A plugin can open a full screen now. Screens registered by a plugin were never rendered, so a plugin could only draw inside its own dock, which on a phone is a drawer about 300dp wide. Enough for a list of files and nothing else.
- Back from a plugin screen returns where you opened it from, the editor or the picker, instead of one fixed place.
- Panels and screens can open an external link and reach their own detail views, so a plugin no longer needs the host to do it.
- The shell's placeholder source-control panel is gone. That rail slot belongs to a plugin, and a plugin claiming it inherits the rail position, the remembered open-panel choice and the phone bottom-nav entry.
- New guide: writing plugins. The plugin model was documented as built but there was nothing task-oriented.
docs/writing-plugins.mdwalks it end to end, from a first plugin to extension points, services, settings pages, actions and the Compose UI surface, then reads the Git and AI Agent plugins as worked examples.
KOTLIN EDITOR
coroutineContext[CoroutineName]?.offered no members at all. A generic operator (a[i],a(i)) now infers its own type parameters from what you pass it, not just from the receiver, and a class named as a value resolves to its companion the way Kotlin does.- Enum members resolve.
Color.RED.namereported "Unresolved reference" on your own enums, and a builtin enum decoded with no constants at all, soAnnotationTarget.CLASSread as unresolved andAnnotationTarget.completed empty. import kotlin.time.Duration.Companion.offered nothing. An explicitly spelledCompanionnow completes its members.items(list) { }insideLazyColumnoffers the import that fixes it. The lightbulb was only reachable with the caret on the argument rather than on the call, a named argument no in-scope overload declares reported nothing, and a nested call offered an import that fixed nothing. The same call also stopped reporting a contradictory second error on top of the first.- A value of function type is coloured the same wherever it appears.
f()andf.invoke()in one body used to come out in two different colours.
ANDROID
- Another module's or an AAR's
Rresolves, both in the editor and in the build. With non-transitive R classes you have to name the package that owns a resource (com.example.base.R.string.x), and that form resolved nowhere below the app: the editor called it unresolved and:feature:compileJavafailed with "com.example.base cannot be resolved". A dependency'sBuildConfigand view bindings come into Kotlin files with it.
DEPENDENCIES
- Editing a dependency's version sticks. Changing a version, closing the project and reopening showed the old one again. Version edits, exclusions and newly attached dependencies are all written to disk when you make them.
RUN
- Your own exception type is caught again. An exception class of yours that extends a real one (
class MyException : Throwable(...)) escaped thetrythat declared it whenever real code threw it back, sotry { suspendCoroutine { it.resumeWithException(MyException()) } } catch (e: MyException)printed nothing and died uncaught. The same shape coversOptional.orElseThrowand a resumed suspend function.
PROJECTS
- One Import project entry on the picker, not two. The top-bar download action and the "Import project" card were not the same door: the top-bar one could only take a shared package. The card is the single entry and covers both a folder and a package.
Full changelog: https://github.com/tyron12233/CodeAssist/releases/tag/v3.11.0