@@ -11,7 +11,11 @@ import dev.jcode.editor.languagePackCompletionItems
1111import dev.jcode.design.LocalEditorSaveActions
1212import dev.jcode.design.JCodeIcon
1313import dev.jcode.design.JcTooltip
14+ import dev.jcode.design.EditorDragSetting
15+ import dev.jcode.design.LocalEditorDragMovesCursor
16+ import dev.jcode.design.LocalRestoreSession
1417import dev.jcode.design.LocalTabCloseButtonSetting
18+ import dev.jcode.design.RestoreSessionSetting
1519import dev.jcode.design.TabCloseButtonSetting
1620import dev.jcode.editor.SyntaxHighlighter
1721import dev.jcode.editor.TokenPalette
@@ -200,7 +204,13 @@ import dev.jcode.feature.sdkmanager.SdkManagerFeature
200204import dev.jcode.feature.settings.SettingsFeature
201205import dev.jcode.workbench.dialog.NewItemDialog
202206import dev.jcode.workbench.dialog.OpenFolderTypeDialog
207+ import dev.jcode.feature.marketplace.ExtensionActivation
208+ import dev.jcode.workbench.marketplace.ExtensionActivationSetting
209+ import dev.jcode.workbench.ExtensionWebViewPage
210+ import dev.jcode.workbench.marketplace.DbManagerPanel
203211import dev.jcode.workbench.marketplace.ExtensionDetailPage
212+ import dev.jcode.workbench.marketplace.ExtensionPermissionsPage
213+ import dev.jcode.workbench.marketplace.LocalExtensionActivation
204214import dev.jcode.workbench.marketplace.ExtensionsPanel
205215import dev.jcode.workbench.LocalTerminalTapConfig
206216import dev.jcode.workbench.RightPanelTab
@@ -253,6 +263,16 @@ fun JCodeApp(
253263 val runConfigVersion by viewModel.runConfigVersion.collectAsStateWithLifecycle()
254264 val autoSetupProgress by viewModel.autoSetupProgress.collectAsStateWithLifecycle(initialValue = DistroWizardProgress .Idle )
255265 val installedExtensions by viewModel.installedExtensions.collectAsStateWithLifecycle()
266+ // Extensions whose contributions are active (not set to Manual) — used for all language-pack lookups
267+ // so the per-extension activation mode actually gates highlighting/completions/formatting.
268+ val activeLanguageExtensions by viewModel.activeLanguageExtensions.collectAsStateWithLifecycle()
269+ val extensionActivations by viewModel.extensionActivations.collectAsStateWithLifecycle()
270+ val extensionActivationSetting = remember(extensionActivations) {
271+ ExtensionActivationSetting (
272+ modeFor = { id -> extensionActivations[id] ? : ExtensionActivation .Default },
273+ onChange = viewModel::setExtensionActivation,
274+ )
275+ }
256276 val marketplaceEntries by viewModel.marketplaceEntries.collectAsStateWithLifecycle()
257277 val marketplaceBusy by viewModel.marketplaceBusy.collectAsStateWithLifecycle()
258278 val themeMode by viewModel.themeMode.collectAsStateWithLifecycle()
@@ -267,6 +287,23 @@ fun JCodeApp(
267287 val tabCloseSetting = remember(hideTabCloseButton) {
268288 TabCloseButtonSetting (hideTabCloseButton, viewModel::setHideTabCloseButton)
269289 }
290+ val editorDragMovesCursor by viewModel.editorDragMovesCursor.collectAsStateWithLifecycle()
291+ val cursorDragVerticalLevel by viewModel.editorCursorDragVerticalLevel.collectAsStateWithLifecycle()
292+ val cursorDragHorizontalLevel by viewModel.editorCursorDragHorizontalLevel.collectAsStateWithLifecycle()
293+ val editorDragSetting = remember(editorDragMovesCursor, cursorDragVerticalLevel, cursorDragHorizontalLevel) {
294+ EditorDragSetting (
295+ enabled = editorDragMovesCursor,
296+ onChange = viewModel::setEditorDragMovesCursor,
297+ verticalLevel = cursorDragVerticalLevel,
298+ horizontalLevel = cursorDragHorizontalLevel,
299+ onVerticalLevelChange = viewModel::setEditorCursorDragVerticalLevel,
300+ onHorizontalLevelChange = viewModel::setEditorCursorDragHorizontalLevel,
301+ )
302+ }
303+ val restoreLastSession by viewModel.restoreLastSession.collectAsStateWithLifecycle()
304+ val restoreSessionSetting = remember(restoreLastSession) {
305+ RestoreSessionSetting (restoreLastSession, viewModel::setRestoreLastSession)
306+ }
270307 val editorSaveActions = remember(viewModel) {
271308 EditorSaveActions (
272309 onUndo = viewModel::undoActiveTab,
@@ -278,8 +315,8 @@ fun JCodeApp(
278315 }
279316 // Completion items for the focused file, resolved from its installed language pack (if any).
280317 val activeFileName = editorGroup.activeTab?.filePath?.name
281- val activeLanguagePack = remember(activeFileName, installedExtensions ) {
282- activeFileName?.let { n -> installedExtensions .firstNotNullOfOrNull { it.languageFor(n) } }
318+ val activeLanguagePack = remember(activeFileName, activeLanguageExtensions ) {
319+ activeFileName?.let { n -> activeLanguageExtensions .firstNotNullOfOrNull { it.languageFor(n) } }
283320 }
284321 val completionSource = remember(activeLanguagePack) {
285322 { prefix: String -> languagePackCompletionItems(activeLanguagePack, prefix) }
@@ -355,6 +392,9 @@ fun JCodeApp(
355392 CompositionLocalProvider (
356393 LocalTerminalTapConfig provides terminalTapConfig,
357394 LocalTabCloseButtonSetting provides tabCloseSetting,
395+ LocalEditorDragMovesCursor provides editorDragSetting,
396+ LocalRestoreSession provides restoreSessionSetting,
397+ LocalExtensionActivation provides extensionActivationSetting,
358398 LocalEditorSaveActions provides editorSaveActions,
359399 LocalCompletionSource provides completionSource,
360400 LocalEnvironmentManager provides environmentManagerActions,
@@ -431,6 +471,9 @@ fun JCodeApp(
431471 onInstallExtension = viewModel::installExtension,
432472 onUninstallExtension = viewModel::uninstallExtension,
433473 onOpenExtensionDetail = viewModel::openExtensionDetailPage,
474+ onOpenExtensionPermissions = viewModel::openExtensionPermissionsPage,
475+ onOpenExtensionApp = viewModel::openExtensionAppPage,
476+ onExtensionExec = viewModel::runtimeExecJson,
434477 ),
435478 onOpenSettingsPage = viewModel::openSettingsPage,
436479 terminalDoubleTapToFocus = terminalDoubleTapToFocus,
@@ -569,11 +612,15 @@ private fun JCodeShell(
569612 ThemeMode .Light -> false
570613 ThemeMode .System -> systemDark
571614 }
615+ // Only extensions not set to Manual contribute language features (highlighting/completions/format).
616+ val activeLanguageExtensions = installedExtensions.filter {
617+ LocalExtensionActivation .current.modeFor(it.id) != ExtensionActivation .Manual
618+ }
572619 val highlightTab = editorGroup.activeTab
573- LaunchedEffect (highlightTab?.id, installedExtensions , editorDark) {
620+ LaunchedEffect (highlightTab?.id, activeLanguageExtensions , editorDark) {
574621 val state = highlightTab?.editorState ? : return @LaunchedEffect
575622 val fileName = highlightTab.filePath.name
576- val lang = installedExtensions .firstNotNullOfOrNull { ext -> ext.languageFor(fileName) }
623+ val lang = activeLanguageExtensions .firstNotNullOfOrNull { ext -> ext.languageFor(fileName) }
577624 val palette = if (editorDark) TokenPalette .DARK else TokenPalette .LIGHT
578625 state.snapshot.collectLatest { snap ->
579626 val spans = withContext(Dispatchers .Default ) {
@@ -1142,7 +1189,7 @@ private fun JCodeShell(
11421189 },
11431190 languageActionsEnabled = run {
11441191 val name = editorGroup.activeTab?.filePath?.name
1145- name != null && installedExtensions .any { it.languageFor(name) != null }
1192+ name != null && activeLanguageExtensions .any { it.languageFor(name) != null }
11461193 },
11471194 onEditorLanguageAction = { action, word ->
11481195 if (action == EditorLanguageAction .FormatDocument ) {
@@ -1258,10 +1305,28 @@ private fun JCodeShell(
12581305 busy = marketplaceBusy,
12591306 onInstall = managerActions.onInstallExtension,
12601307 onUninstall = managerActions.onUninstallExtension,
1308+ onOpenApp = managerActions.onOpenExtensionApp,
12611309 modifier = Modifier .fillMaxSize(),
12621310 )
12631311 }
12641312 }
1313+ EditorPageKind .ExtensionPermissions -> ExtensionPermissionsPage (
1314+ installed = installedExtensions,
1315+ modifier = Modifier .fillMaxSize(),
1316+ )
1317+ EditorPageKind .ExtensionApp -> {
1318+ val appId = tab.id.substringAfter(MainViewModel .EXT_APP_PREFIX )
1319+ installedExtensions.firstOrNull { it.id == appId }?.let { ext ->
1320+ // Key by id so each extension app gets its own WebView (no reuse across tabs).
1321+ key(ext.id) {
1322+ ExtensionWebViewPage (
1323+ extension = ext,
1324+ onExec = managerActions.onExtensionExec,
1325+ modifier = Modifier .fillMaxSize(),
1326+ )
1327+ }
1328+ }
1329+ }
12651330 EditorPageKind .None -> Unit
12661331 }
12671332 },
@@ -1683,6 +1748,7 @@ private fun WorkspacePanel(
16831748 busy = marketplaceBusy,
16841749 onRefreshMarketplace = managerActions.onRefreshMarketplace,
16851750 onOpenDetail = managerActions.onOpenExtensionDetail,
1751+ onOpenPermissions = managerActions.onOpenExtensionPermissions,
16861752 modifier = Modifier .fillMaxSize(),
16871753 )
16881754
@@ -1702,6 +1768,12 @@ private fun WorkspacePanel(
17021768 modifier = Modifier .fillMaxSize(),
17031769 )
17041770
1771+ WorkbenchTool .DbManager -> DbManagerPanel (
1772+ installed = installedExtensions,
1773+ onOpenApp = managerActions.onOpenExtensionApp,
1774+ modifier = Modifier .fillMaxSize(),
1775+ )
1776+
17051777 // Settings opens as an in-editor page (see EditorWorkspace); it is never the
17061778 // selected side-panel tool, so this branch renders nothing.
17071779 WorkbenchTool .Settings -> Unit
0 commit comments