supabase_task.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:appflowy/env/env.dart';
  4. import 'package:appflowy/workspace/application/settings/application_data_storage.dart';
  5. import 'package:flutter/foundation.dart';
  6. import 'package:supabase_flutter/supabase_flutter.dart';
  7. import 'package:url_protocol/url_protocol.dart';
  8. import 'package:hive_flutter/hive_flutter.dart';
  9. import 'package:path/path.dart' as p;
  10. import '../startup.dart';
  11. // ONLY supports in macOS and Windows now.
  12. //
  13. // If you need to update the schema, please update the following files:
  14. // - appflowy_flutter/macos/Runner/Info.plist (macOS)
  15. // - the callback url in Supabase dashboard
  16. const appflowyDeepLinkSchema = 'appflowy-flutter';
  17. const supabaseLoginCallback = '$appflowyDeepLinkSchema://login-callback';
  18. bool isSupabaseInitialized = false;
  19. const hiveBoxName = 'appflowy_supabase_authentication';
  20. // Used to store the session of the supabase in case of the user switch the different folder.
  21. Supabase? supabase;
  22. class InitSupabaseTask extends LaunchTask {
  23. @override
  24. Future<void> initialize(LaunchContext context) async {
  25. if (!isSupabaseEnabled) {
  26. return;
  27. }
  28. if (isSupabaseInitialized) {
  29. return;
  30. }
  31. // register deep link for Windows
  32. if (Platform.isWindows) {
  33. registerProtocolHandler(appflowyDeepLinkSchema);
  34. }
  35. supabase?.dispose();
  36. supabase = null;
  37. supabase = await Supabase.initialize(
  38. url: Env.supabaseUrl,
  39. anonKey: Env.supabaseAnonKey,
  40. debug: kDebugMode,
  41. localStorage: const SupabaseLocalStorage(),
  42. );
  43. }
  44. }
  45. /// customize the supabase auth storage
  46. ///
  47. /// We don't use the default one because it always save the session in the document directory.
  48. /// When we switch to the different folder, the session still exists.
  49. class SupabaseLocalStorage extends LocalStorage {
  50. const SupabaseLocalStorage()
  51. : super(
  52. initialize: _initialize,
  53. hasAccessToken: _hasAccessToken,
  54. accessToken: _accessToken,
  55. removePersistedSession: _removePersistedSession,
  56. persistSession: _persistSession,
  57. );
  58. static Future<void> _initialize() async {
  59. HiveCipher? encryptionCipher;
  60. // customize the path for Hive
  61. final path = await getIt<ApplicationDataStorage>().getPath();
  62. Hive.init(p.join(path, 'supabase_auth'));
  63. await Hive.openBox(
  64. hiveBoxName,
  65. encryptionCipher: encryptionCipher,
  66. );
  67. }
  68. static Future<bool> _hasAccessToken() {
  69. return Future.value(
  70. Hive.box(hiveBoxName).containsKey(
  71. supabasePersistSessionKey,
  72. ),
  73. );
  74. }
  75. static Future<String?> _accessToken() {
  76. return Future.value(
  77. Hive.box(hiveBoxName).get(supabasePersistSessionKey) as String?,
  78. );
  79. }
  80. static Future<void> _removePersistedSession() {
  81. return Hive.box(hiveBoxName).delete(supabasePersistSessionKey);
  82. }
  83. static Future<void> _persistSession(String persistSessionString) {
  84. return Hive.box(hiveBoxName).put(
  85. supabasePersistSessionKey,
  86. persistSessionString,
  87. );
  88. }
  89. }