Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
233841c
WIP: Floating editor sheet demo (#2803)
matthew-carroll Oct 8, 2025
13b5386
WIP: Figuring out the desired public widget APIs for simple vs custom…
matthew-carroll Oct 14, 2025
b31c092
Bottom sheet now clips the editor sheet, shadow is configurable
matthew-carroll Oct 14, 2025
d7fc2ab
Brought back commented out overlay portal that shows the keyboard mou…
matthew-carroll Oct 14, 2025
0ac8c58
Fix a bad sheet dragging state, also add print statements to see why …
matthew-carroll Oct 15, 2025
df3bf3a
Make top margin and preview height configurable through the floating …
matthew-carroll Oct 15, 2025
e8f2030
Add collapsedMinimumHeight to sheet style, remove explicit top MediaQ…
matthew-carroll Oct 15, 2025
8e16ce6
Add debug print for tapping editor for focus
matthew-carroll Oct 16, 2025
32c3318
WIP: Working on the floating editor toolbar and the keyboard panels (…
matthew-carroll Oct 20, 2025
c36282d
Merge branch 'main' into 2803_floating-chat-editor-proof-of-concept
matthew-carroll Feb 11, 2026
a7557a0
Removed some print statements left over from the merge that wouldn't …
matthew-carroll Feb 12, 2026
ba226b7
WIP: Iterating on floating editor with ClickUp
matthew-carroll Feb 16, 2026
ddd5a40
WIP: Floating editor preview mode (need to merge in recent addition o…
matthew-carroll Feb 26, 2026
e4ebeef
Merge branch 'main' into 2803_floating-chat-editor-proof-of-concept
matthew-carroll Feb 26, 2026
6cc51c7
WIP: Finishing preview mode and working on positioning editor above p…
matthew-carroll Mar 3, 2026
f07dd4a
Merge branch 'main' into 2803_floating-chat-editor-proof-of-concept
matthew-carroll Mar 20, 2026
6735aa8
WIP: Working on positioning editor sheet above panels
matthew-carroll Mar 27, 2026
6854de2
Merge branch 'main' into 2803_floating-chat-editor-proof-of-concept
matthew-carroll Mar 27, 2026
94bdd55
Reworked keyboard panel management so that it stays until the keyboar…
matthew-carroll Apr 2, 2026
bdef2e8
Fix selection blowup when in preview mode
matthew-carroll Apr 13, 2026
8653653
Make preview plugin component adjusters configurable so apps can deci…
matthew-carroll Apr 15, 2026
51d473a
Fix: Detach old plugins and attach new plugins when plugin set change…
matthew-carroll Apr 21, 2026
3232e0c
Adjust scaffold widget API
matthew-carroll Apr 25, 2026
37e8ac4
Don't open keyboard when closing a panel, remove bottom padding from …
matthew-carroll Apr 27, 2026
2f5185a
Add auto-focus to chat editor, add concept of 'unknown bottom sheet h…
matthew-carroll May 6, 2026
3196f78
Fix nuanced SuperIme issue where Flutter reports IME closure to us, b…
matthew-carroll May 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
4 changes: 4 additions & 0 deletions super_editor/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# FVM
.fvm
.fvmrc

# Golden failures
**/failures/

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Example - Chat - Bottom Mounted Sheet" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="filePath" value="$PROJECT_DIR$/example_chat/lib/main_bottom_mounted_sheet.dart" />
<method v="2" />
</configuration>
</component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Example - Chat - Floating Editor (Configured)" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="filePath" value="$PROJECT_DIR$/example_chat/lib/main_configured_floating_chat_page.dart" />
<method v="2" />
</configuration>
</component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Example - Chat - Floating Editor (Default)" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="filePath" value="$PROJECT_DIR$/example_chat/lib/main_default_floating_chat_page.dart" />
<method v="2" />
</configuration>
</component>
6 changes: 0 additions & 6 deletions super_editor/.run/Example - Chat.run.xml

This file was deleted.

2 changes: 0 additions & 2 deletions super_editor/example/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,5 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>13.0</string>
</dict>
</plist>
13 changes: 0 additions & 13 deletions super_editor/example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,26 @@ PODS:
- Flutter (1.0.0)
- flutter_keyboard_visibility (0.0.1):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- super_keyboard (0.0.1):
- Flutter
- url_launcher_ios (0.0.1):
- Flutter

DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- super_keyboard (from `.symlinks/plugins/super_keyboard/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)

EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_keyboard_visibility:
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
super_keyboard:
:path: ".symlinks/plugins/super_keyboard/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"

SPEC CHECKSUMS:
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
super_keyboard: 016de6ce9ab826f9a0b185608209d6a3b556d577
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d

PODFILE CHECKSUM: 0dbd5a87e0ace00c9610d2037ac22083a01f861d

Expand Down
22 changes: 22 additions & 0 deletions super_editor/example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand Down Expand Up @@ -47,13 +48,15 @@
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DD955D05ACC2748E65FB82B9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
8D64A633041DB8E7A6AB8AA5 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -64,6 +67,7 @@
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
Expand Down Expand Up @@ -128,6 +132,9 @@

/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
packageProductDependencies = (
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
);
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
Expand All @@ -153,6 +160,9 @@

/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
packageReferences = (
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
);
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1510;
Expand Down Expand Up @@ -549,6 +559,18 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
isa = XCSwiftPackageProductDependency;
productName = FlutterGeneratedPluginSwiftPackage;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Prepare Flutter Framework Script"
scriptText = "/bin/sh &quot;$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh&quot; prepare&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
Expand Down
9 changes: 6 additions & 3 deletions super_editor/example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import UIKit
import Flutter
import UIKit

@main
@objc class AppDelegate: FlutterAppDelegate {
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}
}
29 changes: 25 additions & 4 deletions super_editor/example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
Expand All @@ -24,6 +26,29 @@
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
Expand All @@ -43,9 +68,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import 'package:flutter/material.dart';

/// A simulated chat conversation thread, which is simulated as a bottom-aligned
/// list of tiles.
class FakeChatThread extends StatelessWidget {
const FakeChatThread({super.key, this.scrollPadding = EdgeInsets.zero});

final EdgeInsets scrollPadding;

@override
Widget build(BuildContext context) {
return ListView.builder(
padding: scrollPadding,
reverse: true,
// ^ The list starts at the bottom and grows upward. This is how
// we should layout chat conversations where the most recent
// message appears at the bottom, and you want to retain the
// scroll offset near the newest messages, not the oldest.
itemBuilder: (context, index) {
if (index == 8) {
// Arbitrarily placed text field to test moving focus between a non-editor
// and the editor.
return TextField(
decoration: InputDecoration(
hintText: "Content text field...",
),
);
}

return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Material(
color: Colors.white.withValues(alpha: 0.5),
child: ListTile(
title: Text("This is item $index"),
subtitle: Text("This is a subtitle for $index"),
),
),
);
},
);
}
}
Loading
Loading