| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  | import 'dart:convert'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import 'package:appflowy/core/config/kv.dart'; | 
					
						
							|  |  |  | import 'package:appflowy/core/config/kv_keys.dart'; | 
					
						
							|  |  |  | import 'package:appflowy/startup/startup.dart'; | 
					
						
							| 
									
										
										
										
											2024-03-21 11:02:03 +07:00
										 |  |  | import 'package:collection/collection.dart'; | 
					
						
							| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef FeatureFlagMap = Map<FeatureFlag, bool>; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-03 08:36:12 +07:00
										 |  |  | /// The [FeatureFlag] is used to control the front-end features of the app.
 | 
					
						
							|  |  |  | ///
 | 
					
						
							|  |  |  | /// For example, if your feature is still under development,
 | 
					
						
							|  |  |  | ///   you can set the value to `false` to hide the feature.
 | 
					
						
							|  |  |  | enum FeatureFlag { | 
					
						
							|  |  |  |   // used to control the visibility of the collaborative workspace feature
 | 
					
						
							|  |  |  |   // if it's on, you can see the workspace list and the workspace settings
 | 
					
						
							|  |  |  |   // in the top-left corner of the app
 | 
					
						
							|  |  |  |   collaborativeWorkspace, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // used to control the visibility of the members settings
 | 
					
						
							|  |  |  |   // if it's on, you can see the members settings in the settings page
 | 
					
						
							| 
									
										
										
										
											2024-03-21 11:02:03 +07:00
										 |  |  |   membersSettings, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-21 12:26:48 +07:00
										 |  |  |   // used to control the sync feature of the document
 | 
					
						
							|  |  |  |   // if it's on, the document will be synced the events from server in real-time
 | 
					
						
							|  |  |  |   syncDocument, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-29 17:37:02 +08:00
										 |  |  |   // used to control the sync feature of the database
 | 
					
						
							|  |  |  |   // if it's on, the collaborators will show in the database
 | 
					
						
							|  |  |  |   syncDatabase, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-23 15:46:57 +02:00
										 |  |  |   // used for the search feature
 | 
					
						
							|  |  |  |   search, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-12 17:08:55 +02:00
										 |  |  |   // used for controlling whether to show plan+billing options in settings
 | 
					
						
							|  |  |  |   planBilling, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-21 11:02:03 +07:00
										 |  |  |   // used for ignore the conflicted feature flag
 | 
					
						
							|  |  |  |   unknown; | 
					
						
							| 
									
										
										
										
											2024-03-03 08:36:12 +07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  |   static Future<void> initialize() async { | 
					
						
							|  |  |  |     final values = await getIt<KeyValueStorage>().getWithFormat<FeatureFlagMap>( | 
					
						
							|  |  |  |           KVKeys.featureFlag, | 
					
						
							|  |  |  |           (value) => Map.from(jsonDecode(value)).map( | 
					
						
							| 
									
										
										
										
											2024-03-21 11:02:03 +07:00
										 |  |  |             (key, value) { | 
					
						
							|  |  |  |               final k = FeatureFlag.values.firstWhereOrNull( | 
					
						
							|  |  |  |                     (e) => e.name == key, | 
					
						
							|  |  |  |                   ) ?? | 
					
						
							|  |  |  |                   FeatureFlag.unknown; | 
					
						
							|  |  |  |               return MapEntry(k, value as bool); | 
					
						
							|  |  |  |             }, | 
					
						
							| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  |           ), | 
					
						
							|  |  |  |         ) ?? | 
					
						
							|  |  |  |         {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _values = { | 
					
						
							|  |  |  |       ...{for (final flag in FeatureFlag.values) flag: false}, | 
					
						
							|  |  |  |       ...values, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static UnmodifiableMapView<FeatureFlag, bool> get data => | 
					
						
							|  |  |  |       UnmodifiableMapView(_values); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<void> turnOn() async { | 
					
						
							|  |  |  |     await update(true); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<void> turnOff() async { | 
					
						
							|  |  |  |     await update(false); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Future<void> update(bool value) async { | 
					
						
							|  |  |  |     _values[this] = value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await getIt<KeyValueStorage>().set( | 
					
						
							|  |  |  |       KVKeys.featureFlag, | 
					
						
							|  |  |  |       jsonEncode( | 
					
						
							|  |  |  |         _values.map((key, value) => MapEntry(key.name, value)), | 
					
						
							|  |  |  |       ), | 
					
						
							|  |  |  |     ); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static Future<void> clear() async { | 
					
						
							|  |  |  |     _values = {}; | 
					
						
							|  |  |  |     await getIt<KeyValueStorage>().remove(KVKeys.featureFlag); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-03 08:36:12 +07:00
										 |  |  |   bool get isOn { | 
					
						
							| 
									
										
										
										
											2024-04-01 09:07:38 +08:00
										 |  |  |     if ([ | 
					
						
							| 
									
										
										
										
											2024-06-14 14:42:20 +08:00
										 |  |  |       FeatureFlag.planBilling, | 
					
						
							| 
									
										
										
										
											2024-06-05 16:01:42 +08:00
										 |  |  |       // release this feature in version 0.5.9
 | 
					
						
							|  |  |  |       FeatureFlag.search, | 
					
						
							| 
									
										
										
										
											2024-04-29 11:41:09 +08:00
										 |  |  |       // release this feature in version 0.5.6
 | 
					
						
							|  |  |  |       FeatureFlag.collaborativeWorkspace, | 
					
						
							|  |  |  |       FeatureFlag.membersSettings, | 
					
						
							| 
									
										
										
										
											2024-04-09 20:05:28 +08:00
										 |  |  |       // release this feature in version 0.5.4
 | 
					
						
							| 
									
										
										
										
											2024-04-01 09:07:38 +08:00
										 |  |  |       FeatureFlag.syncDatabase, | 
					
						
							|  |  |  |       FeatureFlag.syncDocument, | 
					
						
							|  |  |  |     ].contains(this)) { | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  |     if (_values.containsKey(this)) { | 
					
						
							|  |  |  |       return _values[this]!; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-03 08:36:12 +07:00
										 |  |  |     switch (this) { | 
					
						
							|  |  |  |       case FeatureFlag.collaborativeWorkspace: | 
					
						
							|  |  |  |       case FeatureFlag.membersSettings: | 
					
						
							| 
									
										
										
										
											2024-06-12 17:08:55 +02:00
										 |  |  |       case FeatureFlag.planBilling: | 
					
						
							| 
									
										
										
										
											2024-04-23 15:46:57 +02:00
										 |  |  |       case FeatureFlag.unknown: | 
					
						
							| 
									
										
										
										
											2024-03-25 22:08:52 +07:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2024-06-05 04:05:51 +02:00
										 |  |  |       case FeatureFlag.search: | 
					
						
							| 
									
										
										
										
											2024-03-21 12:26:48 +07:00
										 |  |  |       case FeatureFlag.syncDocument: | 
					
						
							| 
									
										
										
										
											2024-03-29 17:37:02 +08:00
										 |  |  |       case FeatureFlag.syncDatabase: | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2024-03-03 08:36:12 +07:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   String get description { | 
					
						
							|  |  |  |     switch (this) { | 
					
						
							|  |  |  |       case FeatureFlag.collaborativeWorkspace: | 
					
						
							|  |  |  |         return 'if it\'s on, you can see the workspace list and the workspace settings in the top-left corner of the app'; | 
					
						
							|  |  |  |       case FeatureFlag.membersSettings: | 
					
						
							|  |  |  |         return 'if it\'s on, you can see the members settings in the settings page'; | 
					
						
							| 
									
										
										
										
											2024-03-21 12:26:48 +07:00
										 |  |  |       case FeatureFlag.syncDocument: | 
					
						
							| 
									
										
										
										
											2024-03-26 10:21:49 +07:00
										 |  |  |         return 'if it\'s on, the document will be synced in real-time'; | 
					
						
							| 
									
										
										
										
											2024-03-29 17:37:02 +08:00
										 |  |  |       case FeatureFlag.syncDatabase: | 
					
						
							|  |  |  |         return 'if it\'s on, the collaborators will show in the database'; | 
					
						
							| 
									
										
										
										
											2024-04-23 15:46:57 +02:00
										 |  |  |       case FeatureFlag.search: | 
					
						
							|  |  |  |         return 'if it\'s on, the command palette and search button will be available'; | 
					
						
							| 
									
										
										
										
											2024-06-12 17:08:55 +02:00
										 |  |  |       case FeatureFlag.planBilling: | 
					
						
							|  |  |  |         return 'if it\'s on, plan and billing pages will be available in Settings'; | 
					
						
							| 
									
										
										
										
											2024-03-21 11:02:03 +07:00
										 |  |  |       case FeatureFlag.unknown: | 
					
						
							|  |  |  |         return ''; | 
					
						
							| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   String get key => 'appflowy_feature_flag_${toString()}'; | 
					
						
							| 
									
										
										
										
											2024-03-03 08:36:12 +07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2024-03-07 09:28:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | FeatureFlagMap _values = {}; |