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-07-16 13:23:07 +08:00
|
|
|
// used for space design
|
|
|
|
spaceDesign,
|
|
|
|
|
2024-10-21 10:34:30 +02:00
|
|
|
// used for the inline sub-page mention
|
|
|
|
inlineSubPageMention,
|
|
|
|
|
2025-05-20 16:37:09 +08:00
|
|
|
// used for the shared section
|
|
|
|
sharedSection,
|
|
|
|
|
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-07-26 12:03:29 +08:00
|
|
|
FeatureFlag.planBilling,
|
2024-07-16 13:23:07 +08:00
|
|
|
// release this feature in version 0.6.1
|
|
|
|
FeatureFlag.spaceDesign,
|
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,
|
2024-10-21 10:34:30 +02:00
|
|
|
FeatureFlag.inlineSubPageMention,
|
2025-06-05 09:51:00 +08:00
|
|
|
// release this feature in version 0.9.4
|
|
|
|
FeatureFlag.sharedSection,
|
2024-04-01 09:07:38 +08:00
|
|
|
].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) {
|
2024-07-22 09:43:48 +02:00
|
|
|
case FeatureFlag.planBilling:
|
2024-07-16 13:23:07 +08:00
|
|
|
case FeatureFlag.search:
|
|
|
|
case FeatureFlag.syncDocument:
|
|
|
|
case FeatureFlag.syncDatabase:
|
|
|
|
case FeatureFlag.spaceDesign:
|
2024-10-21 10:34:30 +02:00
|
|
|
case FeatureFlag.inlineSubPageMention:
|
2024-03-03 08:36:12 +07:00
|
|
|
case FeatureFlag.collaborativeWorkspace:
|
|
|
|
case FeatureFlag.membersSettings:
|
2025-05-21 18:03:39 +08:00
|
|
|
return true;
|
|
|
|
case FeatureFlag.sharedSection:
|
2024-04-23 15:46:57 +02:00
|
|
|
case FeatureFlag.unknown:
|
2024-03-25 22:08:52 +07:00
|
|
|
return false;
|
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-07-16 13:23:07 +08:00
|
|
|
case FeatureFlag.spaceDesign:
|
|
|
|
return 'if it\'s on, the space design feature will be available';
|
2024-10-21 10:34:30 +02:00
|
|
|
case FeatureFlag.inlineSubPageMention:
|
|
|
|
return 'if it\'s on, the inline sub-page mention feature will be available';
|
2025-05-20 16:37:09 +08:00
|
|
|
case FeatureFlag.sharedSection:
|
|
|
|
return 'if it\'s on, the shared section will be available';
|
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 = {};
|