|  | @@ -44,6 +44,12 @@ class ZefyrController extends ChangeNotifier {
 | 
	
		
			
			| 44 | 44 |    /// Source of the last text or selection change.
 | 
	
		
			
			| 45 | 45 |    ChangeSource get lastChangeSource => _lastChangeSource;
 | 
	
		
			
			| 46 | 46 |  
 | 
	
		
			
			|  | 47 | +  /// Store any styles attribute that got toggled by the tap of a button
 | 
	
		
			
			|  | 48 | +  /// and that has not been applied yet.
 | 
	
		
			
			|  | 49 | +  /// It gets reseted after each format action within the [document].
 | 
	
		
			
			|  | 50 | +  NotusStyle get toggledStyles => _toggledStyles;
 | 
	
		
			
			|  | 51 | +  NotusStyle _toggledStyles = new NotusStyle();
 | 
	
		
			
			|  | 52 | +
 | 
	
		
			
			| 47 | 53 |    /// Updates selection with specified [value].
 | 
	
		
			
			| 48 | 54 |    ///
 | 
	
		
			
			| 49 | 55 |    /// [value] and [source] cannot be `null`.
 | 
	
	
		
			
			|  | @@ -104,6 +110,9 @@ class ZefyrController extends ChangeNotifier {
 | 
	
		
			
			| 104 | 110 |    /// Resulting change is registered as produced by user action, e.g.
 | 
	
		
			
			| 105 | 111 |    /// using [ChangeSource.local].
 | 
	
		
			
			| 106 | 112 |    ///
 | 
	
		
			
			|  | 113 | +  /// It also applies the toggledStyle if needed. And then it resets it
 | 
	
		
			
			|  | 114 | +  /// in any cases as we don't want to keep it except on inserts.
 | 
	
		
			
			|  | 115 | +  ///
 | 
	
		
			
			| 107 | 116 |    /// Optionally updates selection if provided.
 | 
	
		
			
			| 108 | 117 |    void replaceText(int index, int length, String text,
 | 
	
		
			
			| 109 | 118 |        {TextSelection selection}) {
 | 
	
	
		
			
			|  | @@ -111,8 +120,23 @@ class ZefyrController extends ChangeNotifier {
 | 
	
		
			
			| 111 | 120 |  
 | 
	
		
			
			| 112 | 121 |      if (length > 0 || text.isNotEmpty) {
 | 
	
		
			
			| 113 | 122 |        delta = document.replace(index, length, text);
 | 
	
		
			
			|  | 123 | +      // If the delta is a classical insert operation and we have toggled
 | 
	
		
			
			|  | 124 | +      // some style, then we apply it to our document.
 | 
	
		
			
			|  | 125 | +      if (delta != null &&
 | 
	
		
			
			|  | 126 | +          toggledStyles.isNotEmpty &&
 | 
	
		
			
			|  | 127 | +          delta.length == 2 &&
 | 
	
		
			
			|  | 128 | +          delta[1].isInsert) {
 | 
	
		
			
			|  | 129 | +        // Apply it.
 | 
	
		
			
			|  | 130 | +        Delta retainDelta = new Delta()
 | 
	
		
			
			|  | 131 | +          ..retain(index)
 | 
	
		
			
			|  | 132 | +          ..retain(1, toggledStyles.toJson());
 | 
	
		
			
			|  | 133 | +        document.compose(retainDelta, ChangeSource.local);
 | 
	
		
			
			|  | 134 | +      }
 | 
	
		
			
			| 114 | 135 |      }
 | 
	
		
			
			| 115 | 136 |  
 | 
	
		
			
			|  | 137 | +    // Always reset it after any user action, even if it has not been applied.
 | 
	
		
			
			|  | 138 | +    _toggledStyles = new NotusStyle();
 | 
	
		
			
			|  | 139 | +
 | 
	
		
			
			| 116 | 140 |      if (selection != null) {
 | 
	
		
			
			| 117 | 141 |        if (delta == null) {
 | 
	
		
			
			| 118 | 142 |          _updateSelectionSilent(selection, source: ChangeSource.local);
 | 
	
	
		
			
			|  | @@ -140,6 +164,14 @@ class ZefyrController extends ChangeNotifier {
 | 
	
		
			
			| 140 | 164 |    void formatText(int index, int length, NotusAttribute attribute) {
 | 
	
		
			
			| 141 | 165 |      final change = document.format(index, length, attribute);
 | 
	
		
			
			| 142 | 166 |      _lastChangeSource = ChangeSource.local;
 | 
	
		
			
			|  | 167 | +
 | 
	
		
			
			|  | 168 | +    if (length == 0 &&
 | 
	
		
			
			|  | 169 | +        (attribute.key == NotusAttribute.bold.key ||
 | 
	
		
			
			|  | 170 | +            attribute.key == NotusAttribute.italic.key)) {
 | 
	
		
			
			|  | 171 | +      // Add the attribute to our toggledStyle. It will be used later upon insertion.
 | 
	
		
			
			|  | 172 | +      _toggledStyles = toggledStyles.put(attribute);
 | 
	
		
			
			|  | 173 | +    }
 | 
	
		
			
			|  | 174 | +
 | 
	
		
			
			| 143 | 175 |      // Transform selection against the composed change and give priority to
 | 
	
		
			
			| 144 | 176 |      // the change. This is needed in cases when format operation actually
 | 
	
		
			
			| 145 | 177 |      // inserts data into the document (e.g. embeds).
 | 
	
	
		
			
			|  | @@ -160,10 +192,18 @@ class ZefyrController extends ChangeNotifier {
 | 
	
		
			
			| 160 | 192 |      formatText(index, length, attribute);
 | 
	
		
			
			| 161 | 193 |    }
 | 
	
		
			
			| 162 | 194 |  
 | 
	
		
			
			|  | 195 | +  /// Returns style of specified text range.
 | 
	
		
			
			|  | 196 | +  ///
 | 
	
		
			
			|  | 197 | +  /// If nothing is selected but we've toggled an attribute,
 | 
	
		
			
			|  | 198 | +  ///  we also merge those in our style before returning.
 | 
	
		
			
			| 163 | 199 |    NotusStyle getSelectionStyle() {
 | 
	
		
			
			| 164 | 200 |      int start = _selection.start;
 | 
	
		
			
			| 165 | 201 |      int length = _selection.end - start;
 | 
	
		
			
			| 166 |  | -    return _document.collectStyle(start, length);
 | 
	
		
			
			|  | 202 | +    var lineStyle = _document.collectStyle(start, length);
 | 
	
		
			
			|  | 203 | +
 | 
	
		
			
			|  | 204 | +    lineStyle = lineStyle.mergeAll(toggledStyles);
 | 
	
		
			
			|  | 205 | +
 | 
	
		
			
			|  | 206 | +    return lineStyle;
 | 
	
		
			
			| 167 | 207 |    }
 | 
	
		
			
			| 168 | 208 |  
 | 
	
		
			
			| 169 | 209 |    TextEditingValue get plainTextEditingValue {
 |