mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 04:04:18 +00:00 
			
		
		
		
	Add references support
This commit is contained in:
		
							
								
								
									
										52
									
								
								lib/helpers/virtual_directory_helper.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								lib/helpers/virtual_directory_helper.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/models/api_request.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Virtual directory helper
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// @author Pierre Hubert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum VirtualDirectoryType { USER, GROUP, NONE }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VirtualDirectoryResult {
 | 
				
			||||||
 | 
					  final VirtualDirectoryType type;
 | 
				
			||||||
 | 
					  final int id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const VirtualDirectoryResult({
 | 
				
			||||||
 | 
					    @required this.type,
 | 
				
			||||||
 | 
					    this.id,
 | 
				
			||||||
 | 
					  }) : assert(type != null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VirtualDirectoryHelper {
 | 
				
			||||||
 | 
					  /// Find a virtual directory
 | 
				
			||||||
 | 
					  Future<VirtualDirectoryResult> find(String directory) async {
 | 
				
			||||||
 | 
					    final response = await APIRequest(
 | 
				
			||||||
 | 
					        uri: "virtualDirectory/find",
 | 
				
			||||||
 | 
					        needLogin: true,
 | 
				
			||||||
 | 
					        args: {"directory": directory}).exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (response.code) {
 | 
				
			||||||
 | 
					      case 404:
 | 
				
			||||||
 | 
					        return VirtualDirectoryResult(type: VirtualDirectoryType.NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case 200:
 | 
				
			||||||
 | 
					        final id = response.getObject()["id"];
 | 
				
			||||||
 | 
					        final kind = response.getObject()["kind"];
 | 
				
			||||||
 | 
					        switch (kind) {
 | 
				
			||||||
 | 
					          case "user":
 | 
				
			||||||
 | 
					            return VirtualDirectoryResult(
 | 
				
			||||||
 | 
					                type: VirtualDirectoryType.USER, id: id);
 | 
				
			||||||
 | 
					          case "group":
 | 
				
			||||||
 | 
					            return VirtualDirectoryResult(
 | 
				
			||||||
 | 
					                type: VirtualDirectoryType.GROUP, id: id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          default:
 | 
				
			||||||
 | 
					            throw Exception("Unsupported virtual directory kind: $kind");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        throw new Exception("Could not get virtual directory!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -22,10 +22,6 @@ import 'login_route.dart';
 | 
				
			|||||||
class HomeRoute extends StatefulWidget {
 | 
					class HomeRoute extends StatefulWidget {
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  State<StatefulWidget> createState() => _HomeRouteState();
 | 
					  State<StatefulWidget> createState() => _HomeRouteState();
 | 
				
			||||||
 | 
					 | 
				
			||||||
  /// Get current instance of Home controller
 | 
					 | 
				
			||||||
  static HomeController of(BuildContext context) =>
 | 
					 | 
				
			||||||
      context.findAncestorStateOfType<HomeController>();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CurrPage {
 | 
					class CurrPage {
 | 
				
			||||||
@@ -45,6 +41,11 @@ class CurrPage {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Public interface of home controller
 | 
					/// Public interface of home controller
 | 
				
			||||||
abstract class HomeController extends State<HomeRoute> {
 | 
					abstract class HomeController extends State<HomeRoute> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Get current instance of Home controller
 | 
				
			||||||
 | 
					  static HomeController of(BuildContext context) =>
 | 
				
			||||||
 | 
					      context.findAncestorStateOfType<HomeController>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Open a specific group page specified by its [groupID]
 | 
					  /// Open a specific group page specified by its [groupID]
 | 
				
			||||||
  void openGroup(int groupID);
 | 
					  void openGroup(int groupID);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,7 +67,7 @@ class _GroupsListScreenState extends SafeState<GroupsListScreen> {
 | 
				
			|||||||
                            trailing: IconButton(
 | 
					                            trailing: IconButton(
 | 
				
			||||||
                                icon: Icon(Icons.delete),
 | 
					                                icon: Icon(Icons.delete),
 | 
				
			||||||
                                onPressed: () => _deleteGroup(g)),
 | 
					                                onPressed: () => _deleteGroup(g)),
 | 
				
			||||||
                            onTap: () => HomeRoute.of(context).openGroup(g.id),
 | 
					                            onTap: () => HomeController.of(context).openGroup(g.id),
 | 
				
			||||||
                          ))
 | 
					                          ))
 | 
				
			||||||
                      .toList(),
 | 
					                      .toList(),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
import 'package:comunic/utils/bbcode_parser.dart';
 | 
					import 'package:comunic/utils/bbcode_parser.dart';
 | 
				
			||||||
import 'package:comunic/utils/input_utils.dart';
 | 
					import 'package:comunic/utils/input_utils.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/navigation_utils.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:flutter_emoji/flutter_emoji.dart';
 | 
					import 'package:flutter_emoji/flutter_emoji.dart';
 | 
				
			||||||
import 'package:url_launcher/url_launcher.dart';
 | 
					import 'package:url_launcher/url_launcher.dart';
 | 
				
			||||||
@@ -32,17 +33,17 @@ class TextWidget extends StatelessWidget {
 | 
				
			|||||||
    if (this.parseBBcode)
 | 
					    if (this.parseBBcode)
 | 
				
			||||||
      return BBCodeParsedWidget(
 | 
					      return BBCodeParsedWidget(
 | 
				
			||||||
        text: content,
 | 
					        text: content,
 | 
				
			||||||
        parseCallback: (style, text) => _parseLinks(text, style),
 | 
					        parseCallback: (style, text) => _parseLinks(context, text, style),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Just parse link
 | 
					    // Just parse link
 | 
				
			||||||
    return RichText(
 | 
					    return RichText(
 | 
				
			||||||
      text: TextSpan(children: _parseLinks(content, style)),
 | 
					      text: TextSpan(children: _parseLinks(context, content, style)),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Sub parse function
 | 
					  /// Sub parse function
 | 
				
			||||||
  List<InlineSpan> _parseLinks(String text, TextStyle style) {
 | 
					  List<InlineSpan> _parseLinks(BuildContext context, String text, TextStyle style) {
 | 
				
			||||||
    var buff = StringBuffer();
 | 
					    var buff = StringBuffer();
 | 
				
			||||||
    final list = new List<InlineSpan>();
 | 
					    final list = new List<InlineSpan>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -78,6 +79,25 @@ class TextWidget extends StatelessWidget {
 | 
				
			|||||||
        buff.write(" ");
 | 
					        buff.write(" ");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Check if it is a user reference
 | 
				
			||||||
 | 
					      else if(validateUserReference(word)) {
 | 
				
			||||||
 | 
					        changeWordType();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        list.add(
 | 
				
			||||||
 | 
					          WidgetSpan(
 | 
				
			||||||
 | 
					            child: InkWell(
 | 
				
			||||||
 | 
					              child: Text(
 | 
				
			||||||
 | 
					                word,
 | 
				
			||||||
 | 
					                style: style.copyWith(color: Colors.blueAccent),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              onTap: () => openVirtualDirectory(context, word),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        buff.write(" ");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Simple word
 | 
					      // Simple word
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
        buff.write(word);
 | 
					        buff.write(word);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,3 +27,7 @@ bool validateUrl(String url) {
 | 
				
			|||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Validate user reference
 | 
				
			||||||
 | 
					bool validateUserReference(String ref) =>
 | 
				
			||||||
 | 
					    RegExp(r'@[a-zA-Z0-9]+').hasMatch(ref);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,9 @@
 | 
				
			|||||||
 | 
					import 'package:comunic/helpers/virtual_directory_helper.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/ui/routes/home_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/routes/single_post_route.dart';
 | 
					import 'package:comunic/ui/routes/single_post_route.dart';
 | 
				
			||||||
import 'package:comunic/ui/routes/user_page_route.dart';
 | 
					import 'package:comunic/ui/routes/user_page_route.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/intl_utils.dart';
 | 
				
			||||||
 | 
					import 'package:comunic/utils/ui_utils.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:meta/meta.dart';
 | 
					import 'package:meta/meta.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,3 +30,41 @@ void openPostFullScreen(int postID, BuildContext context) {
 | 
				
			|||||||
  Navigator.of(context)
 | 
					  Navigator.of(context)
 | 
				
			||||||
      .push(MaterialPageRoute(builder: (c) => SinglePostRoute(postID: postID)));
 | 
					      .push(MaterialPageRoute(builder: (c) => SinglePostRoute(postID: postID)));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Open a virtual directory
 | 
				
			||||||
 | 
					void openVirtualDirectory(BuildContext context, String directory) async {
 | 
				
			||||||
 | 
					  if (directory.startsWith("@")) directory = directory.substring(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    final result = await VirtualDirectoryHelper().find(directory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (result.type) {
 | 
				
			||||||
 | 
					      case VirtualDirectoryType.USER:
 | 
				
			||||||
 | 
					        openUserPage(context: context, userID: result.id);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case VirtualDirectoryType.GROUP:
 | 
				
			||||||
 | 
					        HomeController.of(context).openGroup(result.id);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      case VirtualDirectoryType.NONE:
 | 
				
			||||||
 | 
					        await showDialog(
 | 
				
			||||||
 | 
					            context: context,
 | 
				
			||||||
 | 
					            builder: (c) => AlertDialog(
 | 
				
			||||||
 | 
					                  title: Text(tr("Error")),
 | 
				
			||||||
 | 
					                  content: Text(tr("Could not find related resource!")),
 | 
				
			||||||
 | 
					                  actions: <Widget>[
 | 
				
			||||||
 | 
					                    MaterialButton(
 | 
				
			||||||
 | 
					                      child: Text(tr("OK")),
 | 
				
			||||||
 | 
					                      onPressed: () => Navigator.of(c).pop(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ));
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  } catch (e, stack) {
 | 
				
			||||||
 | 
					    print(e);
 | 
				
			||||||
 | 
					    print(stack);
 | 
				
			||||||
 | 
					    showSimpleSnack(context, tr("Could not search virtual directory!"));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user